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::ReqRedisFtUnknown => CommandClass::ArgN,
256
257 _ => CommandClass::Arg0,
258 }
259}
260
261#[must_use]
273pub fn is_redis_error(ty: MsgType) -> bool {
274 use MsgType as M;
275 matches!(
276 ty,
277 M::RspRedisError
278 | M::RspRedisErrorErr
279 | M::RspRedisErrorOom
280 | M::RspRedisErrorBusy
281 | M::RspRedisErrorNoauth
282 | M::RspRedisErrorLoading
283 | M::RspRedisErrorBusykey
284 | M::RspRedisErrorMisconf
285 | M::RspRedisErrorNoscript
286 | M::RspRedisErrorReadonly
287 | M::RspRedisErrorWrongtype
288 | M::RspRedisErrorExecabort
289 | M::RspRedisErrorMasterdown
290 | M::RspRedisErrorNoreplicas
291 )
292}
293
294#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
297pub struct CommandTraits {
298 pub is_read: bool,
300 pub quit: bool,
302 pub routing: RoutingOverride,
304}
305
306#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
308pub enum RoutingOverride {
309 #[default]
311 None,
312 LocalNodeOnly,
314 TokenOwnerLocalRackOnly,
316 AllNodesAllRacksAllDcs,
318}
319
320#[must_use]
336pub fn lookup(keyword: &[u8]) -> Option<(MsgType, CommandTraits)> {
337 if keyword.is_empty() || keyword.len() > 32 {
338 return None;
339 }
340 let mut buf = [0u8; 32];
341 for (i, &b) in keyword.iter().enumerate() {
342 buf[i] = b.to_ascii_lowercase();
343 }
344 let key = &buf[..keyword.len()];
345 if key.starts_with(b"ft.")
353 && !matches!(
354 key,
355 b"ft.create"
356 | b"ft.search"
357 | b"ft.info"
358 | b"ft.list"
359 | b"ft._list"
360 | b"ft.dropindex"
361 | b"ft.regex"
362 )
363 {
364 return Some((
365 MsgType::ReqRedisFtUnknown,
366 CommandTraits {
367 is_read: true,
368 quit: false,
369 routing: RoutingOverride::LocalNodeOnly,
370 },
371 ));
372 }
373 let (ty, is_read, quit, routing) = match key {
374 b"get" => (MsgType::ReqRedisGet, true, false, RoutingOverride::None),
376 b"set" => (MsgType::ReqRedisSet, false, false, RoutingOverride::None),
377 b"ttl" => (MsgType::ReqRedisTtl, false, false, RoutingOverride::None),
378 b"del" => (MsgType::ReqRedisDel, false, false, RoutingOverride::None),
379 b"pttl" => (MsgType::ReqRedisPttl, true, false, RoutingOverride::None),
381 b"decr" => (MsgType::ReqRedisDecr, false, false, RoutingOverride::None),
382 b"dump" => (MsgType::ReqRedisDump, true, false, RoutingOverride::None),
383 b"hdel" => (MsgType::ReqRedisHdel, false, false, RoutingOverride::None),
384 b"hget" => (MsgType::ReqRedisHget, true, false, RoutingOverride::None),
385 b"hlen" => (MsgType::ReqRedisHlen, true, false, RoutingOverride::None),
386 b"hset" => (MsgType::ReqRedisHset, false, false, RoutingOverride::None),
387 b"incr" => (MsgType::ReqRedisIncr, false, false, RoutingOverride::None),
388 b"keys" => (
389 MsgType::ReqRedisKeys,
390 true,
391 false,
392 RoutingOverride::LocalNodeOnly,
393 ),
394 b"info" => (
395 MsgType::ReqRedisInfo,
396 true,
397 false,
398 RoutingOverride::LocalNodeOnly,
399 ),
400 b"llen" => (MsgType::ReqRedisLlen, true, false, RoutingOverride::None),
401 b"lpop" => (MsgType::ReqRedisLpop, false, false, RoutingOverride::None),
402 b"lrem" => (MsgType::ReqRedisLrem, false, false, RoutingOverride::None),
403 b"lset" => (MsgType::ReqRedisLset, false, false, RoutingOverride::None),
404 b"mget" => (MsgType::ReqRedisMget, true, false, RoutingOverride::None),
405 b"mset" => (MsgType::ReqRedisMset, false, false, RoutingOverride::None),
406 b"ping" => (
407 MsgType::ReqRedisPing,
408 true,
409 false,
410 RoutingOverride::LocalNodeOnly,
411 ),
412 b"rpop" => (MsgType::ReqRedisRpop, false, false, RoutingOverride::None),
413 b"sadd" => (MsgType::ReqRedisSadd, false, false, RoutingOverride::None),
414 b"scan" => (
415 MsgType::ReqRedisScan,
416 true,
417 false,
418 RoutingOverride::LocalNodeOnly,
419 ),
420 b"spop" => (MsgType::ReqRedisSpop, false, false, RoutingOverride::None),
421 b"srem" => (MsgType::ReqRedisSrem, false, false, RoutingOverride::None),
422 b"type" => (MsgType::ReqRedisType, true, false, RoutingOverride::None),
423 b"zadd" => (MsgType::ReqRedisZadd, false, false, RoutingOverride::None),
424 b"zrem" => (MsgType::ReqRedisZrem, false, false, RoutingOverride::None),
425 b"eval" => (MsgType::ReqRedisEval, false, false, RoutingOverride::None),
426 b"sort" => (MsgType::ReqRedisSort, true, false, RoutingOverride::None),
427 b"quit" => (MsgType::ReqRedisQuit, false, true, RoutingOverride::None),
428 b"load" => (
429 MsgType::ReqRedisScriptLoad,
430 false,
431 false,
432 RoutingOverride::AllNodesAllRacksAllDcs,
433 ),
434 b"kill" => (
435 MsgType::ReqRedisScriptKill,
436 false,
437 false,
438 RoutingOverride::AllNodesAllRacksAllDcs,
439 ),
440 b"hkeys" => (
442 MsgType::ReqRedisHkeys,
443 true,
444 false,
445 RoutingOverride::TokenOwnerLocalRackOnly,
446 ),
447 b"hmget" => (MsgType::ReqRedisHmget, true, false, RoutingOverride::None),
448 b"hmset" => (MsgType::ReqRedisHmset, false, false, RoutingOverride::None),
449 b"hvals" => (
450 MsgType::ReqRedisHvals,
451 true,
452 false,
453 RoutingOverride::TokenOwnerLocalRackOnly,
454 ),
455 b"hscan" => (
456 MsgType::ReqRedisHscan,
457 true,
458 false,
459 RoutingOverride::TokenOwnerLocalRackOnly,
460 ),
461 b"lpush" => (MsgType::ReqRedisLpush, false, false, RoutingOverride::None),
462 b"ltrim" => (MsgType::ReqRedisLtrim, false, false, RoutingOverride::None),
463 b"rpush" => (MsgType::ReqRedisRpush, false, false, RoutingOverride::None),
464 b"scard" => (MsgType::ReqRedisScard, true, false, RoutingOverride::None),
465 b"sdiff" => (MsgType::ReqRedisSdiff, true, false, RoutingOverride::None),
466 b"setex" => (MsgType::ReqRedisSetex, false, false, RoutingOverride::None),
467 b"setnx" => (MsgType::ReqRedisSetnx, false, false, RoutingOverride::None),
468 b"smove" => (MsgType::ReqRedisSmove, false, false, RoutingOverride::None),
469 b"sscan" => (
470 MsgType::ReqRedisSscan,
471 true,
472 false,
473 RoutingOverride::TokenOwnerLocalRackOnly,
474 ),
475 b"zcard" => (MsgType::ReqRedisZcard, true, false, RoutingOverride::None),
476 b"zrank" => (MsgType::ReqRedisZrank, true, false, RoutingOverride::None),
477 b"zscan" => (
478 MsgType::ReqRedisZscan,
479 true,
480 false,
481 RoutingOverride::TokenOwnerLocalRackOnly,
482 ),
483 b"pfadd" => (MsgType::ReqRedisPfadd, false, false, RoutingOverride::None),
484 b"flush" => (
485 MsgType::ReqRedisScriptFlush,
486 false,
487 false,
488 RoutingOverride::AllNodesAllRacksAllDcs,
489 ),
490 b"append" => (MsgType::ReqRedisAppend, false, false, RoutingOverride::None),
492 b"decrby" => (MsgType::ReqRedisDecrby, false, false, RoutingOverride::None),
493 b"exists" => (MsgType::ReqRedisExists, true, false, RoutingOverride::None),
494 b"expire" => (MsgType::ReqRedisExpire, false, false, RoutingOverride::None),
495 b"getbit" => (MsgType::ReqRedisGetbit, true, false, RoutingOverride::None),
496 b"getset" => (MsgType::ReqRedisGetset, false, false, RoutingOverride::None),
497 b"psetex" => (MsgType::ReqRedisPsetex, false, false, RoutingOverride::None),
498 b"hsetnx" => (MsgType::ReqRedisHsetnx, false, false, RoutingOverride::None),
499 b"incrby" => (MsgType::ReqRedisIncrby, false, false, RoutingOverride::None),
500 b"lindex" => (MsgType::ReqRedisLindex, true, false, RoutingOverride::None),
501 b"lpushx" => (MsgType::ReqRedisLpushx, false, false, RoutingOverride::None),
502 b"lrange" => (MsgType::ReqRedisLrange, true, false, RoutingOverride::None),
503 b"rpushx" => (MsgType::ReqRedisRpushx, false, false, RoutingOverride::None),
504 b"setbit" => (MsgType::ReqRedisSetbit, false, false, RoutingOverride::None),
505 b"sinter" => (MsgType::ReqRedisSinter, true, false, RoutingOverride::None),
506 b"strlen" => (MsgType::ReqRedisStrlen, true, false, RoutingOverride::None),
507 b"sunion" => (MsgType::ReqRedisSunion, true, false, RoutingOverride::None),
508 b"zcount" => (MsgType::ReqRedisZcount, true, false, RoutingOverride::None),
509 b"zrange" => (MsgType::ReqRedisZrange, true, false, RoutingOverride::None),
510 b"zscore" => (MsgType::ReqRedisZscore, true, false, RoutingOverride::None),
511 b"config" => (
512 MsgType::ReqRedisConfig,
513 true,
514 false,
515 RoutingOverride::LocalNodeOnly,
516 ),
517 b"geoadd" => (MsgType::ReqRedisGeoadd, false, false, RoutingOverride::None),
518 b"geopos" => (MsgType::ReqRedisGeopos, true, false, RoutingOverride::None),
519 b"unlink" => (MsgType::ReqRedisUnlink, false, false, RoutingOverride::None),
520 b"script" => (MsgType::ReqRedisScript, false, false, RoutingOverride::None),
521 b"bitpos" => (MsgType::ReqRedisBitpos, true, false, RoutingOverride::None),
522 b"persist" => (
524 MsgType::ReqRedisPersist,
525 false,
526 false,
527 RoutingOverride::None,
528 ),
529 b"pexpire" => (
530 MsgType::ReqRedisPexpire,
531 false,
532 false,
533 RoutingOverride::None,
534 ),
535 b"hexists" => (MsgType::ReqRedisHexists, true, false, RoutingOverride::None),
536 b"hgetall" => (
537 MsgType::ReqRedisHgetall,
538 true,
539 false,
540 RoutingOverride::TokenOwnerLocalRackOnly,
541 ),
542 b"hincrby" => (
543 MsgType::ReqRedisHincrby,
544 false,
545 false,
546 RoutingOverride::None,
547 ),
548 b"linsert" => (
549 MsgType::ReqRedisLinsert,
550 false,
551 false,
552 RoutingOverride::None,
553 ),
554 b"zincrby" => (
555 MsgType::ReqRedisZincrby,
556 false,
557 false,
558 RoutingOverride::None,
559 ),
560 b"evalsha" => (
561 MsgType::ReqRedisEvalsha,
562 false,
563 false,
564 RoutingOverride::None,
565 ),
566 b"restore" => (
567 MsgType::ReqRedisRestore,
568 false,
569 false,
570 RoutingOverride::None,
571 ),
572 b"slaveof" => (
573 MsgType::ReqRedisSlaveof,
574 false,
575 false,
576 RoutingOverride::LocalNodeOnly,
577 ),
578 b"pfcount" => (
579 MsgType::ReqRedisPfcount,
580 false,
581 false,
582 RoutingOverride::None,
583 ),
584 b"geohash" => (MsgType::ReqRedisGeohash, true, false, RoutingOverride::None),
585 b"geodist" => (MsgType::ReqRedisGeodist, true, false, RoutingOverride::None),
586 b"hstrlen" => (MsgType::ReqRedisHstrlen, true, false, RoutingOverride::None),
587 b"expireat" => (
589 MsgType::ReqRedisExpireat,
590 false,
591 false,
592 RoutingOverride::None,
593 ),
594 b"bitcount" => (
595 MsgType::ReqRedisBitcount,
596 true,
597 false,
598 RoutingOverride::None,
599 ),
600 b"getrange" => (
601 MsgType::ReqRedisGetrange,
602 true,
603 false,
604 RoutingOverride::None,
605 ),
606 b"setrange" => (
607 MsgType::ReqRedisSetrange,
608 false,
609 false,
610 RoutingOverride::None,
611 ),
612 b"smembers" => (
613 MsgType::ReqRedisSmembers,
614 true,
615 false,
616 RoutingOverride::None,
617 ),
618 b"zrevrank" => (
619 MsgType::ReqRedisZrevrank,
620 true,
621 false,
622 RoutingOverride::None,
623 ),
624 b"json.set" => (
625 MsgType::ReqRedisJsonset,
626 false,
627 false,
628 RoutingOverride::None,
629 ),
630 b"json.get" => (MsgType::ReqRedisJsonget, true, false, RoutingOverride::None),
631 b"json.del" => (
632 MsgType::ReqRedisJsondel,
633 false,
634 false,
635 RoutingOverride::None,
636 ),
637 b"pexpireat" => (
639 MsgType::ReqRedisPexpireat,
640 false,
641 false,
642 RoutingOverride::None,
643 ),
644 b"rpoplpush" => (
645 MsgType::ReqRedisRpoplpush,
646 false,
647 false,
648 RoutingOverride::None,
649 ),
650 b"sismember" => (
651 MsgType::ReqRedisSismember,
652 true,
653 false,
654 RoutingOverride::None,
655 ),
656 b"zlexcount" => (
657 MsgType::ReqRedisZlexcount,
658 true,
659 false,
660 RoutingOverride::None,
661 ),
662 b"zrevrange" => (
663 MsgType::ReqRedisZrevrange,
664 true,
665 false,
666 RoutingOverride::None,
667 ),
668 b"georadius" => (
669 MsgType::ReqRedisGeoradius,
670 true,
671 false,
672 RoutingOverride::None,
673 ),
674 b"json.type" => (
675 MsgType::ReqRedisJsontype,
676 true,
677 false,
678 RoutingOverride::None,
679 ),
680 b"json.mget" => (
681 MsgType::ReqRedisJsonmget,
682 true,
683 false,
684 RoutingOverride::None,
685 ),
686 b"sdiffstore" => (
688 MsgType::ReqRedisSdiffstore,
689 false,
690 false,
691 RoutingOverride::None,
692 ),
693 b"incrbyfloat" => (
695 MsgType::ReqRedisIncrbyfloat,
696 false,
697 false,
698 RoutingOverride::None,
699 ),
700 b"sinterstore" => (
701 MsgType::ReqRedisSinterstore,
702 false,
703 false,
704 RoutingOverride::None,
705 ),
706 b"srandmember" => (
707 MsgType::ReqRedisSrandmember,
708 true,
709 false,
710 RoutingOverride::None,
711 ),
712 b"sunionstore" => (
713 MsgType::ReqRedisSunionstore,
714 true,
715 false,
716 RoutingOverride::None,
717 ),
718 b"zinterstore" => (
719 MsgType::ReqRedisZinterstore,
720 true,
721 false,
722 RoutingOverride::None,
723 ),
724 b"zrangebylex" => (
725 MsgType::ReqRedisZrangebylex,
726 true,
727 false,
728 RoutingOverride::None,
729 ),
730 b"zunionstore" => (
731 MsgType::ReqRedisZunionstore,
732 true,
733 false,
734 RoutingOverride::None,
735 ),
736 b"json.arrlen" => (
737 MsgType::ReqRedisJsonarrlen,
738 true,
739 false,
740 RoutingOverride::None,
741 ),
742 b"json.objlen" => (
743 MsgType::ReqRedisJsonobjlen,
744 true,
745 false,
746 RoutingOverride::None,
747 ),
748 b"hincrbyfloat" => (
750 MsgType::ReqRedisHincrbyfloat,
751 false,
752 false,
753 RoutingOverride::None,
754 ),
755 b"json.objkeys" => (
756 MsgType::ReqRedisJsonobjkeys,
757 true,
758 false,
759 RoutingOverride::None,
760 ),
761 b"zrangebyscore" => (
763 MsgType::ReqRedisZrangebyscore,
764 true,
765 false,
766 RoutingOverride::None,
767 ),
768 b"zremrangebylex" => (
770 MsgType::ReqRedisZremrangebylex,
771 false,
772 false,
773 RoutingOverride::None,
774 ),
775 b"zrevrangebylex" => (
776 MsgType::ReqRedisZrevrangebylex,
777 true,
778 false,
779 RoutingOverride::None,
780 ),
781 b"json.arrappend" => (
782 MsgType::ReqRedisJsonarrappend,
783 false,
784 false,
785 RoutingOverride::None,
786 ),
787 b"json.arrinsert" => (
788 MsgType::ReqRedisJsonarrinsert,
789 false,
790 false,
791 RoutingOverride::None,
792 ),
793 b"zremrangebyrank" => (
795 MsgType::ReqRedisZremrangebyrank,
796 false,
797 false,
798 RoutingOverride::None,
799 ),
800 b"zremrangebyscore" => (
802 MsgType::ReqRedisZremrangebyscore,
803 false,
804 false,
805 RoutingOverride::None,
806 ),
807 b"zrevrangebyscore" => (
808 MsgType::ReqRedisZrevrangebyscore,
809 true,
810 false,
811 RoutingOverride::None,
812 ),
813 b"georadiusbymember" => (
815 MsgType::ReqRedisGeoradiusbymember,
816 true,
817 false,
818 RoutingOverride::None,
819 ),
820 b"ft.create" => (
825 MsgType::ReqRedisFtCreate,
826 false,
827 false,
828 RoutingOverride::LocalNodeOnly,
829 ),
830 b"ft.search" => (
831 MsgType::ReqRedisFtSearch,
832 true,
833 false,
834 RoutingOverride::LocalNodeOnly,
835 ),
836 b"ft.info" => (
837 MsgType::ReqRedisFtInfo,
838 true,
839 false,
840 RoutingOverride::LocalNodeOnly,
841 ),
842 b"ft.list" | b"ft._list" => (
843 MsgType::ReqRedisFtList,
844 true,
845 false,
846 RoutingOverride::LocalNodeOnly,
847 ),
848 b"ft.dropindex" => (
849 MsgType::ReqRedisFtDropindex,
850 false,
851 false,
852 RoutingOverride::LocalNodeOnly,
853 ),
854 b"ft.regex" => (
860 MsgType::ReqRedisFtRegex,
861 true,
862 false,
863 RoutingOverride::LocalNodeOnly,
864 ),
865 b"dyno_config:conn_consistency" => (
867 MsgType::HackSettingConnConsistency,
868 false,
869 false,
870 RoutingOverride::None,
871 ),
872 _ => return None,
873 };
874 Some((
875 ty,
876 CommandTraits {
877 is_read,
878 quit,
879 routing,
880 },
881 ))
882}
883
884#[must_use]
898pub fn error_lookup(token: &[u8]) -> Option<MsgType> {
899 match token {
900 b"-ERR" => Some(MsgType::RspRedisErrorErr),
901 b"-OOM" => Some(MsgType::RspRedisErrorOom),
902 b"-BUSY" => Some(MsgType::RspRedisErrorBusy),
903 b"-NOAUTH" => Some(MsgType::RspRedisErrorNoauth),
904 b"-LOADING" => Some(MsgType::RspRedisErrorLoading),
905 b"-BUSYKEY" => Some(MsgType::RspRedisErrorBusykey),
906 b"-MISCONF" => Some(MsgType::RspRedisErrorMisconf),
907 b"-NOSCRIPT" => Some(MsgType::RspRedisErrorNoscript),
908 b"-READONLY" => Some(MsgType::RspRedisErrorReadonly),
909 b"-WRONGTYPE" => Some(MsgType::RspRedisErrorWrongtype),
910 b"-EXECABORT" => Some(MsgType::RspRedisErrorExecabort),
911 b"-MASTERDOWN" => Some(MsgType::RspRedisErrorMasterdown),
912 b"-NOREPLICAS" => Some(MsgType::RspRedisErrorNoreplicas),
913 _ => None,
914 }
915}
916
917#[cfg(test)]
918mod tests {
919 use super::*;
920
921 #[test]
922 fn lookup_get_set() {
923 let (ty, t) = lookup(b"GET").unwrap();
924 assert_eq!(ty, MsgType::ReqRedisGet);
925 assert!(t.is_read);
926 let (ty, t) = lookup(b"set").unwrap();
927 assert_eq!(ty, MsgType::ReqRedisSet);
928 assert!(!t.is_read);
929 }
930
931 #[test]
932 fn lookup_unknown() {
933 assert!(lookup(b"NOTACOMMAND").is_none());
934 }
935
936 #[test]
937 fn classify_get_is_arg0() {
938 assert_eq!(classify(MsgType::ReqRedisGet), CommandClass::Arg0);
939 }
940
941 #[test]
942 fn classify_mset_is_argkvx() {
943 assert_eq!(classify(MsgType::ReqRedisMset), CommandClass::ArgKvX);
944 }
945
946 #[test]
947 fn error_lookup_wrongtype() {
948 assert_eq!(
949 error_lookup(b"-WRONGTYPE"),
950 Some(MsgType::RspRedisErrorWrongtype)
951 );
952 }
953}