diff --git a/async.c b/async.c index 6990e86..68a656f 100644 --- a/async.c +++ b/async.c @@ -374,7 +374,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, /* Custom reply functions are not supported for pub/sub. This will fail * very hard when they are used... */ - if (reply->type == REDIS_REPLY_ARRAY) { + if (reply->type == REDIS_REPLY_ARRAY || reply->type == REDIS_REPLY_PUSH) { assert(reply->elements >= 2); assert(reply->element[0]->type == REDIS_REPLY_STRING); stype = reply->element[0]->str; diff --git a/hiredis.c b/hiredis.c index deb65a9..1c9e8ae 100644 --- a/hiredis.c +++ b/hiredis.c @@ -97,6 +97,7 @@ void freeReplyObject(void *reply) { case REDIS_REPLY_ARRAY: case REDIS_REPLY_MAP: case REDIS_REPLY_SET: + case REDIS_REPLY_PUSH: if (r->element != NULL) { for (j = 0; j < r->elements; j++) freeReplyObject(r->element[j]); @@ -155,7 +156,8 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len parent = task->parent->obj; assert(parent->type == REDIS_REPLY_ARRAY || parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET); + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); parent->element[task->idx] = r; } return r; @@ -201,7 +203,8 @@ static void *createIntegerObject(const redisReadTask *task, long long value) { parent = task->parent->obj; assert(parent->type == REDIS_REPLY_ARRAY || parent->type == REDIS_REPLY_MAP || - parent->type == REDIS_REPLY_SET); + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); parent->element[task->idx] = r; } return r; diff --git a/read.c b/read.c index 835eb65..4924014 100644 --- a/read.c +++ b/read.c @@ -250,7 +250,8 @@ static void moveToNextTask(redisReader *r) { prv = r->task[r->ridx-1]; assert(prv->type == REDIS_REPLY_ARRAY || prv->type == REDIS_REPLY_MAP || - prv->type == REDIS_REPLY_SET); + prv->type == REDIS_REPLY_SET || + prv->type == REDIS_REPLY_PUSH); if (cur->idx == prv->elements-1) { r->ridx--; } else { @@ -562,6 +563,9 @@ static int processItem(redisReader *r) { case '=': cur->type = REDIS_REPLY_VERB; break; + case '>': + cur->type = REDIS_REPLY_PUSH; + break; default: __redisReaderSetErrorProtocolByte(r,*p); return REDIS_ERR; @@ -587,6 +591,7 @@ static int processItem(redisReader *r) { case REDIS_REPLY_ARRAY: case REDIS_REPLY_MAP: case REDIS_REPLY_SET: + case REDIS_REPLY_PUSH: return processAggregateItem(r); default: assert(NULL); diff --git a/test.c b/test.c index 8e45e78..1d38caa 100644 --- a/test.c +++ b/test.c @@ -488,6 +488,21 @@ static void test_reply_reader(void) { !memcmp(((redisReply*)reply)->str,"LOLWUT", 6)); freeReplyObject(reply); redisReaderFree(reader); + + /* RESP3 push messages (Github issue #815) */ + test("Can parse RESP3 push messages: "); + reader = redisReaderCreate(); + redisReaderFeed(reader,(char*)">2\r\n$6\r\nLOLWUT\r\n:42\r\n",21); + ret = redisReaderGetReply(reader,&reply); + test_cond(ret == REDIS_OK && + ((redisReply*)reply)->type == REDIS_REPLY_PUSH && + ((redisReply*)reply)->elements == 2 && + ((redisReply*)reply)->element[0]->type == REDIS_REPLY_STRING && + !memcmp(((redisReply*)reply)->element[0]->str,"LOLWUT",6) && + ((redisReply*)reply)->element[1]->type == REDIS_REPLY_INTEGER && + ((redisReply*)reply)->element[1]->integer == 42); + freeReplyObject(reply); + redisReaderFree(reader); } static void test_free_null(void) {