diff options
author | git-hulk <hulk.website@gmail.com> | 2024-01-27 22:21:54 +0800 |
---|---|---|
committer | Michael Grunder <michael.grunder@gmail.com> | 2024-01-31 12:08:52 -0800 |
commit | 5b253d89c7cc9593723334e0a45077bd4008d3db (patch) | |
tree | 5538a775daf676538f02829e3d521ab39bc5fa77 | |
parent | 2706c3e16d57c9babd24bfd83ade2efcdb13a7b8 (diff) |
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
```
-rw-r--r-- | hiredis.c | 8 | ||||
-rw-r--r-- | read.c | 7 | ||||
-rw-r--r-- | test.c | 20 |
3 files changed, 34 insertions, 1 deletions
@@ -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); |