1#![allow(clippy::too_many_lines)]
18#![allow(clippy::match_same_arms)]
19
20use crate::msg::MsgType;
21
22#[derive(Copy, Clone, Debug, Eq, PartialEq)]
24pub enum CommandClass {
25 Argz,
27 Arg0,
29 Arg1,
31 Arg2,
33 Arg3,
35 ArgN,
37 ArgX,
39 ArgKvX,
41 ArgUpto1,
43 ArgEval,
46}
47
48impl CommandClass {
49 #[must_use]
51 pub fn is_argz(self) -> bool {
52 matches!(self, Self::Argz)
53 }
54
55 #[must_use]
57 pub fn is_argx(self) -> bool {
58 matches!(self, Self::ArgX)
59 }
60
61 #[must_use]
63 pub fn is_argkvx(self) -> bool {
64 matches!(self, Self::ArgKvX)
65 }
66
67 #[must_use]
69 pub fn is_argeval(self) -> bool {
70 matches!(self, Self::ArgEval)
71 }
72}
73
74#[must_use]
90pub fn classify(ty: MsgType) -> CommandClass {
91 use MsgType as M;
92 match ty {
93 M::ReqRedisPing | M::ReqRedisQuit | M::ReqRedisScriptFlush | M::ReqRedisScriptKill => {
95 CommandClass::Argz
96 }
97
98 M::ReqRedisPersist
100 | M::ReqRedisPttl
101 | M::ReqRedisTtl
102 | M::ReqRedisType
103 | M::ReqRedisDump
104 | M::ReqRedisDecr
105 | M::ReqRedisGet
106 | M::ReqRedisIncr
107 | M::ReqRedisStrlen
108 | M::ReqRedisHgetall
109 | M::ReqRedisHkeys
110 | M::ReqRedisHlen
111 | M::ReqRedisHvals
112 | M::ReqRedisLlen
113 | M::ReqRedisLpop
114 | M::ReqRedisRpop
115 | M::ReqRedisScard
116 | M::ReqRedisSmembers
117 | M::ReqRedisSrandmember
118 | M::ReqRedisZcard
119 | M::ReqRedisKeys
120 | M::ReqRedisPfcount => CommandClass::Arg0,
121
122 M::ReqRedisExpire
124 | M::ReqRedisExpireat
125 | M::ReqRedisPexpire
126 | M::ReqRedisPexpireat
127 | M::ReqRedisAppend
128 | M::ReqRedisDecrby
129 | M::ReqRedisGetbit
130 | M::ReqRedisGetset
131 | M::ReqRedisIncrby
132 | M::ReqRedisIncrbyfloat
133 | M::ReqRedisSetnx
134 | M::ReqRedisHexists
135 | M::ReqRedisHget
136 | M::ReqRedisHstrlen
137 | M::ReqRedisLindex
138 | M::ReqRedisLpushx
139 | M::ReqRedisRpoplpush
140 | M::ReqRedisRpushx
141 | M::ReqRedisSismember
142 | M::ReqRedisZrank
143 | M::ReqRedisZrevrank
144 | M::ReqRedisZscore
145 | M::ReqRedisSlaveof
146 | M::ReqRedisConfig
147 | M::ReqRedisScriptLoad
148 | M::ReqRedisScriptExists => CommandClass::Arg1,
149
150 M::ReqRedisGetrange
152 | M::ReqRedisPsetex
153 | M::ReqRedisSetbit
154 | M::ReqRedisSetex
155 | M::ReqRedisSetrange
156 | M::ReqRedisHincrby
157 | M::ReqRedisHincrbyfloat
158 | M::ReqRedisHsetnx
159 | M::ReqRedisLrange
160 | M::ReqRedisLrem
161 | M::ReqRedisLset
162 | M::ReqRedisLtrim
163 | M::ReqRedisSmove
164 | M::ReqRedisZcount
165 | M::ReqRedisZincrby
166 | M::ReqRedisZlexcount
167 | M::ReqRedisZremrangebylex
168 | M::ReqRedisZremrangebyrank
169 | M::ReqRedisZremrangebyscore
170 | M::ReqRedisRestore => CommandClass::Arg2,
171
172 M::ReqRedisLinsert => CommandClass::Arg3,
174
175 M::ReqRedisSort
177 | M::ReqRedisBitcount
178 | M::ReqRedisBitpos
179 | M::ReqRedisSet
180 | M::ReqRedisScan
181 | M::ReqRedisHdel
182 | M::ReqRedisHmget
183 | M::ReqRedisHmset
184 | M::ReqRedisHscan
185 | M::ReqRedisHset
186 | M::ReqRedisLpush
187 | M::ReqRedisRpush
188 | M::ReqRedisSadd
189 | M::ReqRedisSdiff
190 | M::ReqRedisSdiffstore
191 | M::ReqRedisSinter
192 | M::ReqRedisSinterstore
193 | M::ReqRedisSrem
194 | M::ReqRedisSunion
195 | M::ReqRedisSunionstore
196 | M::ReqRedisSscan
197 | M::ReqRedisSpop
198 | M::ReqRedisZadd
199 | M::ReqRedisZinterstore
200 | M::ReqRedisZrange
201 | M::ReqRedisZrangebyscore
202 | M::ReqRedisZrem
203 | M::ReqRedisZrevrange
204 | M::ReqRedisZrangebylex
205 | M::ReqRedisZrevrangebylex
206 | M::ReqRedisZrevrangebyscore
207 | M::ReqRedisZunionstore
208 | M::ReqRedisZscan
209 | M::ReqRedisPfadd
210 | M::ReqRedisGeoadd
211 | M::ReqRedisGeoradius
212 | M::ReqRedisGeodist
213 | M::ReqRedisGeohash
214 | M::ReqRedisGeopos
215 | M::ReqRedisGeoradiusbymember
216 | M::ReqRedisJsonset
217 | M::ReqRedisJsonget
218 | M::ReqRedisJsondel
219 | M::ReqRedisJsontype
220 | M::ReqRedisJsonmget
221 | M::ReqRedisJsonarrappend
222 | M::ReqRedisJsonarrinsert
223 | M::ReqRedisJsonarrlen
224 | M::ReqRedisJsonobjkeys
225 | M::ReqRedisJsonobjlen
226 | M::ReqRedisUnlink => CommandClass::ArgN,
227
228 M::ReqRedisMget | M::ReqRedisDel | M::ReqRedisExists => CommandClass::ArgX,
230
231 M::ReqRedisMset => CommandClass::ArgKvX,
233
234 M::ReqRedisInfo => CommandClass::ArgUpto1,
236
237 M::ReqRedisEval | M::ReqRedisEvalsha => CommandClass::ArgEval,
239
240 M::ReqRedisFtCreate | M::ReqRedisFtSearch | M::ReqRedisFtDropindex | M::ReqRedisFtRegex => {
246 CommandClass::ArgN
247 }
248 M::ReqRedisFtInfo => CommandClass::Arg0,
249 M::ReqRedisFtList => CommandClass::Argz,
250 M::ReqRedisFtSugadd | M::ReqRedisFtSugget => CommandClass::ArgN,
256 M::ReqRedisFtSugdel => CommandClass::Arg1,
257 M::ReqRedisFtSuglen => CommandClass::Arg0,
258 M::ReqRedisFtUnknown => CommandClass::ArgN,
264
265 _ => CommandClass::Arg0,
266 }
267}
268
269#[must_use]
281pub fn is_redis_error(ty: MsgType) -> bool {
282 use MsgType as M;
283 matches!(
284 ty,
285 M::RspRedisError
286 | M::RspRedisErrorErr
287 | M::RspRedisErrorOom
288 | M::RspRedisErrorBusy
289 | M::RspRedisErrorNoauth
290 | M::RspRedisErrorLoading
291 | M::RspRedisErrorBusykey
292 | M::RspRedisErrorMisconf
293 | M::RspRedisErrorNoscript
294 | M::RspRedisErrorReadonly
295 | M::RspRedisErrorWrongtype
296 | M::RspRedisErrorExecabort
297 | M::RspRedisErrorMasterdown
298 | M::RspRedisErrorNoreplicas
299 )
300}
301
302#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
305pub struct CommandTraits {
306 pub is_read: bool,
308 pub quit: bool,
310 pub routing: RoutingOverride,
312}
313
314#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
316pub enum RoutingOverride {
317 #[default]
319 None,
320 LocalNodeOnly,
322 TokenOwnerLocalRackOnly,
324 AllNodesAllRacksAllDcs,
326}
327
328#[must_use]
344pub fn lookup(keyword: &[u8]) -> Option<(MsgType, CommandTraits)> {
345 if keyword.is_empty() || keyword.len() > 32 {
346 return None;
347 }
348 let mut buf = [0u8; 32];
349 for (i, &b) in keyword.iter().enumerate() {
350 buf[i] = b.to_ascii_lowercase();
351 }
352 let key = &buf[..keyword.len()];
353 if key.starts_with(b"ft.")
361 && !matches!(
362 key,
363 b"ft.create"
364 | b"ft.search"
365 | b"ft.info"
366 | b"ft.list"
367 | b"ft._list"
368 | b"ft.dropindex"
369 | b"ft.regex"
370 | b"ft.sugadd"
371 | b"ft.sugget"
372 | b"ft.sugdel"
373 | b"ft.suglen"
374 )
375 {
376 return Some((
377 MsgType::ReqRedisFtUnknown,
378 CommandTraits {
379 is_read: true,
380 quit: false,
381 routing: RoutingOverride::LocalNodeOnly,
382 },
383 ));
384 }
385 let (ty, is_read, quit, routing) = match key {
386 b"get" => (MsgType::ReqRedisGet, true, false, RoutingOverride::None),
388 b"set" => (MsgType::ReqRedisSet, false, false, RoutingOverride::None),
389 b"ttl" => (MsgType::ReqRedisTtl, false, false, RoutingOverride::None),
390 b"del" => (MsgType::ReqRedisDel, false, false, RoutingOverride::None),
391 b"pttl" => (MsgType::ReqRedisPttl, true, false, RoutingOverride::None),
393 b"decr" => (MsgType::ReqRedisDecr, false, false, RoutingOverride::None),
394 b"dump" => (MsgType::ReqRedisDump, true, false, RoutingOverride::None),
395 b"hdel" => (MsgType::ReqRedisHdel, false, false, RoutingOverride::None),
396 b"hget" => (MsgType::ReqRedisHget, true, false, RoutingOverride::None),
397 b"hlen" => (MsgType::ReqRedisHlen, true, false, RoutingOverride::None),
398 b"hset" => (MsgType::ReqRedisHset, false, false, RoutingOverride::None),
399 b"incr" => (MsgType::ReqRedisIncr, false, false, RoutingOverride::None),
400 b"keys" => (
401 MsgType::ReqRedisKeys,
402 true,
403 false,
404 RoutingOverride::LocalNodeOnly,
405 ),
406 b"info" => (
407 MsgType::ReqRedisInfo,
408 true,
409 false,
410 RoutingOverride::LocalNodeOnly,
411 ),
412 b"llen" => (MsgType::ReqRedisLlen, true, false, RoutingOverride::None),
413 b"lpop" => (MsgType::ReqRedisLpop, false, false, RoutingOverride::None),
414 b"lrem" => (MsgType::ReqRedisLrem, false, false, RoutingOverride::None),
415 b"lset" => (MsgType::ReqRedisLset, false, false, RoutingOverride::None),
416 b"mget" => (MsgType::ReqRedisMget, true, false, RoutingOverride::None),
417 b"mset" => (MsgType::ReqRedisMset, false, false, RoutingOverride::None),
418 b"ping" => (
419 MsgType::ReqRedisPing,
420 true,
421 false,
422 RoutingOverride::LocalNodeOnly,
423 ),
424 b"rpop" => (MsgType::ReqRedisRpop, false, false, RoutingOverride::None),
425 b"sadd" => (MsgType::ReqRedisSadd, false, false, RoutingOverride::None),
426 b"scan" => (
427 MsgType::ReqRedisScan,
428 true,
429 false,
430 RoutingOverride::LocalNodeOnly,
431 ),
432 b"spop" => (MsgType::ReqRedisSpop, false, false, RoutingOverride::None),
433 b"srem" => (MsgType::ReqRedisSrem, false, false, RoutingOverride::None),
434 b"type" => (MsgType::ReqRedisType, true, false, RoutingOverride::None),
435 b"zadd" => (MsgType::ReqRedisZadd, false, false, RoutingOverride::None),
436 b"zrem" => (MsgType::ReqRedisZrem, false, false, RoutingOverride::None),
437 b"eval" => (MsgType::ReqRedisEval, false, false, RoutingOverride::None),
438 b"sort" => (MsgType::ReqRedisSort, true, false, RoutingOverride::None),
439 b"quit" => (MsgType::ReqRedisQuit, false, true, RoutingOverride::None),
440 b"load" => (
441 MsgType::ReqRedisScriptLoad,
442 false,
443 false,
444 RoutingOverride::AllNodesAllRacksAllDcs,
445 ),
446 b"kill" => (
447 MsgType::ReqRedisScriptKill,
448 false,
449 false,
450 RoutingOverride::AllNodesAllRacksAllDcs,
451 ),
452 b"hkeys" => (
454 MsgType::ReqRedisHkeys,
455 true,
456 false,
457 RoutingOverride::TokenOwnerLocalRackOnly,
458 ),
459 b"hmget" => (MsgType::ReqRedisHmget, true, false, RoutingOverride::None),
460 b"hmset" => (MsgType::ReqRedisHmset, false, false, RoutingOverride::None),
461 b"hvals" => (
462 MsgType::ReqRedisHvals,
463 true,
464 false,
465 RoutingOverride::TokenOwnerLocalRackOnly,
466 ),
467 b"hscan" => (
468 MsgType::ReqRedisHscan,
469 true,
470 false,
471 RoutingOverride::TokenOwnerLocalRackOnly,
472 ),
473 b"lpush" => (MsgType::ReqRedisLpush, false, false, RoutingOverride::None),
474 b"ltrim" => (MsgType::ReqRedisLtrim, false, false, RoutingOverride::None),
475 b"rpush" => (MsgType::ReqRedisRpush, false, false, RoutingOverride::None),
476 b"scard" => (MsgType::ReqRedisScard, true, false, RoutingOverride::None),
477 b"sdiff" => (MsgType::ReqRedisSdiff, true, false, RoutingOverride::None),
478 b"setex" => (MsgType::ReqRedisSetex, false, false, RoutingOverride::None),
479 b"setnx" => (MsgType::ReqRedisSetnx, false, false, RoutingOverride::None),
480 b"smove" => (MsgType::ReqRedisSmove, false, false, RoutingOverride::None),
481 b"sscan" => (
482 MsgType::ReqRedisSscan,
483 true,
484 false,
485 RoutingOverride::TokenOwnerLocalRackOnly,
486 ),
487 b"zcard" => (MsgType::ReqRedisZcard, true, false, RoutingOverride::None),
488 b"zrank" => (MsgType::ReqRedisZrank, true, false, RoutingOverride::None),
489 b"zscan" => (
490 MsgType::ReqRedisZscan,
491 true,
492 false,
493 RoutingOverride::TokenOwnerLocalRackOnly,
494 ),
495 b"pfadd" => (MsgType::ReqRedisPfadd, false, false, RoutingOverride::None),
496 b"flush" => (
497 MsgType::ReqRedisScriptFlush,
498 false,
499 false,
500 RoutingOverride::AllNodesAllRacksAllDcs,
501 ),
502 b"append" => (MsgType::ReqRedisAppend, false, false, RoutingOverride::None),
504 b"decrby" => (MsgType::ReqRedisDecrby, false, false, RoutingOverride::None),
505 b"exists" => (MsgType::ReqRedisExists, true, false, RoutingOverride::None),
506 b"expire" => (MsgType::ReqRedisExpire, false, false, RoutingOverride::None),
507 b"getbit" => (MsgType::ReqRedisGetbit, true, false, RoutingOverride::None),
508 b"getset" => (MsgType::ReqRedisGetset, false, false, RoutingOverride::None),
509 b"psetex" => (MsgType::ReqRedisPsetex, false, false, RoutingOverride::None),
510 b"hsetnx" => (MsgType::ReqRedisHsetnx, false, false, RoutingOverride::None),
511 b"incrby" => (MsgType::ReqRedisIncrby, false, false, RoutingOverride::None),
512 b"lindex" => (MsgType::ReqRedisLindex, true, false, RoutingOverride::None),
513 b"lpushx" => (MsgType::ReqRedisLpushx, false, false, RoutingOverride::None),
514 b"lrange" => (MsgType::ReqRedisLrange, true, false, RoutingOverride::None),
515 b"rpushx" => (MsgType::ReqRedisRpushx, false, false, RoutingOverride::None),
516 b"setbit" => (MsgType::ReqRedisSetbit, false, false, RoutingOverride::None),
517 b"sinter" => (MsgType::ReqRedisSinter, true, false, RoutingOverride::None),
518 b"strlen" => (MsgType::ReqRedisStrlen, true, false, RoutingOverride::None),
519 b"sunion" => (MsgType::ReqRedisSunion, true, false, RoutingOverride::None),
520 b"zcount" => (MsgType::ReqRedisZcount, true, false, RoutingOverride::None),
521 b"zrange" => (MsgType::ReqRedisZrange, true, false, RoutingOverride::None),
522 b"zscore" => (MsgType::ReqRedisZscore, true, false, RoutingOverride::None),
523 b"config" => (
524 MsgType::ReqRedisConfig,
525 true,
526 false,
527 RoutingOverride::LocalNodeOnly,
528 ),
529 b"geoadd" => (MsgType::ReqRedisGeoadd, false, false, RoutingOverride::None),
530 b"geopos" => (MsgType::ReqRedisGeopos, true, false, RoutingOverride::None),
531 b"unlink" => (MsgType::ReqRedisUnlink, false, false, RoutingOverride::None),
532 b"script" => (MsgType::ReqRedisScript, false, false, RoutingOverride::None),
533 b"bitpos" => (MsgType::ReqRedisBitpos, true, false, RoutingOverride::None),
534 b"persist" => (
536 MsgType::ReqRedisPersist,
537 false,
538 false,
539 RoutingOverride::None,
540 ),
541 b"pexpire" => (
542 MsgType::ReqRedisPexpire,
543 false,
544 false,
545 RoutingOverride::None,
546 ),
547 b"hexists" => (MsgType::ReqRedisHexists, true, false, RoutingOverride::None),
548 b"hgetall" => (
549 MsgType::ReqRedisHgetall,
550 true,
551 false,
552 RoutingOverride::TokenOwnerLocalRackOnly,
553 ),
554 b"hincrby" => (
555 MsgType::ReqRedisHincrby,
556 false,
557 false,
558 RoutingOverride::None,
559 ),
560 b"linsert" => (
561 MsgType::ReqRedisLinsert,
562 false,
563 false,
564 RoutingOverride::None,
565 ),
566 b"zincrby" => (
567 MsgType::ReqRedisZincrby,
568 false,
569 false,
570 RoutingOverride::None,
571 ),
572 b"evalsha" => (
573 MsgType::ReqRedisEvalsha,
574 false,
575 false,
576 RoutingOverride::None,
577 ),
578 b"restore" => (
579 MsgType::ReqRedisRestore,
580 false,
581 false,
582 RoutingOverride::None,
583 ),
584 b"slaveof" => (
585 MsgType::ReqRedisSlaveof,
586 false,
587 false,
588 RoutingOverride::LocalNodeOnly,
589 ),
590 b"pfcount" => (
591 MsgType::ReqRedisPfcount,
592 false,
593 false,
594 RoutingOverride::None,
595 ),
596 b"geohash" => (MsgType::ReqRedisGeohash, true, false, RoutingOverride::None),
597 b"geodist" => (MsgType::ReqRedisGeodist, true, false, RoutingOverride::None),
598 b"hstrlen" => (MsgType::ReqRedisHstrlen, true, false, RoutingOverride::None),
599 b"expireat" => (
601 MsgType::ReqRedisExpireat,
602 false,
603 false,
604 RoutingOverride::None,
605 ),
606 b"bitcount" => (
607 MsgType::ReqRedisBitcount,
608 true,
609 false,
610 RoutingOverride::None,
611 ),
612 b"getrange" => (
613 MsgType::ReqRedisGetrange,
614 true,
615 false,
616 RoutingOverride::None,
617 ),
618 b"setrange" => (
619 MsgType::ReqRedisSetrange,
620 false,
621 false,
622 RoutingOverride::None,
623 ),
624 b"smembers" => (
625 MsgType::ReqRedisSmembers,
626 true,
627 false,
628 RoutingOverride::None,
629 ),
630 b"zrevrank" => (
631 MsgType::ReqRedisZrevrank,
632 true,
633 false,
634 RoutingOverride::None,
635 ),
636 b"json.set" => (
637 MsgType::ReqRedisJsonset,
638 false,
639 false,
640 RoutingOverride::None,
641 ),
642 b"json.get" => (MsgType::ReqRedisJsonget, true, false, RoutingOverride::None),
643 b"json.del" => (
644 MsgType::ReqRedisJsondel,
645 false,
646 false,
647 RoutingOverride::None,
648 ),
649 b"pexpireat" => (
651 MsgType::ReqRedisPexpireat,
652 false,
653 false,
654 RoutingOverride::None,
655 ),
656 b"rpoplpush" => (
657 MsgType::ReqRedisRpoplpush,
658 false,
659 false,
660 RoutingOverride::None,
661 ),
662 b"sismember" => (
663 MsgType::ReqRedisSismember,
664 true,
665 false,
666 RoutingOverride::None,
667 ),
668 b"zlexcount" => (
669 MsgType::ReqRedisZlexcount,
670 true,
671 false,
672 RoutingOverride::None,
673 ),
674 b"zrevrange" => (
675 MsgType::ReqRedisZrevrange,
676 true,
677 false,
678 RoutingOverride::None,
679 ),
680 b"georadius" => (
681 MsgType::ReqRedisGeoradius,
682 true,
683 false,
684 RoutingOverride::None,
685 ),
686 b"json.type" => (
687 MsgType::ReqRedisJsontype,
688 true,
689 false,
690 RoutingOverride::None,
691 ),
692 b"json.mget" => (
693 MsgType::ReqRedisJsonmget,
694 true,
695 false,
696 RoutingOverride::None,
697 ),
698 b"sdiffstore" => (
700 MsgType::ReqRedisSdiffstore,
701 false,
702 false,
703 RoutingOverride::None,
704 ),
705 b"incrbyfloat" => (
707 MsgType::ReqRedisIncrbyfloat,
708 false,
709 false,
710 RoutingOverride::None,
711 ),
712 b"sinterstore" => (
713 MsgType::ReqRedisSinterstore,
714 false,
715 false,
716 RoutingOverride::None,
717 ),
718 b"srandmember" => (
719 MsgType::ReqRedisSrandmember,
720 true,
721 false,
722 RoutingOverride::None,
723 ),
724 b"sunionstore" => (
725 MsgType::ReqRedisSunionstore,
726 true,
727 false,
728 RoutingOverride::None,
729 ),
730 b"zinterstore" => (
731 MsgType::ReqRedisZinterstore,
732 true,
733 false,
734 RoutingOverride::None,
735 ),
736 b"zrangebylex" => (
737 MsgType::ReqRedisZrangebylex,
738 true,
739 false,
740 RoutingOverride::None,
741 ),
742 b"zunionstore" => (
743 MsgType::ReqRedisZunionstore,
744 true,
745 false,
746 RoutingOverride::None,
747 ),
748 b"json.arrlen" => (
749 MsgType::ReqRedisJsonarrlen,
750 true,
751 false,
752 RoutingOverride::None,
753 ),
754 b"json.objlen" => (
755 MsgType::ReqRedisJsonobjlen,
756 true,
757 false,
758 RoutingOverride::None,
759 ),
760 b"hincrbyfloat" => (
762 MsgType::ReqRedisHincrbyfloat,
763 false,
764 false,
765 RoutingOverride::None,
766 ),
767 b"json.objkeys" => (
768 MsgType::ReqRedisJsonobjkeys,
769 true,
770 false,
771 RoutingOverride::None,
772 ),
773 b"zrangebyscore" => (
775 MsgType::ReqRedisZrangebyscore,
776 true,
777 false,
778 RoutingOverride::None,
779 ),
780 b"zremrangebylex" => (
782 MsgType::ReqRedisZremrangebylex,
783 false,
784 false,
785 RoutingOverride::None,
786 ),
787 b"zrevrangebylex" => (
788 MsgType::ReqRedisZrevrangebylex,
789 true,
790 false,
791 RoutingOverride::None,
792 ),
793 b"json.arrappend" => (
794 MsgType::ReqRedisJsonarrappend,
795 false,
796 false,
797 RoutingOverride::None,
798 ),
799 b"json.arrinsert" => (
800 MsgType::ReqRedisJsonarrinsert,
801 false,
802 false,
803 RoutingOverride::None,
804 ),
805 b"zremrangebyrank" => (
807 MsgType::ReqRedisZremrangebyrank,
808 false,
809 false,
810 RoutingOverride::None,
811 ),
812 b"zremrangebyscore" => (
814 MsgType::ReqRedisZremrangebyscore,
815 false,
816 false,
817 RoutingOverride::None,
818 ),
819 b"zrevrangebyscore" => (
820 MsgType::ReqRedisZrevrangebyscore,
821 true,
822 false,
823 RoutingOverride::None,
824 ),
825 b"georadiusbymember" => (
827 MsgType::ReqRedisGeoradiusbymember,
828 true,
829 false,
830 RoutingOverride::None,
831 ),
832 b"ft.create" => (
837 MsgType::ReqRedisFtCreate,
838 false,
839 false,
840 RoutingOverride::LocalNodeOnly,
841 ),
842 b"ft.search" => (
843 MsgType::ReqRedisFtSearch,
844 true,
845 false,
846 RoutingOverride::LocalNodeOnly,
847 ),
848 b"ft.info" => (
849 MsgType::ReqRedisFtInfo,
850 true,
851 false,
852 RoutingOverride::LocalNodeOnly,
853 ),
854 b"ft.list" | b"ft._list" => (
855 MsgType::ReqRedisFtList,
856 true,
857 false,
858 RoutingOverride::LocalNodeOnly,
859 ),
860 b"ft.dropindex" => (
861 MsgType::ReqRedisFtDropindex,
862 false,
863 false,
864 RoutingOverride::LocalNodeOnly,
865 ),
866 b"ft.regex" => (
872 MsgType::ReqRedisFtRegex,
873 true,
874 false,
875 RoutingOverride::LocalNodeOnly,
876 ),
877 b"ft.sugadd" => (
884 MsgType::ReqRedisFtSugadd,
885 false,
886 false,
887 RoutingOverride::LocalNodeOnly,
888 ),
889 b"ft.sugget" => (
890 MsgType::ReqRedisFtSugget,
891 true,
892 false,
893 RoutingOverride::LocalNodeOnly,
894 ),
895 b"ft.sugdel" => (
896 MsgType::ReqRedisFtSugdel,
897 false,
898 false,
899 RoutingOverride::LocalNodeOnly,
900 ),
901 b"ft.suglen" => (
902 MsgType::ReqRedisFtSuglen,
903 true,
904 false,
905 RoutingOverride::LocalNodeOnly,
906 ),
907 b"dyno_config:conn_consistency" => (
909 MsgType::HackSettingConnConsistency,
910 false,
911 false,
912 RoutingOverride::None,
913 ),
914 _ => return None,
915 };
916 Some((
917 ty,
918 CommandTraits {
919 is_read,
920 quit,
921 routing,
922 },
923 ))
924}
925
926#[must_use]
940pub fn error_lookup(token: &[u8]) -> Option<MsgType> {
941 match token {
942 b"-ERR" => Some(MsgType::RspRedisErrorErr),
943 b"-OOM" => Some(MsgType::RspRedisErrorOom),
944 b"-BUSY" => Some(MsgType::RspRedisErrorBusy),
945 b"-NOAUTH" => Some(MsgType::RspRedisErrorNoauth),
946 b"-LOADING" => Some(MsgType::RspRedisErrorLoading),
947 b"-BUSYKEY" => Some(MsgType::RspRedisErrorBusykey),
948 b"-MISCONF" => Some(MsgType::RspRedisErrorMisconf),
949 b"-NOSCRIPT" => Some(MsgType::RspRedisErrorNoscript),
950 b"-READONLY" => Some(MsgType::RspRedisErrorReadonly),
951 b"-WRONGTYPE" => Some(MsgType::RspRedisErrorWrongtype),
952 b"-EXECABORT" => Some(MsgType::RspRedisErrorExecabort),
953 b"-MASTERDOWN" => Some(MsgType::RspRedisErrorMasterdown),
954 b"-NOREPLICAS" => Some(MsgType::RspRedisErrorNoreplicas),
955 _ => None,
956 }
957}
958
959#[cfg(test)]
960mod tests {
961 use super::*;
962
963 #[test]
964 fn lookup_get_set() {
965 let (ty, t) = lookup(b"GET").unwrap();
966 assert_eq!(ty, MsgType::ReqRedisGet);
967 assert!(t.is_read);
968 let (ty, t) = lookup(b"set").unwrap();
969 assert_eq!(ty, MsgType::ReqRedisSet);
970 assert!(!t.is_read);
971 }
972
973 #[test]
974 fn lookup_unknown() {
975 assert!(lookup(b"NOTACOMMAND").is_none());
976 }
977
978 #[test]
979 fn classify_get_is_arg0() {
980 assert_eq!(classify(MsgType::ReqRedisGet), CommandClass::Arg0);
981 }
982
983 #[test]
984 fn classify_mset_is_argkvx() {
985 assert_eq!(classify(MsgType::ReqRedisMset), CommandClass::ArgKvX);
986 }
987
988 #[test]
989 fn error_lookup_wrongtype() {
990 assert_eq!(
991 error_lookup(b"-WRONGTYPE"),
992 Some(MsgType::RspRedisErrorWrongtype)
993 );
994 }
995}