Commit 5b253d89 authored by git-hulk's avatar git-hulk Committed by Michael Grunder
Browse files

Add support of RESP3 attribute type

Currently, Redis DEBUG PROTOCOL 'attrib' command will return an
attribute type, but hiredis doesn't support it yet. So it got the
protocol type error:

```
127.0.0.1:6379>  DEBUG PROTOCOL attrib
Error: Protocol error, got "|" as reply type byte
```

After apply this PR, it should reply:

```
127.0.0.1:6379> DEBUG PROTOCOL attrib
1# "key-popularity"
1# 1) "key:123"
   2) (integer) 90
```
parent 2706c3e1
......@@ -102,6 +102,7 @@ void freeReplyObject(void *reply) {
break; /* Nothing to free */
case REDIS_REPLY_ARRAY:
case REDIS_REPLY_MAP:
case REDIS_REPLY_ATTR:
case REDIS_REPLY_SET:
case REDIS_REPLY_PUSH:
if (r->element != NULL) {
......@@ -160,6 +161,7 @@ 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_ATTR ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_PUSH);
parent->element[task->idx] = r;
......@@ -192,6 +194,7 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
parent = task->parent->obj;
assert(parent->type == REDIS_REPLY_ARRAY ||
parent->type == REDIS_REPLY_MAP ||
parent->type == REDIS_REPLY_ATTR ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_PUSH);
parent->element[task->idx] = r;
......@@ -212,6 +215,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_ATTR ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_PUSH);
parent->element[task->idx] = r;
......@@ -249,6 +254,7 @@ static void *createDoubleObject(const redisReadTask *task, double value, char *s
parent = task->parent->obj;
assert(parent->type == REDIS_REPLY_ARRAY ||
parent->type == REDIS_REPLY_MAP ||
parent->type == REDIS_REPLY_ATTR ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_PUSH);
parent->element[task->idx] = r;
......@@ -267,6 +273,7 @@ static void *createNilObject(const redisReadTask *task) {
parent = task->parent->obj;
assert(parent->type == REDIS_REPLY_ARRAY ||
parent->type == REDIS_REPLY_MAP ||
parent->type == REDIS_REPLY_ATTR ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_PUSH);
parent->element[task->idx] = r;
......@@ -287,6 +294,7 @@ static void *createBoolObject(const redisReadTask *task, int bval) {
parent = task->parent->obj;
assert(parent->type == REDIS_REPLY_ARRAY ||
parent->type == REDIS_REPLY_MAP ||
parent->type == REDIS_REPLY_ATTR ||
parent->type == REDIS_REPLY_SET ||
parent->type == REDIS_REPLY_PUSH);
parent->element[task->idx] = r;
......
......@@ -250,6 +250,7 @@ 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_ATTR ||
prv->type == REDIS_REPLY_SET ||
prv->type == REDIS_REPLY_PUSH);
if (cur->idx == prv->elements-1) {
......@@ -534,7 +535,7 @@ static int processAggregateItem(redisReader *r) {
moveToNextTask(r);
} else {
if (cur->type == REDIS_REPLY_MAP) elements *= 2;
if (cur->type == REDIS_REPLY_MAP || cur->type == REDIS_REPLY_ATTR) elements *= 2;
if (r->fn && r->fn->createArray)
obj = r->fn->createArray(cur,elements);
......@@ -602,6 +603,9 @@ static int processItem(redisReader *r) {
case '%':
cur->type = REDIS_REPLY_MAP;
break;
case '|':
cur->type = REDIS_REPLY_ATTR;
break;
case '~':
cur->type = REDIS_REPLY_SET;
break;
......@@ -642,6 +646,7 @@ static int processItem(redisReader *r) {
return processBulkItem(r);
case REDIS_REPLY_ARRAY:
case REDIS_REPLY_MAP:
case REDIS_REPLY_ATTR:
case REDIS_REPLY_SET:
case REDIS_REPLY_PUSH:
return processAggregateItem(r);
......
......@@ -795,6 +795,26 @@ static void test_reply_reader(void) {
freeReplyObject(reply);
redisReaderFree(reader);
test("Can parse RESP3 attribute: ");
reader = redisReaderCreate();
redisReaderFeed(reader, "|2\r\n+foo\r\n:123\r\n+bar\r\n#t\r\n",26);
ret = redisReaderGetReply(reader,&reply);
test_cond(ret == REDIS_OK &&
((redisReply*)reply)->type == REDIS_REPLY_ATTR &&
((redisReply*)reply)->elements == 4 &&
((redisReply*)reply)->element[0]->type == REDIS_REPLY_STATUS &&
((redisReply*)reply)->element[0]->len == 3 &&
!strcmp(((redisReply*)reply)->element[0]->str,"foo") &&
((redisReply*)reply)->element[1]->type == REDIS_REPLY_INTEGER &&
((redisReply*)reply)->element[1]->integer == 123 &&
((redisReply*)reply)->element[2]->type == REDIS_REPLY_STATUS &&
((redisReply*)reply)->element[2]->len == 3 &&
!strcmp(((redisReply*)reply)->element[2]->str,"bar") &&
((redisReply*)reply)->element[3]->type == REDIS_REPLY_BOOL &&
((redisReply*)reply)->element[3]->integer);
freeReplyObject(reply);
redisReaderFree(reader);
test("Can parse RESP3 set: ");
reader = redisReaderCreate();
redisReaderFeed(reader, "~5\r\n+orange\r\n$5\r\napple\r\n#f\r\n:100\r\n:999\r\n",40);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment