+static void zrankCommand(redisClient *c) {
+ robj *o;
+ o = lookupKeyRead(c->db,c->argv[1]);
+ if (o == NULL) {
+ addReply(c,shared.nullbulk);
+ return;
+ }
+ if (o->type != REDIS_ZSET) {
+ addReply(c,shared.wrongtypeerr);
+ return;
+ }
+
+ zset *zs = o->ptr;
+ zskiplist *zsl = zs->zsl;
+ dictEntry *de = dictFind(zs->dict,c->argv[2]);
+ if (!de) {
+ addReply(c,shared.nullbulk);
+ return;
+ }
+
+ double *score = dictGetEntryVal(de);
+ zskiplistNode *x;
+ unsigned long rank = 0;
+ int i;
+
+ x = zsl->header;
+ for (i = zsl->level-1; i >= 0; i--) {
+ while (x->forward[i] &&
+ (x->forward[i]->score < *score ||
+ (x->forward[i]->score == *score &&
+ compareStringObjects(x->forward[i]->obj,c->argv[2]) < 0))) {
+ rank += x->span[i];
+ x = x->forward[i];
+ }
+
+ if (x->forward[i] && compareStringObjects(x->forward[i]->obj,c->argv[2]) == 0) {
+ addReplyLong(c, rank);
+ return;
+ }
+ }
+
+ addReply(c,shared.nullbulk);
+}
+