Skip to content

Commit 5b253d8

Browse files
git-hulkmichael-grunder
authored andcommitted
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 ```
1 parent 2706c3e commit 5b253d8

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

hiredis.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ void freeReplyObject(void *reply) {
102102
break; /* Nothing to free */
103103
case REDIS_REPLY_ARRAY:
104104
case REDIS_REPLY_MAP:
105+
case REDIS_REPLY_ATTR:
105106
case REDIS_REPLY_SET:
106107
case REDIS_REPLY_PUSH:
107108
if (r->element != NULL) {
@@ -160,6 +161,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
160161
parent = task->parent->obj;
161162
assert(parent->type == REDIS_REPLY_ARRAY ||
162163
parent->type == REDIS_REPLY_MAP ||
164+
parent->type == REDIS_REPLY_ATTR ||
163165
parent->type == REDIS_REPLY_SET ||
164166
parent->type == REDIS_REPLY_PUSH);
165167
parent->element[task->idx] = r;
@@ -192,6 +194,7 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
192194
parent = task->parent->obj;
193195
assert(parent->type == REDIS_REPLY_ARRAY ||
194196
parent->type == REDIS_REPLY_MAP ||
197+
parent->type == REDIS_REPLY_ATTR ||
195198
parent->type == REDIS_REPLY_SET ||
196199
parent->type == REDIS_REPLY_PUSH);
197200
parent->element[task->idx] = r;
@@ -212,6 +215,8 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
212215
parent = task->parent->obj;
213216
assert(parent->type == REDIS_REPLY_ARRAY ||
214217
parent->type == REDIS_REPLY_MAP ||
218+
parent->type == REDIS_REPLY_ATTR ||
219+
parent->type == REDIS_REPLY_SET ||
215220
parent->type == REDIS_REPLY_SET ||
216221
parent->type == REDIS_REPLY_PUSH);
217222
parent->element[task->idx] = r;
@@ -249,6 +254,7 @@ static void *createDoubleObject(const redisReadTask *task, double value, char *s
249254
parent = task->parent->obj;
250255
assert(parent->type == REDIS_REPLY_ARRAY ||
251256
parent->type == REDIS_REPLY_MAP ||
257+
parent->type == REDIS_REPLY_ATTR ||
252258
parent->type == REDIS_REPLY_SET ||
253259
parent->type == REDIS_REPLY_PUSH);
254260
parent->element[task->idx] = r;
@@ -267,6 +273,7 @@ static void *createNilObject(const redisReadTask *task) {
267273
parent = task->parent->obj;
268274
assert(parent->type == REDIS_REPLY_ARRAY ||
269275
parent->type == REDIS_REPLY_MAP ||
276+
parent->type == REDIS_REPLY_ATTR ||
270277
parent->type == REDIS_REPLY_SET ||
271278
parent->type == REDIS_REPLY_PUSH);
272279
parent->element[task->idx] = r;
@@ -287,6 +294,7 @@ static void *createBoolObject(const redisReadTask *task, int bval) {
287294
parent = task->parent->obj;
288295
assert(parent->type == REDIS_REPLY_ARRAY ||
289296
parent->type == REDIS_REPLY_MAP ||
297+
parent->type == REDIS_REPLY_ATTR ||
290298
parent->type == REDIS_REPLY_SET ||
291299
parent->type == REDIS_REPLY_PUSH);
292300
parent->element[task->idx] = r;

read.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ static void moveToNextTask(redisReader *r) {
250250
prv = r->task[r->ridx-1];
251251
assert(prv->type == REDIS_REPLY_ARRAY ||
252252
prv->type == REDIS_REPLY_MAP ||
253+
prv->type == REDIS_REPLY_ATTR ||
253254
prv->type == REDIS_REPLY_SET ||
254255
prv->type == REDIS_REPLY_PUSH);
255256
if (cur->idx == prv->elements-1) {
@@ -534,7 +535,7 @@ static int processAggregateItem(redisReader *r) {
534535

535536
moveToNextTask(r);
536537
} else {
537-
if (cur->type == REDIS_REPLY_MAP) elements *= 2;
538+
if (cur->type == REDIS_REPLY_MAP || cur->type == REDIS_REPLY_ATTR) elements *= 2;
538539

539540
if (r->fn && r->fn->createArray)
540541
obj = r->fn->createArray(cur,elements);
@@ -602,6 +603,9 @@ static int processItem(redisReader *r) {
602603
case '%':
603604
cur->type = REDIS_REPLY_MAP;
604605
break;
606+
case '|':
607+
cur->type = REDIS_REPLY_ATTR;
608+
break;
605609
case '~':
606610
cur->type = REDIS_REPLY_SET;
607611
break;
@@ -642,6 +646,7 @@ static int processItem(redisReader *r) {
642646
return processBulkItem(r);
643647
case REDIS_REPLY_ARRAY:
644648
case REDIS_REPLY_MAP:
649+
case REDIS_REPLY_ATTR:
645650
case REDIS_REPLY_SET:
646651
case REDIS_REPLY_PUSH:
647652
return processAggregateItem(r);

test.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,26 @@ static void test_reply_reader(void) {
795795
freeReplyObject(reply);
796796
redisReaderFree(reader);
797797

798+
test("Can parse RESP3 attribute: ");
799+
reader = redisReaderCreate();
800+
redisReaderFeed(reader, "|2\r\n+foo\r\n:123\r\n+bar\r\n#t\r\n",26);
801+
ret = redisReaderGetReply(reader,&reply);
802+
test_cond(ret == REDIS_OK &&
803+
((redisReply*)reply)->type == REDIS_REPLY_ATTR &&
804+
((redisReply*)reply)->elements == 4 &&
805+
((redisReply*)reply)->element[0]->type == REDIS_REPLY_STATUS &&
806+
((redisReply*)reply)->element[0]->len == 3 &&
807+
!strcmp(((redisReply*)reply)->element[0]->str,"foo") &&
808+
((redisReply*)reply)->element[1]->type == REDIS_REPLY_INTEGER &&
809+
((redisReply*)reply)->element[1]->integer == 123 &&
810+
((redisReply*)reply)->element[2]->type == REDIS_REPLY_STATUS &&
811+
((redisReply*)reply)->element[2]->len == 3 &&
812+
!strcmp(((redisReply*)reply)->element[2]->str,"bar") &&
813+
((redisReply*)reply)->element[3]->type == REDIS_REPLY_BOOL &&
814+
((redisReply*)reply)->element[3]->integer);
815+
freeReplyObject(reply);
816+
redisReaderFree(reader);
817+
798818
test("Can parse RESP3 set: ");
799819
reader = redisReaderCreate();
800820
redisReaderFeed(reader, "~5\r\n+orange\r\n$5\r\napple\r\n#f\r\n:100\r\n:999\r\n",40);

0 commit comments

Comments
 (0)