kora_core/command.rs
1//! Command and response types for the Kōra engine.
2//!
3//! `Command` is the parsed, type-safe representation of every operation the
4//! engine supports — strings, lists, sets, hashes, sorted sets, streams,
5//! HyperLogLog, bitmaps, geo, vectors, pub/sub, transactions, and server
6//! management. The protocol crate parses raw RESP frames into `Command`
7//! variants, and the shard engine pattern-matches on them for execution.
8//!
9//! `CommandResponse` is the corresponding output type. Variants map directly
10//! to RESP wire types (simple string, error, integer, bulk string, array, nil)
11//! plus a `BulkStringShared` variant that allows zero-copy responses via
12//! `Arc<[u8]>`.
13//!
14//! Helper methods on `Command` (`key()`, `is_multi_key()`, `is_mutation()`,
15//! `cmd_type()`) drive the engine's routing and WAL logic.
16
17use std::sync::Arc;
18use std::time::Duration;
19
20/// A parsed command ready for execution by a shard.
21#[derive(Debug, Clone)]
22pub enum Command {
23 // -- String commands --
24 /// GET key
25 Get {
26 /// The key to retrieve.
27 key: Vec<u8>,
28 },
29 /// SET key value \[EX seconds\] \[PX millis\] \[NX|XX\]
30 Set {
31 /// The key.
32 key: Vec<u8>,
33 /// The value.
34 value: Vec<u8>,
35 /// Optional TTL in seconds.
36 ex: Option<u64>,
37 /// Optional TTL in milliseconds.
38 px: Option<u64>,
39 /// Only set if key does not exist.
40 nx: bool,
41 /// Only set if key already exists.
42 xx: bool,
43 },
44 /// GETSET key value (deprecated but supported)
45 GetSet {
46 /// The key.
47 key: Vec<u8>,
48 /// The new value.
49 value: Vec<u8>,
50 },
51 /// APPEND key value
52 Append {
53 /// The key.
54 key: Vec<u8>,
55 /// The value to append.
56 value: Vec<u8>,
57 },
58 /// STRLEN key
59 Strlen {
60 /// The key.
61 key: Vec<u8>,
62 },
63 /// INCR key
64 Incr {
65 /// The key.
66 key: Vec<u8>,
67 },
68 /// DECR key
69 Decr {
70 /// The key.
71 key: Vec<u8>,
72 },
73 /// INCRBY key delta
74 IncrBy {
75 /// The key.
76 key: Vec<u8>,
77 /// The increment amount.
78 delta: i64,
79 },
80 /// DECRBY key delta
81 DecrBy {
82 /// The key.
83 key: Vec<u8>,
84 /// The decrement amount.
85 delta: i64,
86 },
87 /// MGET key \[key ...\]
88 MGet {
89 /// The keys to retrieve.
90 keys: Vec<Vec<u8>>,
91 },
92 /// MSET key value \[key value ...\]
93 MSet {
94 /// Key-value pairs to set.
95 entries: Vec<(Vec<u8>, Vec<u8>)>,
96 },
97 /// SETNX key value
98 SetNx {
99 /// The key.
100 key: Vec<u8>,
101 /// The value.
102 value: Vec<u8>,
103 },
104 /// INCRBYFLOAT key delta
105 IncrByFloat {
106 /// The key.
107 key: Vec<u8>,
108 /// The float increment amount.
109 delta: f64,
110 },
111 /// GETRANGE key start end
112 GetRange {
113 /// The key.
114 key: Vec<u8>,
115 /// Start offset.
116 start: i64,
117 /// End offset (inclusive).
118 end: i64,
119 },
120 /// SETRANGE key offset value
121 SetRange {
122 /// The key.
123 key: Vec<u8>,
124 /// Byte offset.
125 offset: usize,
126 /// Value to write at offset.
127 value: Vec<u8>,
128 },
129 /// GETDEL key
130 GetDel {
131 /// The key.
132 key: Vec<u8>,
133 },
134 /// GETEX key \[EX seconds | PX millis | EXAT timestamp | PXAT timestamp\_ms | PERSIST\]
135 GetEx {
136 /// The key.
137 key: Vec<u8>,
138 /// Optional TTL in seconds.
139 ex: Option<u64>,
140 /// Optional TTL in milliseconds.
141 px: Option<u64>,
142 /// Optional absolute Unix timestamp (seconds).
143 exat: Option<u64>,
144 /// Optional absolute Unix timestamp (milliseconds).
145 pxat: Option<u64>,
146 /// Whether to remove TTL.
147 persist: bool,
148 },
149 /// MSETNX key value \[key value ...\]
150 MSetNx {
151 /// Key-value pairs to set.
152 entries: Vec<(Vec<u8>, Vec<u8>)>,
153 },
154
155 // -- Key commands --
156 /// DEL key \[key ...\]
157 Del {
158 /// The keys to delete.
159 keys: Vec<Vec<u8>>,
160 },
161 /// EXISTS key \[key ...\]
162 Exists {
163 /// The keys to check.
164 keys: Vec<Vec<u8>>,
165 },
166 /// EXPIRE key seconds
167 Expire {
168 /// The key.
169 key: Vec<u8>,
170 /// TTL in seconds.
171 seconds: u64,
172 },
173 /// PEXPIRE key milliseconds
174 PExpire {
175 /// The key.
176 key: Vec<u8>,
177 /// TTL in milliseconds.
178 millis: u64,
179 },
180 /// PERSIST key
181 Persist {
182 /// The key.
183 key: Vec<u8>,
184 },
185 /// TTL key
186 Ttl {
187 /// The key.
188 key: Vec<u8>,
189 },
190 /// PTTL key
191 PTtl {
192 /// The key.
193 key: Vec<u8>,
194 },
195 /// TYPE key
196 Type {
197 /// The key.
198 key: Vec<u8>,
199 },
200 /// KEYS pattern
201 Keys {
202 /// Glob pattern to match.
203 pattern: String,
204 },
205 /// SCAN cursor \[MATCH pattern\] \[COUNT count\]
206 Scan {
207 /// The cursor position.
208 cursor: u64,
209 /// Optional glob pattern filter.
210 pattern: Option<String>,
211 /// Optional count hint.
212 count: Option<usize>,
213 },
214 /// EXPIREAT key timestamp
215 ExpireAt {
216 /// The key.
217 key: Vec<u8>,
218 /// Absolute Unix timestamp in seconds.
219 timestamp: u64,
220 },
221 /// PEXPIREAT key timestamp\_ms
222 PExpireAt {
223 /// The key.
224 key: Vec<u8>,
225 /// Absolute Unix timestamp in milliseconds.
226 timestamp_ms: u64,
227 },
228 /// RENAME key newkey
229 Rename {
230 /// The source key.
231 key: Vec<u8>,
232 /// The destination key.
233 newkey: Vec<u8>,
234 },
235 /// RENAMENX key newkey
236 RenameNx {
237 /// The source key.
238 key: Vec<u8>,
239 /// The destination key.
240 newkey: Vec<u8>,
241 },
242 /// UNLINK key \[key ...\]
243 Unlink {
244 /// The keys to unlink.
245 keys: Vec<Vec<u8>>,
246 },
247 /// COPY source destination \[REPLACE\]
248 Copy {
249 /// The source key.
250 source: Vec<u8>,
251 /// The destination key.
252 destination: Vec<u8>,
253 /// Whether to overwrite the destination.
254 replace: bool,
255 },
256 /// RANDOMKEY
257 RandomKey,
258 /// TOUCH key \[key ...\]
259 Touch {
260 /// The keys to touch.
261 keys: Vec<Vec<u8>>,
262 },
263 /// OBJECT REFCOUNT key
264 ObjectRefCount {
265 /// The key.
266 key: Vec<u8>,
267 },
268 /// OBJECT IDLETIME key
269 ObjectIdleTime {
270 /// The key.
271 key: Vec<u8>,
272 },
273 /// OBJECT HELP
274 ObjectHelp,
275 /// DBSIZE
276 DbSize,
277 /// FLUSHDB
278 FlushDb,
279
280 // -- List commands --
281 /// LPUSH key value \[value ...\]
282 LPush {
283 /// The key.
284 key: Vec<u8>,
285 /// Values to push.
286 values: Vec<Vec<u8>>,
287 },
288 /// RPUSH key value \[value ...\]
289 RPush {
290 /// The key.
291 key: Vec<u8>,
292 /// Values to push.
293 values: Vec<Vec<u8>>,
294 },
295 /// LPOP key
296 LPop {
297 /// The key.
298 key: Vec<u8>,
299 },
300 /// RPOP key
301 RPop {
302 /// The key.
303 key: Vec<u8>,
304 },
305 /// LLEN key
306 LLen {
307 /// The key.
308 key: Vec<u8>,
309 },
310 /// LRANGE key start stop
311 LRange {
312 /// The key.
313 key: Vec<u8>,
314 /// Start index (0-based, negative from end).
315 start: i64,
316 /// Stop index (inclusive, negative from end).
317 stop: i64,
318 },
319 /// LINDEX key index
320 LIndex {
321 /// The key.
322 key: Vec<u8>,
323 /// The index (negative from end).
324 index: i64,
325 },
326 /// LSET key index value
327 LSet {
328 /// The key.
329 key: Vec<u8>,
330 /// The index.
331 index: i64,
332 /// The value to set.
333 value: Vec<u8>,
334 },
335 /// LINSERT key BEFORE|AFTER pivot value
336 LInsert {
337 /// The key.
338 key: Vec<u8>,
339 /// Insert before pivot if true, after if false.
340 before: bool,
341 /// The pivot element.
342 pivot: Vec<u8>,
343 /// The value to insert.
344 value: Vec<u8>,
345 },
346 /// LREM key count value
347 LRem {
348 /// The key.
349 key: Vec<u8>,
350 /// Count: >0 from head, <0 from tail, 0 = all.
351 count: i64,
352 /// The value to remove.
353 value: Vec<u8>,
354 },
355 /// LTRIM key start stop
356 LTrim {
357 /// The key.
358 key: Vec<u8>,
359 /// Start index.
360 start: i64,
361 /// Stop index (inclusive).
362 stop: i64,
363 },
364 /// LPOS key value \[RANK rank\] \[COUNT count\] \[MAXLEN len\]
365 LPos {
366 /// The key.
367 key: Vec<u8>,
368 /// The value to search for.
369 value: Vec<u8>,
370 /// Rank parameter (skip N matches).
371 rank: Option<i64>,
372 /// Count parameter (return N positions, 0 = all).
373 count: Option<i64>,
374 /// Maximum elements to scan.
375 maxlen: Option<i64>,
376 },
377 /// RPOPLPUSH source destination
378 RPopLPush {
379 /// The source key.
380 source: Vec<u8>,
381 /// The destination key.
382 destination: Vec<u8>,
383 },
384 /// LMOVE source destination LEFT|RIGHT LEFT|RIGHT
385 LMove {
386 /// The source key.
387 source: Vec<u8>,
388 /// The destination key.
389 destination: Vec<u8>,
390 /// Pop from left side of source if true, right if false.
391 from_left: bool,
392 /// Push to left side of destination if true, right if false.
393 to_left: bool,
394 },
395
396 // -- Hash commands --
397 /// HSET key field value \[field value ...\]
398 HSet {
399 /// The key.
400 key: Vec<u8>,
401 /// Field-value pairs.
402 fields: Vec<(Vec<u8>, Vec<u8>)>,
403 },
404 /// HGET key field
405 HGet {
406 /// The key.
407 key: Vec<u8>,
408 /// The field name.
409 field: Vec<u8>,
410 },
411 /// HDEL key field \[field ...\]
412 HDel {
413 /// The key.
414 key: Vec<u8>,
415 /// Fields to delete.
416 fields: Vec<Vec<u8>>,
417 },
418 /// HGETALL key
419 HGetAll {
420 /// The key.
421 key: Vec<u8>,
422 },
423 /// HLEN key
424 HLen {
425 /// The key.
426 key: Vec<u8>,
427 },
428 /// HEXISTS key field
429 HExists {
430 /// The key.
431 key: Vec<u8>,
432 /// The field name.
433 field: Vec<u8>,
434 },
435 /// HINCRBY key field increment
436 HIncrBy {
437 /// The key.
438 key: Vec<u8>,
439 /// The field name.
440 field: Vec<u8>,
441 /// The increment amount.
442 delta: i64,
443 },
444 /// HMGET key field \[field ...\]
445 HMGet {
446 /// The key.
447 key: Vec<u8>,
448 /// Fields to retrieve.
449 fields: Vec<Vec<u8>>,
450 },
451 /// HKEYS key
452 HKeys {
453 /// The key.
454 key: Vec<u8>,
455 },
456 /// HVALS key
457 HVals {
458 /// The key.
459 key: Vec<u8>,
460 },
461 /// HSETNX key field value
462 HSetNx {
463 /// The key.
464 key: Vec<u8>,
465 /// The field name.
466 field: Vec<u8>,
467 /// The value.
468 value: Vec<u8>,
469 },
470 /// HINCRBYFLOAT key field delta
471 HIncrByFloat {
472 /// The key.
473 key: Vec<u8>,
474 /// The field name.
475 field: Vec<u8>,
476 /// The float increment amount.
477 delta: f64,
478 },
479 /// HRANDFIELD key \[count \[WITHVALUES\]\]
480 HRandField {
481 /// The key.
482 key: Vec<u8>,
483 /// Optional count (negative = allow duplicates).
484 count: Option<i64>,
485 /// Whether to include values.
486 withvalues: bool,
487 },
488 /// HSCAN key cursor \[MATCH pattern\] \[COUNT count\]
489 HScan {
490 /// The key.
491 key: Vec<u8>,
492 /// The cursor position.
493 cursor: u64,
494 /// Optional glob pattern filter.
495 pattern: Option<String>,
496 /// Optional count hint.
497 count: Option<usize>,
498 },
499
500 // -- Set commands --
501 /// SADD key member \[member ...\]
502 SAdd {
503 /// The key.
504 key: Vec<u8>,
505 /// Members to add.
506 members: Vec<Vec<u8>>,
507 },
508 /// SREM key member \[member ...\]
509 SRem {
510 /// The key.
511 key: Vec<u8>,
512 /// Members to remove.
513 members: Vec<Vec<u8>>,
514 },
515 /// SMEMBERS key
516 SMembers {
517 /// The key.
518 key: Vec<u8>,
519 },
520 /// SISMEMBER key member
521 SIsMember {
522 /// The key.
523 key: Vec<u8>,
524 /// The member to check.
525 member: Vec<u8>,
526 },
527 /// SCARD key
528 SCard {
529 /// The key.
530 key: Vec<u8>,
531 },
532 /// SPOP key \[count\]
533 SPop {
534 /// The key.
535 key: Vec<u8>,
536 /// Optional count of members to pop.
537 count: Option<usize>,
538 },
539 /// SRANDMEMBER key \[count\]
540 SRandMember {
541 /// The key.
542 key: Vec<u8>,
543 /// Optional count (negative = allow duplicates).
544 count: Option<i64>,
545 },
546 /// SUNION key \[key ...\]
547 SUnion {
548 /// The keys of the sets.
549 keys: Vec<Vec<u8>>,
550 },
551 /// SUNIONSTORE destination key \[key ...\]
552 SUnionStore {
553 /// The destination key.
554 destination: Vec<u8>,
555 /// The source set keys.
556 keys: Vec<Vec<u8>>,
557 },
558 /// SINTER key \[key ...\]
559 SInter {
560 /// The keys of the sets.
561 keys: Vec<Vec<u8>>,
562 },
563 /// SINTERSTORE destination key \[key ...\]
564 SInterStore {
565 /// The destination key.
566 destination: Vec<u8>,
567 /// The source set keys.
568 keys: Vec<Vec<u8>>,
569 },
570 /// SDIFF key \[key ...\]
571 SDiff {
572 /// The keys of the sets.
573 keys: Vec<Vec<u8>>,
574 },
575 /// SDIFFSTORE destination key \[key ...\]
576 SDiffStore {
577 /// The destination key.
578 destination: Vec<u8>,
579 /// The source set keys.
580 keys: Vec<Vec<u8>>,
581 },
582 /// SINTERCARD numkeys key \[key ...\] \[LIMIT limit\]
583 SInterCard {
584 /// Number of keys.
585 numkeys: usize,
586 /// The keys of the sets.
587 keys: Vec<Vec<u8>>,
588 /// Optional limit on the count.
589 limit: Option<usize>,
590 },
591 /// SMOVE source destination member
592 SMove {
593 /// The source key.
594 source: Vec<u8>,
595 /// The destination key.
596 destination: Vec<u8>,
597 /// The member to move.
598 member: Vec<u8>,
599 },
600 /// SMISMEMBER key member \[member ...\]
601 SMisMember {
602 /// The key.
603 key: Vec<u8>,
604 /// Members to check.
605 members: Vec<Vec<u8>>,
606 },
607 /// SSCAN key cursor \[MATCH pattern\] \[COUNT count\]
608 SScan {
609 /// The key.
610 key: Vec<u8>,
611 /// The cursor position.
612 cursor: u64,
613 /// Optional glob pattern filter.
614 pattern: Option<String>,
615 /// Optional count hint.
616 count: Option<usize>,
617 },
618
619 // -- Server commands --
620 /// PING \[message\]
621 Ping {
622 /// Optional message to echo back.
623 message: Option<Vec<u8>>,
624 },
625 /// ECHO message
626 Echo {
627 /// The message to echo.
628 message: Vec<u8>,
629 },
630 /// INFO \[section\]
631 Info {
632 /// Optional section filter.
633 section: Option<String>,
634 },
635 /// BGSAVE — trigger a background RDB snapshot.
636 BgSave,
637 /// BGREWRITEAOF — trigger a WAL rewrite.
638 BgRewriteAof,
639 /// FLUSHALL — flush all databases.
640 FlushAll,
641 /// COMMAND \[INFO \[command ...\]\] — returns command metadata.
642 CommandInfo {
643 /// Optional command names to fetch metadata for. Empty means all commands.
644 names: Vec<Vec<u8>>,
645 },
646 /// HELLO \[protover\] — protocol version negotiation (RESP3).
647 Hello {
648 /// Requested protocol version (2 or 3).
649 version: Option<u8>,
650 },
651 /// AUTH password — authenticate the connection.
652 Auth {
653 /// Password.
654 password: Vec<u8>,
655 },
656 /// DUMP — extract all key-value entries from a shard (internal).
657 Dump,
658
659 // -- Transaction commands --
660 /// MULTI — start a transaction block.
661 Multi,
662 /// EXEC — execute all queued commands in a transaction.
663 Exec,
664 /// DISCARD — discard all queued commands in a transaction.
665 Discard,
666 /// WATCH key \[key ...\] — optimistic locking (accepted, not enforced).
667 Watch {
668 /// Keys to watch.
669 keys: Vec<Vec<u8>>,
670 },
671 /// UNWATCH — clear all watched keys.
672 Unwatch,
673
674 // -- Server commands (Phase 5) --
675 /// CONFIG GET pattern
676 ConfigGet {
677 /// Glob pattern for config keys.
678 pattern: String,
679 },
680 /// CONFIG SET parameter value
681 ConfigSet {
682 /// Config parameter name.
683 parameter: String,
684 /// Config value.
685 value: String,
686 },
687 /// CONFIG RESETSTAT
688 ConfigResetStat,
689 /// CLIENT ID — return connection unique ID.
690 ClientId,
691 /// CLIENT GETNAME — return connection name.
692 ClientGetName,
693 /// CLIENT SETNAME name — set connection name.
694 ClientSetName {
695 /// The connection name.
696 name: Vec<u8>,
697 },
698 /// CLIENT LIST — list all connections.
699 ClientList,
700 /// CLIENT INFO — current connection info.
701 ClientInfo,
702 /// TIME — return server time.
703 Time,
704 /// SELECT db — select database (only db 0 supported).
705 Select {
706 /// Database index.
707 db: i64,
708 },
709 /// QUIT — close connection gracefully.
710 Quit,
711 /// WAIT numreplicas timeout — wait for replication acknowledgements.
712 Wait {
713 /// Number of replicas to wait for.
714 numreplicas: i64,
715 /// Timeout in milliseconds.
716 timeout: i64,
717 },
718 /// COMMAND COUNT — return number of supported commands.
719 CommandCount,
720 /// COMMAND LIST — return the names of supported commands.
721 CommandList,
722 /// COMMAND HELP — return command help text.
723 CommandHelp,
724 /// COMMAND DOCS \[command ...\] — return command documentation metadata.
725 CommandDocs {
726 /// Optional command names to fetch docs for. Empty means all commands.
727 names: Vec<Vec<u8>>,
728 },
729
730 // -- Document commands --
731 /// DOC.CREATE collection \[COMPRESSION profile\] — create a collection.
732 DocCreate {
733 /// Collection name.
734 collection: Vec<u8>,
735 /// Optional compression profile name.
736 compression: Option<Vec<u8>>,
737 },
738 /// DOC.DROP collection — drop a collection.
739 DocDrop {
740 /// Collection name.
741 collection: Vec<u8>,
742 },
743 /// DOC.INFO collection — collection metadata.
744 DocInfo {
745 /// Collection name.
746 collection: Vec<u8>,
747 },
748 /// DOC.DICTINFO collection — dictionary statistics for a collection.
749 DocDictInfo {
750 /// Collection name.
751 collection: Vec<u8>,
752 },
753 /// DOC.STORAGE collection — storage statistics for a collection.
754 DocStorage {
755 /// Collection name.
756 collection: Vec<u8>,
757 },
758 /// DOC.SET collection doc_id json — insert or replace a document.
759 DocSet {
760 /// Collection name.
761 collection: Vec<u8>,
762 /// External document ID.
763 doc_id: Vec<u8>,
764 /// JSON payload bytes.
765 json: Vec<u8>,
766 },
767 /// DOC.INSERT collection json — insert with auto-generated ID.
768 DocInsert {
769 /// Collection name.
770 collection: Vec<u8>,
771 /// JSON payload bytes.
772 json: Vec<u8>,
773 },
774 /// DOC.MSET collection doc_id json \[doc_id json ...\] — batch insert/replace.
775 DocMSet {
776 /// Collection name.
777 collection: Vec<u8>,
778 /// Batch entries as `(doc_id, json_payload)`.
779 entries: Vec<(Vec<u8>, Vec<u8>)>,
780 },
781 /// DOC.GET collection doc_id \[FIELDS path ...\] — fetch a document.
782 DocGet {
783 /// Collection name.
784 collection: Vec<u8>,
785 /// External document ID.
786 doc_id: Vec<u8>,
787 /// Optional projection paths. Empty means full document.
788 fields: Vec<Vec<u8>>,
789 },
790 /// DOC.MGET collection doc_id \[doc_id ...\] — batch fetch.
791 DocMGet {
792 /// Collection name.
793 collection: Vec<u8>,
794 /// External document IDs.
795 doc_ids: Vec<Vec<u8>>,
796 },
797 /// DOC.UPDATE collection doc_id <mutation...> — apply field-level mutations.
798 DocUpdate {
799 /// Collection name.
800 collection: Vec<u8>,
801 /// External document ID.
802 doc_id: Vec<u8>,
803 /// Mutation operations to apply in order.
804 mutations: Vec<DocUpdateMutation>,
805 },
806 /// DOC.DEL collection doc_id — delete a document.
807 DocDel {
808 /// Collection name.
809 collection: Vec<u8>,
810 /// External document ID.
811 doc_id: Vec<u8>,
812 },
813 /// DOC.EXISTS collection doc_id — check document existence.
814 DocExists {
815 /// Collection name.
816 collection: Vec<u8>,
817 /// External document ID.
818 doc_id: Vec<u8>,
819 },
820 /// DOC.CREATEINDEX collection field type — create a secondary index.
821 DocCreateIndex {
822 /// Collection name.
823 collection: Vec<u8>,
824 /// Dotted field path.
825 field: Vec<u8>,
826 /// Index type string (hash, sorted, array, unique).
827 index_type: Vec<u8>,
828 },
829 /// DOC.DROPINDEX collection field — drop a secondary index.
830 DocDropIndex {
831 /// Collection name.
832 collection: Vec<u8>,
833 /// Dotted field path.
834 field: Vec<u8>,
835 },
836 /// DOC.INDEXES collection — list indexes.
837 DocIndexes {
838 /// Collection name.
839 collection: Vec<u8>,
840 },
841 /// DOC.FIND collection WHERE expr \[ORDER BY field \[ASC|DESC\]\] \[PROJECT f1 f2 ...\] \[LIMIT n\] \[OFFSET n\]
842 DocFind {
843 /// Collection name.
844 collection: Vec<u8>,
845 /// WHERE expression string.
846 where_clause: Vec<u8>,
847 /// Optional projection field paths.
848 fields: Vec<Vec<u8>>,
849 /// Optional result limit.
850 limit: Option<usize>,
851 /// Result offset (default 0).
852 offset: usize,
853 /// Optional field path to sort results by.
854 order_by: Option<Vec<u8>>,
855 /// True if sort order is descending (default ascending).
856 order_desc: bool,
857 },
858 /// DOC.COUNT collection WHERE expr
859 DocCount {
860 /// Collection name.
861 collection: Vec<u8>,
862 /// WHERE expression string.
863 where_clause: Vec<u8>,
864 },
865
866 // -- CDC commands --
867 /// CDCPOLL cursor count — poll CDC events from a shard.
868 CdcPoll {
869 /// Cursor position (sequence number).
870 cursor: u64,
871 /// Maximum events to return.
872 count: usize,
873 },
874 /// CDC.GROUP CREATE key group start\_seq — create a consumer group.
875 CdcGroupCreate {
876 /// The CDC stream key.
877 key: Vec<u8>,
878 /// Consumer group name.
879 group: String,
880 /// Starting sequence number.
881 start_seq: u64,
882 },
883 /// CDC.GROUP READ key group consumer count — read from a consumer group.
884 CdcGroupRead {
885 /// The CDC stream key.
886 key: Vec<u8>,
887 /// Consumer group name.
888 group: String,
889 /// Consumer name within the group.
890 consumer: String,
891 /// Maximum events to return.
892 count: usize,
893 },
894 /// CDC.ACK key group seq \[seq ...\] — acknowledge events.
895 CdcAck {
896 /// The CDC stream key.
897 key: Vec<u8>,
898 /// Consumer group name.
899 group: String,
900 /// Sequence numbers to acknowledge.
901 seqs: Vec<u64>,
902 },
903 /// CDC.PENDING key group — list pending entries.
904 CdcPending {
905 /// The CDC stream key.
906 key: Vec<u8>,
907 /// Consumer group name.
908 group: String,
909 },
910
911 // -- Vector commands --
912 /// VECSET key dim v1 v2 ... — store a vector.
913 VecSet {
914 /// The key.
915 key: Vec<u8>,
916 /// Vector dimensions.
917 dimensions: usize,
918 /// The vector components.
919 vector: Vec<f32>,
920 },
921 /// VECQUERY key k v1 v2 ... — query nearest neighbors.
922 VecQuery {
923 /// The index key.
924 key: Vec<u8>,
925 /// Number of neighbors.
926 k: usize,
927 /// Query vector.
928 vector: Vec<f32>,
929 },
930 /// VECDEL key — delete a vector.
931 VecDel {
932 /// The key.
933 key: Vec<u8>,
934 },
935
936 // -- Sorted Set commands --
937 /// ZADD key score member \[score member ...\]
938 ZAdd {
939 /// The key.
940 key: Vec<u8>,
941 /// Score-member pairs.
942 members: Vec<(f64, Vec<u8>)>,
943 },
944 /// ZREM key member \[member ...\]
945 ZRem {
946 /// The key.
947 key: Vec<u8>,
948 /// Members to remove.
949 members: Vec<Vec<u8>>,
950 },
951 /// ZSCORE key member
952 ZScore {
953 /// The key.
954 key: Vec<u8>,
955 /// The member.
956 member: Vec<u8>,
957 },
958 /// ZRANK key member
959 ZRank {
960 /// The key.
961 key: Vec<u8>,
962 /// The member.
963 member: Vec<u8>,
964 },
965 /// ZREVRANK key member
966 ZRevRank {
967 /// The key.
968 key: Vec<u8>,
969 /// The member.
970 member: Vec<u8>,
971 },
972 /// ZCARD key
973 ZCard {
974 /// The key.
975 key: Vec<u8>,
976 },
977 /// ZRANGE key start stop \[WITHSCORES\]
978 ZRange {
979 /// The key.
980 key: Vec<u8>,
981 /// Start index (0-based, negative from end).
982 start: i64,
983 /// Stop index (inclusive, negative from end).
984 stop: i64,
985 /// Whether to include scores in output.
986 withscores: bool,
987 },
988 /// ZREVRANGE key start stop \[WITHSCORES\]
989 ZRevRange {
990 /// The key.
991 key: Vec<u8>,
992 /// Start index (0-based, negative from end).
993 start: i64,
994 /// Stop index (inclusive, negative from end).
995 stop: i64,
996 /// Whether to include scores in output.
997 withscores: bool,
998 },
999 /// ZRANGEBYSCORE key min max \[WITHSCORES\] \[LIMIT offset count\]
1000 ZRangeByScore {
1001 /// The key.
1002 key: Vec<u8>,
1003 /// Minimum score (inclusive).
1004 min: f64,
1005 /// Maximum score (inclusive).
1006 max: f64,
1007 /// Whether to include scores in output.
1008 withscores: bool,
1009 /// Optional offset for LIMIT.
1010 offset: Option<usize>,
1011 /// Optional count for LIMIT.
1012 count: Option<usize>,
1013 },
1014 /// ZINCRBY key increment member
1015 ZIncrBy {
1016 /// The key.
1017 key: Vec<u8>,
1018 /// The increment amount.
1019 delta: f64,
1020 /// The member.
1021 member: Vec<u8>,
1022 },
1023 /// ZCOUNT key min max
1024 ZCount {
1025 /// The key.
1026 key: Vec<u8>,
1027 /// Minimum score (inclusive).
1028 min: f64,
1029 /// Maximum score (inclusive).
1030 max: f64,
1031 },
1032 /// ZREVRANGEBYSCORE key max min \[WITHSCORES\] \[LIMIT offset count\]
1033 ZRevRangeByScore {
1034 /// The key.
1035 key: Vec<u8>,
1036 /// Maximum score.
1037 max: f64,
1038 /// Minimum score.
1039 min: f64,
1040 /// Whether to include scores in output.
1041 withscores: bool,
1042 /// Optional offset for LIMIT.
1043 offset: Option<usize>,
1044 /// Optional count for LIMIT.
1045 count: Option<usize>,
1046 },
1047 /// ZPOPMIN key \[count\]
1048 ZPopMin {
1049 /// The key.
1050 key: Vec<u8>,
1051 /// Optional count of members to pop.
1052 count: Option<usize>,
1053 },
1054 /// ZPOPMAX key \[count\]
1055 ZPopMax {
1056 /// The key.
1057 key: Vec<u8>,
1058 /// Optional count of members to pop.
1059 count: Option<usize>,
1060 },
1061 /// ZRANGEBYLEX key min max \[LIMIT offset count\]
1062 ZRangeByLex {
1063 /// The key.
1064 key: Vec<u8>,
1065 /// Lexicographic minimum (e.g. "-", "\[a", "(a").
1066 min: Vec<u8>,
1067 /// Lexicographic maximum (e.g. "+", "\[z", "(z").
1068 max: Vec<u8>,
1069 /// Optional offset for LIMIT.
1070 offset: Option<usize>,
1071 /// Optional count for LIMIT.
1072 count: Option<usize>,
1073 },
1074 /// ZREVRANGEBYLEX key max min \[LIMIT offset count\]
1075 ZRevRangeByLex {
1076 /// The key.
1077 key: Vec<u8>,
1078 /// Lexicographic maximum.
1079 max: Vec<u8>,
1080 /// Lexicographic minimum.
1081 min: Vec<u8>,
1082 /// Optional offset for LIMIT.
1083 offset: Option<usize>,
1084 /// Optional count for LIMIT.
1085 count: Option<usize>,
1086 },
1087 /// ZLEXCOUNT key min max
1088 ZLexCount {
1089 /// The key.
1090 key: Vec<u8>,
1091 /// Lexicographic minimum.
1092 min: Vec<u8>,
1093 /// Lexicographic maximum.
1094 max: Vec<u8>,
1095 },
1096 /// ZMSCORE key member \[member ...\]
1097 ZMScore {
1098 /// The key.
1099 key: Vec<u8>,
1100 /// Members to query.
1101 members: Vec<Vec<u8>>,
1102 },
1103 /// ZRANDMEMBER key \[count \[WITHSCORES\]\]
1104 ZRandMember {
1105 /// The key.
1106 key: Vec<u8>,
1107 /// Optional count (negative = allow duplicates).
1108 count: Option<i64>,
1109 /// Whether to include scores.
1110 withscores: bool,
1111 },
1112 /// ZSCAN key cursor \[MATCH pattern\] \[COUNT count\]
1113 ZScan {
1114 /// The key.
1115 key: Vec<u8>,
1116 /// The cursor position.
1117 cursor: u64,
1118 /// Optional glob pattern filter.
1119 pattern: Option<String>,
1120 /// Optional count hint.
1121 count: Option<usize>,
1122 },
1123
1124 // -- Stream commands --
1125 /// XADD key \[MAXLEN count\] id field value \[field value ...\]
1126 XAdd {
1127 /// The key.
1128 key: Vec<u8>,
1129 /// The entry ID (usually "*" for auto-generate).
1130 id: Vec<u8>,
1131 /// Field-value pairs for the entry.
1132 fields: Vec<(Vec<u8>, Vec<u8>)>,
1133 /// Optional MAXLEN trimming threshold.
1134 maxlen: Option<usize>,
1135 },
1136 /// XLEN key
1137 XLen {
1138 /// The key.
1139 key: Vec<u8>,
1140 },
1141 /// XRANGE key start end \[COUNT count\]
1142 XRange {
1143 /// The key.
1144 key: Vec<u8>,
1145 /// Start ID (or "-" for minimum).
1146 start: Vec<u8>,
1147 /// End ID (or "+" for maximum).
1148 end: Vec<u8>,
1149 /// Optional maximum number of entries to return.
1150 count: Option<usize>,
1151 },
1152 /// XREVRANGE key end start \[COUNT count\]
1153 XRevRange {
1154 /// The key.
1155 key: Vec<u8>,
1156 /// Start ID (or "+" for maximum, reversed semantics).
1157 start: Vec<u8>,
1158 /// End ID (or "-" for minimum, reversed semantics).
1159 end: Vec<u8>,
1160 /// Optional maximum number of entries to return.
1161 count: Option<usize>,
1162 },
1163 /// XREAD \[COUNT count\] STREAMS key \[key ...\] id \[id ...\]
1164 XRead {
1165 /// Keys to read from.
1166 keys: Vec<Vec<u8>>,
1167 /// IDs to read after (one per key).
1168 ids: Vec<Vec<u8>>,
1169 /// Optional maximum number of entries per key.
1170 count: Option<usize>,
1171 },
1172 /// XTRIM key MAXLEN count
1173 XTrim {
1174 /// The key.
1175 key: Vec<u8>,
1176 /// Maximum number of entries to keep.
1177 maxlen: usize,
1178 },
1179
1180 // -- Object commands --
1181 /// OBJECT FREQ key — return the LFU frequency counter.
1182 ObjectFreq {
1183 /// The key.
1184 key: Vec<u8>,
1185 },
1186 /// OBJECT ENCODING key — return the encoding type.
1187 ObjectEncoding {
1188 /// The key.
1189 key: Vec<u8>,
1190 },
1191
1192 // -- Stats commands --
1193 /// STATS.HOTKEYS count — return top hot keys.
1194 StatsHotkeys {
1195 /// Number of hot keys to return.
1196 count: usize,
1197 },
1198 /// STATS.LATENCY command p1 p2 ... — return latency percentiles.
1199 StatsLatency {
1200 /// Command name (e.g. "GET").
1201 command: Vec<u8>,
1202 /// Percentile values to return (e.g. \[50.0, 99.0, 99.9\]).
1203 percentiles: Vec<f64>,
1204 },
1205 /// STATS.MEMORY prefix ... — return memory usage for key prefixes.
1206 StatsMemory {
1207 /// Key prefixes to query.
1208 prefixes: Vec<Vec<u8>>,
1209 },
1210
1211 // -- Pub/Sub commands --
1212 /// SUBSCRIBE channel \[channel ...\]
1213 Subscribe {
1214 /// Channels to subscribe to.
1215 channels: Vec<Vec<u8>>,
1216 },
1217 /// UNSUBSCRIBE \[channel ...\]
1218 Unsubscribe {
1219 /// Channels to unsubscribe from (empty = all).
1220 channels: Vec<Vec<u8>>,
1221 },
1222 /// PSUBSCRIBE pattern \[pattern ...\]
1223 PSubscribe {
1224 /// Glob patterns to subscribe to.
1225 patterns: Vec<Vec<u8>>,
1226 },
1227 /// PUNSUBSCRIBE \[pattern ...\]
1228 PUnsubscribe {
1229 /// Glob patterns to unsubscribe from (empty = all).
1230 patterns: Vec<Vec<u8>>,
1231 },
1232 /// PUBLISH channel message
1233 Publish {
1234 /// The target channel.
1235 channel: Vec<u8>,
1236 /// The message payload.
1237 message: Vec<u8>,
1238 },
1239
1240 // -- HyperLogLog commands --
1241 /// PFADD key element \[element ...\]
1242 PfAdd {
1243 /// The key.
1244 key: Vec<u8>,
1245 /// Elements to add to the HyperLogLog.
1246 elements: Vec<Vec<u8>>,
1247 },
1248 /// PFCOUNT key \[key ...\]
1249 PfCount {
1250 /// The keys to count (union cardinality when multiple).
1251 keys: Vec<Vec<u8>>,
1252 },
1253 /// PFMERGE destkey sourcekey \[sourcekey ...\]
1254 PfMerge {
1255 /// The destination key.
1256 destkey: Vec<u8>,
1257 /// The source keys to merge from.
1258 sourcekeys: Vec<Vec<u8>>,
1259 },
1260
1261 // -- Bitmap commands --
1262 /// SETBIT key offset value
1263 SetBit {
1264 /// The key.
1265 key: Vec<u8>,
1266 /// The bit offset.
1267 offset: u64,
1268 /// The bit value (0 or 1).
1269 value: u8,
1270 },
1271 /// GETBIT key offset
1272 GetBit {
1273 /// The key.
1274 key: Vec<u8>,
1275 /// The bit offset.
1276 offset: u64,
1277 },
1278 /// BITCOUNT key \[start end \[BYTE|BIT\]\]
1279 BitCount {
1280 /// The key.
1281 key: Vec<u8>,
1282 /// Optional start offset.
1283 start: Option<i64>,
1284 /// Optional end offset.
1285 end: Option<i64>,
1286 /// True if offsets are in bits, false (default) for bytes.
1287 use_bit: bool,
1288 },
1289 /// BITOP AND|OR|XOR|NOT destkey key \[key ...\]
1290 BitOp {
1291 /// The bitwise operation.
1292 operation: BitOperation,
1293 /// The destination key.
1294 destkey: Vec<u8>,
1295 /// The source keys.
1296 keys: Vec<Vec<u8>>,
1297 },
1298 /// BITPOS key bit \[start \[end \[BYTE|BIT\]\]\]
1299 BitPos {
1300 /// The key.
1301 key: Vec<u8>,
1302 /// The bit value to search for (0 or 1).
1303 bit: u8,
1304 /// Optional start offset.
1305 start: Option<i64>,
1306 /// Optional end offset.
1307 end: Option<i64>,
1308 /// True if offsets are in bits, false (default) for bytes.
1309 use_bit: bool,
1310 },
1311 /// BITFIELD key \[GET|SET|INCRBY|OVERFLOW ...\]
1312 BitField {
1313 /// The key.
1314 key: Vec<u8>,
1315 /// Ordered BITFIELD operations to execute.
1316 operations: Vec<BitFieldOperation>,
1317 },
1318
1319 // -- Geo commands --
1320 /// GEOADD key \[NX|XX\] \[CH\] longitude latitude member \[...\]
1321 GeoAdd {
1322 /// The key.
1323 key: Vec<u8>,
1324 /// Only add new members, don't update existing.
1325 nx: bool,
1326 /// Only update existing members, don't add new.
1327 xx: bool,
1328 /// Return number of changed elements instead of added.
1329 ch: bool,
1330 /// Longitude, latitude, member triples.
1331 members: Vec<(f64, f64, Vec<u8>)>,
1332 },
1333 /// GEODIST key member1 member2 \[m|km|ft|mi\]
1334 GeoDist {
1335 /// The key.
1336 key: Vec<u8>,
1337 /// First member.
1338 member1: Vec<u8>,
1339 /// Second member.
1340 member2: Vec<u8>,
1341 /// Distance unit (default: meters).
1342 unit: GeoUnit,
1343 },
1344 /// GEOHASH key member \[member ...\]
1345 GeoHash {
1346 /// The key.
1347 key: Vec<u8>,
1348 /// Members to get geohash strings for.
1349 members: Vec<Vec<u8>>,
1350 },
1351 /// GEOPOS key member \[member ...\]
1352 GeoPos {
1353 /// The key.
1354 key: Vec<u8>,
1355 /// Members to get positions for.
1356 members: Vec<Vec<u8>>,
1357 },
1358 /// GEOSEARCH key FROMMEMBER member|FROMLONLAT lon lat BYRADIUS radius unit \[ASC|DESC\] \[COUNT count\] \[WITHCOORD\] \[WITHDIST\] \[WITHHASH\]
1359 GeoSearch {
1360 /// The key.
1361 key: Vec<u8>,
1362 /// Member to search from (mutually exclusive with from\_lonlat).
1363 from_member: Option<Vec<u8>>,
1364 /// Longitude/latitude to search from (mutually exclusive with from\_member).
1365 from_lonlat: Option<(f64, f64)>,
1366 /// Search radius.
1367 radius: f64,
1368 /// Radius unit.
1369 unit: GeoUnit,
1370 /// Sort ascending if true, descending if false, unsorted if None.
1371 asc: Option<bool>,
1372 /// Maximum number of results.
1373 count: Option<usize>,
1374 /// Include coordinates in response.
1375 withcoord: bool,
1376 /// Include distance in response.
1377 withdist: bool,
1378 /// Include geohash in response.
1379 withhash: bool,
1380 },
1381
1382 // -- Blocking operations --
1383 /// BLPOP key \[key ...\] timeout
1384 BLPop {
1385 /// Keys to pop from (tried in order).
1386 keys: Vec<Vec<u8>>,
1387 /// Timeout in seconds (0 = try once).
1388 timeout: f64,
1389 },
1390 /// BRPOP key \[key ...\] timeout
1391 BRPop {
1392 /// Keys to pop from (tried in order).
1393 keys: Vec<Vec<u8>>,
1394 /// Timeout in seconds (0 = try once).
1395 timeout: f64,
1396 },
1397 /// BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout
1398 BLMove {
1399 /// The source key.
1400 source: Vec<u8>,
1401 /// The destination key.
1402 destination: Vec<u8>,
1403 /// Pop from left side of source if true, right if false.
1404 from_left: bool,
1405 /// Push to left side of destination if true, right if false.
1406 to_left: bool,
1407 /// Timeout in seconds (0 = try once).
1408 timeout: f64,
1409 },
1410 /// BZPOPMIN key \[key ...\] timeout
1411 BZPopMin {
1412 /// Keys to pop from (tried in order).
1413 keys: Vec<Vec<u8>>,
1414 /// Timeout in seconds (0 = try once).
1415 timeout: f64,
1416 },
1417 /// BZPOPMAX key \[key ...\] timeout
1418 BZPopMax {
1419 /// Keys to pop from (tried in order).
1420 keys: Vec<Vec<u8>>,
1421 /// Timeout in seconds (0 = try once).
1422 timeout: f64,
1423 },
1424
1425 // -- Stream consumer group commands --
1426 /// XGROUP CREATE key group id \[MKSTREAM\]
1427 XGroupCreate {
1428 /// The stream key.
1429 key: Vec<u8>,
1430 /// Consumer group name.
1431 group: String,
1432 /// Starting ID ("$" or "0" or specific ID).
1433 id: String,
1434 /// Create stream if it does not exist.
1435 mkstream: bool,
1436 },
1437 /// XGROUP DESTROY key group
1438 XGroupDestroy {
1439 /// The stream key.
1440 key: Vec<u8>,
1441 /// Consumer group name.
1442 group: String,
1443 },
1444 /// XGROUP DELCONSUMER key group consumer
1445 XGroupDelConsumer {
1446 /// The stream key.
1447 key: Vec<u8>,
1448 /// Consumer group name.
1449 group: String,
1450 /// Consumer name.
1451 consumer: String,
1452 },
1453 /// XREADGROUP GROUP group consumer \[COUNT count\] STREAMS key \[key ...\] id \[id ...\]
1454 XReadGroup {
1455 /// Consumer group name.
1456 group: String,
1457 /// Consumer name.
1458 consumer: String,
1459 /// Optional max entries per key.
1460 count: Option<usize>,
1461 /// Keys to read from.
1462 keys: Vec<Vec<u8>>,
1463 /// IDs to read after (one per key, ">" for new).
1464 ids: Vec<Vec<u8>>,
1465 },
1466 /// XACK key group id \[id ...\]
1467 XAck {
1468 /// The stream key.
1469 key: Vec<u8>,
1470 /// Consumer group name.
1471 group: String,
1472 /// IDs to acknowledge.
1473 ids: Vec<Vec<u8>>,
1474 },
1475 /// XPENDING key group \[start end count\]
1476 XPending {
1477 /// The stream key.
1478 key: Vec<u8>,
1479 /// Consumer group name.
1480 group: String,
1481 /// Optional start ID filter.
1482 start: Option<Vec<u8>>,
1483 /// Optional end ID filter.
1484 end: Option<Vec<u8>>,
1485 /// Optional count limit.
1486 count: Option<usize>,
1487 },
1488 /// XCLAIM key group consumer min-idle-time id \[id ...\]
1489 XClaim {
1490 /// The stream key.
1491 key: Vec<u8>,
1492 /// Consumer group name.
1493 group: String,
1494 /// Consumer claiming the messages.
1495 consumer: String,
1496 /// Minimum idle time in milliseconds.
1497 min_idle_time: u64,
1498 /// IDs to claim.
1499 ids: Vec<Vec<u8>>,
1500 },
1501 /// XAUTOCLAIM key group consumer min-idle-time start \[COUNT count\]
1502 XAutoClaim {
1503 /// The stream key.
1504 key: Vec<u8>,
1505 /// Consumer group name.
1506 group: String,
1507 /// Consumer claiming the messages.
1508 consumer: String,
1509 /// Minimum idle time in milliseconds.
1510 min_idle_time: u64,
1511 /// Start ID for scanning.
1512 start: Vec<u8>,
1513 /// Optional count of entries to claim.
1514 count: Option<usize>,
1515 },
1516 /// XINFO STREAM key
1517 XInfoStream {
1518 /// The stream key.
1519 key: Vec<u8>,
1520 },
1521 /// XINFO GROUPS key
1522 XInfoGroups {
1523 /// The stream key.
1524 key: Vec<u8>,
1525 },
1526 /// XDEL key id \[id ...\]
1527 XDel {
1528 /// The stream key.
1529 key: Vec<u8>,
1530 /// IDs to delete.
1531 ids: Vec<Vec<u8>>,
1532 },
1533}
1534
1535/// One `DOC.UPDATE` mutation operation.
1536#[derive(Debug, Clone, PartialEq)]
1537pub enum DocUpdateMutation {
1538 /// `SET path value` — set path to JSON value.
1539 Set {
1540 /// Dotted path bytes.
1541 path: Vec<u8>,
1542 /// JSON value bytes.
1543 value: Vec<u8>,
1544 },
1545 /// `DEL path` — remove path.
1546 Del {
1547 /// Dotted path bytes.
1548 path: Vec<u8>,
1549 },
1550 /// `INCR path delta` — increment numeric value at path.
1551 Incr {
1552 /// Dotted path bytes.
1553 path: Vec<u8>,
1554 /// Increment amount.
1555 delta: f64,
1556 },
1557 /// `PUSH path value` — append JSON value to array at path.
1558 Push {
1559 /// Dotted path bytes.
1560 path: Vec<u8>,
1561 /// JSON value bytes.
1562 value: Vec<u8>,
1563 },
1564 /// `PULL path value` — remove matching JSON value(s) from array at path.
1565 Pull {
1566 /// Dotted path bytes.
1567 path: Vec<u8>,
1568 /// JSON value bytes.
1569 value: Vec<u8>,
1570 },
1571}
1572
1573/// Bitwise operation for BITOP command.
1574#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1575pub enum BitOperation {
1576 /// Bitwise AND.
1577 And,
1578 /// Bitwise OR.
1579 Or,
1580 /// Bitwise XOR.
1581 Xor,
1582 /// Bitwise NOT (single source key).
1583 Not,
1584}
1585
1586/// Integer encoding used by BITFIELD subcommands.
1587#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1588pub struct BitFieldEncoding {
1589 /// Signed (`i`) when true, unsigned (`u`) when false.
1590 pub signed: bool,
1591 /// Bit width of the encoded integer.
1592 pub bits: u8,
1593}
1594
1595/// Offset format used by BITFIELD subcommands.
1596#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1597pub enum BitFieldOffset {
1598 /// Absolute bit offset (e.g. `0`).
1599 Absolute(i64),
1600 /// Type-scaled offset (e.g. `#2` multiplies by type width).
1601 Multiplied(i64),
1602}
1603
1604/// Overflow behavior for BITFIELD mutation operations.
1605#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1606pub enum BitFieldOverflow {
1607 /// Wrap around the representable range (default).
1608 Wrap,
1609 /// Clamp to minimum/maximum representable value.
1610 Sat,
1611 /// Do not apply the operation and return nil for that subcommand.
1612 Fail,
1613}
1614
1615/// A parsed BITFIELD subcommand.
1616#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1617pub enum BitFieldOperation {
1618 /// GET type offset
1619 Get {
1620 /// Integer encoding for the field.
1621 encoding: BitFieldEncoding,
1622 /// Bit offset to read from.
1623 offset: BitFieldOffset,
1624 },
1625 /// SET type offset value
1626 Set {
1627 /// Integer encoding for the field.
1628 encoding: BitFieldEncoding,
1629 /// Bit offset to write to.
1630 offset: BitFieldOffset,
1631 /// New value to assign.
1632 value: i64,
1633 },
1634 /// INCRBY type offset increment
1635 IncrBy {
1636 /// Integer encoding for the field.
1637 encoding: BitFieldEncoding,
1638 /// Bit offset to mutate.
1639 offset: BitFieldOffset,
1640 /// Amount to increment/decrement by.
1641 increment: i64,
1642 },
1643 /// OVERFLOW WRAP|SAT|FAIL
1644 Overflow(BitFieldOverflow),
1645}
1646
1647/// Distance unit for geo commands.
1648#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1649pub enum GeoUnit {
1650 /// Meters (default).
1651 Meters,
1652 /// Kilometers.
1653 Kilometers,
1654 /// Feet.
1655 Feet,
1656 /// Miles.
1657 Miles,
1658}
1659
1660impl Command {
1661 /// Extract the primary key for routing, if this is a single-key command.
1662 pub fn key(&self) -> Option<&[u8]> {
1663 match self {
1664 Command::Get { key }
1665 | Command::Set { key, .. }
1666 | Command::GetSet { key, .. }
1667 | Command::Append { key, .. }
1668 | Command::Strlen { key }
1669 | Command::Incr { key }
1670 | Command::Decr { key }
1671 | Command::IncrBy { key, .. }
1672 | Command::DecrBy { key, .. }
1673 | Command::SetNx { key, .. }
1674 | Command::Expire { key, .. }
1675 | Command::PExpire { key, .. }
1676 | Command::Persist { key }
1677 | Command::Ttl { key }
1678 | Command::PTtl { key }
1679 | Command::Type { key }
1680 | Command::LPush { key, .. }
1681 | Command::RPush { key, .. }
1682 | Command::LPop { key }
1683 | Command::RPop { key }
1684 | Command::LLen { key }
1685 | Command::LRange { key, .. }
1686 | Command::LIndex { key, .. }
1687 | Command::LSet { key, .. }
1688 | Command::LInsert { key, .. }
1689 | Command::LRem { key, .. }
1690 | Command::LTrim { key, .. }
1691 | Command::LPos { key, .. }
1692 | Command::RPopLPush { source: key, .. }
1693 | Command::LMove { source: key, .. }
1694 | Command::HSet { key, .. }
1695 | Command::HGet { key, .. }
1696 | Command::HDel { key, .. }
1697 | Command::HGetAll { key }
1698 | Command::HLen { key }
1699 | Command::HExists { key, .. }
1700 | Command::HIncrBy { key, .. }
1701 | Command::HMGet { key, .. }
1702 | Command::HKeys { key }
1703 | Command::HVals { key }
1704 | Command::HSetNx { key, .. }
1705 | Command::HIncrByFloat { key, .. }
1706 | Command::HRandField { key, .. }
1707 | Command::HScan { key, .. }
1708 | Command::SAdd { key, .. }
1709 | Command::SRem { key, .. }
1710 | Command::SMembers { key }
1711 | Command::SIsMember { key, .. }
1712 | Command::SCard { key }
1713 | Command::SPop { key, .. }
1714 | Command::SRandMember { key, .. }
1715 | Command::SMove { source: key, .. }
1716 | Command::SMisMember { key, .. }
1717 | Command::SScan { key, .. }
1718 | Command::ZAdd { key, .. }
1719 | Command::ZRem { key, .. }
1720 | Command::ZScore { key, .. }
1721 | Command::ZRank { key, .. }
1722 | Command::ZRevRank { key, .. }
1723 | Command::ZCard { key }
1724 | Command::ZRange { key, .. }
1725 | Command::ZRevRange { key, .. }
1726 | Command::ZRangeByScore { key, .. }
1727 | Command::ZIncrBy { key, .. }
1728 | Command::ZCount { key, .. }
1729 | Command::ZRevRangeByScore { key, .. }
1730 | Command::ZPopMin { key, .. }
1731 | Command::ZPopMax { key, .. }
1732 | Command::ZRangeByLex { key, .. }
1733 | Command::ZRevRangeByLex { key, .. }
1734 | Command::ZLexCount { key, .. }
1735 | Command::ZMScore { key, .. }
1736 | Command::ZRandMember { key, .. }
1737 | Command::ZScan { key, .. }
1738 | Command::VecSet { key, .. }
1739 | Command::VecDel { key }
1740 | Command::XAdd { key, .. }
1741 | Command::XLen { key }
1742 | Command::XRange { key, .. }
1743 | Command::XRevRange { key, .. }
1744 | Command::XTrim { key, .. }
1745 | Command::ObjectFreq { key }
1746 | Command::ObjectEncoding { key }
1747 | Command::ObjectRefCount { key }
1748 | Command::ObjectIdleTime { key }
1749 | Command::IncrByFloat { key, .. }
1750 | Command::GetRange { key, .. }
1751 | Command::SetRange { key, .. }
1752 | Command::GetDel { key }
1753 | Command::GetEx { key, .. }
1754 | Command::ExpireAt { key, .. }
1755 | Command::PExpireAt { key, .. }
1756 | Command::Rename { key, .. }
1757 | Command::RenameNx { key, .. }
1758 | Command::Copy { source: key, .. }
1759 | Command::PfAdd { key, .. }
1760 | Command::SetBit { key, .. }
1761 | Command::GetBit { key, .. }
1762 | Command::BitCount { key, .. }
1763 | Command::BitPos { key, .. }
1764 | Command::BitField { key, .. }
1765 | Command::GeoAdd { key, .. }
1766 | Command::GeoDist { key, .. }
1767 | Command::GeoHash { key, .. }
1768 | Command::GeoPos { key, .. }
1769 | Command::GeoSearch { key, .. }
1770 | Command::BLMove { source: key, .. }
1771 | Command::XGroupCreate { key, .. }
1772 | Command::XGroupDestroy { key, .. }
1773 | Command::XGroupDelConsumer { key, .. }
1774 | Command::XAck { key, .. }
1775 | Command::XPending { key, .. }
1776 | Command::XClaim { key, .. }
1777 | Command::XAutoClaim { key, .. }
1778 | Command::XInfoStream { key }
1779 | Command::XInfoGroups { key }
1780 | Command::XDel { key, .. } => Some(key),
1781 Command::PfCount { keys } => {
1782 if keys.len() == 1 {
1783 Some(&keys[0])
1784 } else {
1785 None
1786 }
1787 }
1788 Command::VecQuery { .. } => None,
1789 _ => None,
1790 }
1791 }
1792
1793 /// Returns true if this command operates on multiple keys that may span shards.
1794 pub fn is_multi_key(&self) -> bool {
1795 matches!(
1796 self,
1797 Command::MGet { .. }
1798 | Command::MSet { .. }
1799 | Command::Del { .. }
1800 | Command::Exists { .. }
1801 | Command::XRead { .. }
1802 | Command::MSetNx { .. }
1803 | Command::Unlink { .. }
1804 | Command::Touch { .. }
1805 | Command::SUnion { .. }
1806 | Command::SUnionStore { .. }
1807 | Command::SInter { .. }
1808 | Command::SInterStore { .. }
1809 | Command::SDiff { .. }
1810 | Command::SDiffStore { .. }
1811 | Command::SInterCard { .. }
1812 | Command::PfMerge { .. }
1813 | Command::BitOp { .. }
1814 | Command::BLPop { .. }
1815 | Command::BRPop { .. }
1816 | Command::BZPopMin { .. }
1817 | Command::BZPopMax { .. }
1818 | Command::XReadGroup { .. }
1819 ) || matches!(self, Command::PfCount { keys } if keys.len() > 1)
1820 }
1821
1822 /// Returns true if this is a keyless/server command.
1823 pub fn is_keyless(&self) -> bool {
1824 matches!(
1825 self,
1826 Command::Ping { .. }
1827 | Command::Echo { .. }
1828 | Command::Info { .. }
1829 | Command::DbSize
1830 | Command::FlushDb
1831 | Command::FlushAll
1832 | Command::Keys { .. }
1833 | Command::Scan { .. }
1834 | Command::BgSave
1835 | Command::BgRewriteAof
1836 | Command::CommandInfo { .. }
1837 | Command::Hello { .. }
1838 | Command::Auth { .. }
1839 | Command::Dump
1840 | Command::CdcPoll { .. }
1841 | Command::CdcGroupCreate { .. }
1842 | Command::CdcGroupRead { .. }
1843 | Command::CdcAck { .. }
1844 | Command::CdcPending { .. }
1845 | Command::StatsHotkeys { .. }
1846 | Command::StatsLatency { .. }
1847 | Command::StatsMemory { .. }
1848 | Command::Subscribe { .. }
1849 | Command::Unsubscribe { .. }
1850 | Command::PSubscribe { .. }
1851 | Command::PUnsubscribe { .. }
1852 | Command::Publish { .. }
1853 | Command::RandomKey
1854 | Command::ObjectHelp
1855 | Command::Multi
1856 | Command::Exec
1857 | Command::Discard
1858 | Command::Watch { .. }
1859 | Command::Unwatch
1860 | Command::ConfigGet { .. }
1861 | Command::ConfigSet { .. }
1862 | Command::ConfigResetStat
1863 | Command::ClientId
1864 | Command::ClientGetName
1865 | Command::ClientSetName { .. }
1866 | Command::ClientList
1867 | Command::ClientInfo
1868 | Command::Time
1869 | Command::Select { .. }
1870 | Command::Quit
1871 | Command::Wait { .. }
1872 | Command::CommandCount
1873 | Command::CommandList
1874 | Command::CommandHelp
1875 | Command::CommandDocs { .. }
1876 | Command::DocCreate { .. }
1877 | Command::DocDrop { .. }
1878 | Command::DocInfo { .. }
1879 | Command::DocDictInfo { .. }
1880 | Command::DocStorage { .. }
1881 | Command::DocSet { .. }
1882 | Command::DocInsert { .. }
1883 | Command::DocMSet { .. }
1884 | Command::DocGet { .. }
1885 | Command::DocMGet { .. }
1886 | Command::DocUpdate { .. }
1887 | Command::DocDel { .. }
1888 | Command::DocExists { .. }
1889 | Command::DocCreateIndex { .. }
1890 | Command::DocDropIndex { .. }
1891 | Command::DocIndexes { .. }
1892 | Command::DocFind { .. }
1893 | Command::DocCount { .. }
1894 )
1895 }
1896
1897 /// Returns true if this command mutates data (for WAL logging).
1898 pub fn is_mutation(&self) -> bool {
1899 matches!(
1900 self,
1901 Command::Set { .. }
1902 | Command::GetSet { .. }
1903 | Command::Append { .. }
1904 | Command::Incr { .. }
1905 | Command::Decr { .. }
1906 | Command::IncrBy { .. }
1907 | Command::DecrBy { .. }
1908 | Command::MSet { .. }
1909 | Command::SetNx { .. }
1910 | Command::Del { .. }
1911 | Command::Expire { .. }
1912 | Command::PExpire { .. }
1913 | Command::Persist { .. }
1914 | Command::FlushDb
1915 | Command::FlushAll
1916 | Command::LPush { .. }
1917 | Command::RPush { .. }
1918 | Command::LPop { .. }
1919 | Command::RPop { .. }
1920 | Command::LSet { .. }
1921 | Command::LInsert { .. }
1922 | Command::LRem { .. }
1923 | Command::LTrim { .. }
1924 | Command::RPopLPush { .. }
1925 | Command::LMove { .. }
1926 | Command::HSet { .. }
1927 | Command::HDel { .. }
1928 | Command::HIncrBy { .. }
1929 | Command::HSetNx { .. }
1930 | Command::HIncrByFloat { .. }
1931 | Command::SAdd { .. }
1932 | Command::SRem { .. }
1933 | Command::SPop { .. }
1934 | Command::SUnionStore { .. }
1935 | Command::SInterStore { .. }
1936 | Command::SDiffStore { .. }
1937 | Command::SMove { .. }
1938 | Command::ZAdd { .. }
1939 | Command::ZRem { .. }
1940 | Command::ZIncrBy { .. }
1941 | Command::ZPopMin { .. }
1942 | Command::ZPopMax { .. }
1943 | Command::VecSet { .. }
1944 | Command::VecDel { .. }
1945 | Command::XAdd { .. }
1946 | Command::XTrim { .. }
1947 | Command::IncrByFloat { .. }
1948 | Command::SetRange { .. }
1949 | Command::GetDel { .. }
1950 | Command::GetEx { .. }
1951 | Command::MSetNx { .. }
1952 | Command::ExpireAt { .. }
1953 | Command::PExpireAt { .. }
1954 | Command::Rename { .. }
1955 | Command::RenameNx { .. }
1956 | Command::Unlink { .. }
1957 | Command::Copy { .. }
1958 | Command::PfAdd { .. }
1959 | Command::PfMerge { .. }
1960 | Command::SetBit { .. }
1961 | Command::BitOp { .. }
1962 | Command::GeoAdd { .. }
1963 | Command::BLPop { .. }
1964 | Command::BRPop { .. }
1965 | Command::BLMove { .. }
1966 | Command::BZPopMin { .. }
1967 | Command::BZPopMax { .. }
1968 | Command::XGroupCreate { .. }
1969 | Command::XGroupDestroy { .. }
1970 | Command::XGroupDelConsumer { .. }
1971 | Command::XAck { .. }
1972 | Command::XClaim { .. }
1973 | Command::XAutoClaim { .. }
1974 | Command::XDel { .. }
1975 | Command::DocCreate { .. }
1976 | Command::DocDrop { .. }
1977 | Command::DocSet { .. }
1978 | Command::DocInsert { .. }
1979 | Command::DocMSet { .. }
1980 | Command::DocUpdate { .. }
1981 | Command::DocDel { .. }
1982 | Command::DocCreateIndex { .. }
1983 | Command::DocDropIndex { .. }
1984 )
1985 }
1986
1987 /// Return a numeric type index for stats tracking.
1988 pub fn cmd_type(&self) -> u8 {
1989 match self {
1990 Command::Get { .. } => 0,
1991 Command::Set { .. } => 1,
1992 Command::Del { .. } | Command::Unlink { .. } => 2,
1993 Command::Incr { .. } | Command::IncrBy { .. } | Command::IncrByFloat { .. } => 3,
1994 Command::Decr { .. } | Command::DecrBy { .. } => 4,
1995 Command::MGet { .. } => 5,
1996 Command::MSet { .. } | Command::MSetNx { .. } => 6,
1997 Command::Exists { .. } => 7,
1998 Command::Expire { .. }
1999 | Command::PExpire { .. }
2000 | Command::ExpireAt { .. }
2001 | Command::PExpireAt { .. } => 8,
2002 Command::Ttl { .. } | Command::PTtl { .. } => 9,
2003 Command::LPush { .. } => 10,
2004 Command::RPush { .. } => 11,
2005 Command::LPop { .. } => 12,
2006 Command::RPop { .. } => 13,
2007 Command::HSet { .. } | Command::HSetNx { .. } => 14,
2008 Command::HGet { .. } | Command::HMGet { .. } => 15,
2009 Command::HGetAll { .. } | Command::HKeys { .. } | Command::HVals { .. } => 16,
2010 Command::SAdd { .. } => 17,
2011 Command::SRem { .. } | Command::SPop { .. } => 18,
2012 Command::SRandMember { .. } | Command::SMisMember { .. } | Command::SScan { .. } => 40,
2013 Command::SUnion { .. }
2014 | Command::SUnionStore { .. }
2015 | Command::SInter { .. }
2016 | Command::SInterStore { .. }
2017 | Command::SDiff { .. }
2018 | Command::SDiffStore { .. }
2019 | Command::SInterCard { .. }
2020 | Command::SMove { .. } => 41,
2021 Command::Ping { .. } => 19,
2022 Command::Info { .. } => 20,
2023 Command::DbSize => 21,
2024 Command::FlushDb | Command::FlushAll => 22,
2025 Command::Keys { .. } | Command::Scan { .. } => 23,
2026 Command::VecSet { .. } => 24,
2027 Command::VecQuery { .. } => 25,
2028 Command::ZAdd { .. } => 27,
2029 Command::ZRange { .. }
2030 | Command::ZRevRange { .. }
2031 | Command::ZRangeByScore { .. }
2032 | Command::ZRevRangeByScore { .. }
2033 | Command::ZRangeByLex { .. }
2034 | Command::ZRevRangeByLex { .. } => 28,
2035 Command::ZScore { .. }
2036 | Command::ZRank { .. }
2037 | Command::ZRevRank { .. }
2038 | Command::ZCard { .. }
2039 | Command::ZCount { .. }
2040 | Command::ZLexCount { .. }
2041 | Command::ZMScore { .. } => 29,
2042 Command::ZRem { .. }
2043 | Command::ZIncrBy { .. }
2044 | Command::ZPopMin { .. }
2045 | Command::ZPopMax { .. } => 30,
2046 Command::ZRandMember { .. } | Command::ZScan { .. } => 42,
2047 Command::ObjectFreq { .. }
2048 | Command::ObjectEncoding { .. }
2049 | Command::ObjectRefCount { .. }
2050 | Command::ObjectIdleTime { .. }
2051 | Command::ObjectHelp => 31,
2052 Command::XAdd { .. } | Command::XTrim { .. } => 33,
2053 Command::XLen { .. }
2054 | Command::XRange { .. }
2055 | Command::XRevRange { .. }
2056 | Command::XRead { .. } => 34,
2057 Command::Subscribe { .. }
2058 | Command::Unsubscribe { .. }
2059 | Command::PSubscribe { .. }
2060 | Command::PUnsubscribe { .. }
2061 | Command::Publish { .. } => 35,
2062 Command::LSet { .. }
2063 | Command::LInsert { .. }
2064 | Command::LRem { .. }
2065 | Command::LTrim { .. } => 36,
2066 Command::LPos { .. } => 37,
2067 Command::RPopLPush { .. } | Command::LMove { .. } => 38,
2068 Command::HRandField { .. } | Command::HScan { .. } => 39,
2069 Command::PfAdd { .. } | Command::PfCount { .. } | Command::PfMerge { .. } => 43,
2070 Command::SetBit { .. }
2071 | Command::GetBit { .. }
2072 | Command::BitCount { .. }
2073 | Command::BitOp { .. }
2074 | Command::BitPos { .. }
2075 | Command::BitField { .. } => 44,
2076 Command::GeoAdd { .. }
2077 | Command::GeoDist { .. }
2078 | Command::GeoHash { .. }
2079 | Command::GeoPos { .. }
2080 | Command::GeoSearch { .. } => 45,
2081 Command::Multi
2082 | Command::Exec
2083 | Command::Discard
2084 | Command::Watch { .. }
2085 | Command::Unwatch => 46,
2086 Command::ConfigGet { .. }
2087 | Command::ConfigSet { .. }
2088 | Command::ConfigResetStat
2089 | Command::ClientId
2090 | Command::ClientGetName
2091 | Command::ClientSetName { .. }
2092 | Command::ClientList
2093 | Command::ClientInfo
2094 | Command::Time
2095 | Command::Select { .. }
2096 | Command::Quit
2097 | Command::Wait { .. }
2098 | Command::CommandCount
2099 | Command::CommandList
2100 | Command::CommandHelp
2101 | Command::CommandDocs { .. } => 47,
2102 Command::BLPop { .. }
2103 | Command::BRPop { .. }
2104 | Command::BLMove { .. }
2105 | Command::BZPopMin { .. }
2106 | Command::BZPopMax { .. } => 48,
2107 Command::XGroupCreate { .. }
2108 | Command::XGroupDestroy { .. }
2109 | Command::XGroupDelConsumer { .. }
2110 | Command::XReadGroup { .. }
2111 | Command::XAck { .. }
2112 | Command::XPending { .. }
2113 | Command::XClaim { .. }
2114 | Command::XAutoClaim { .. }
2115 | Command::XInfoStream { .. }
2116 | Command::XInfoGroups { .. }
2117 | Command::XDel { .. } => 49,
2118 Command::DocCreate { .. }
2119 | Command::DocDrop { .. }
2120 | Command::DocInfo { .. }
2121 | Command::DocDictInfo { .. }
2122 | Command::DocStorage { .. }
2123 | Command::DocSet { .. }
2124 | Command::DocInsert { .. }
2125 | Command::DocMSet { .. }
2126 | Command::DocGet { .. }
2127 | Command::DocMGet { .. }
2128 | Command::DocUpdate { .. }
2129 | Command::DocDel { .. }
2130 | Command::DocExists { .. }
2131 | Command::DocCreateIndex { .. }
2132 | Command::DocDropIndex { .. }
2133 | Command::DocIndexes { .. }
2134 | Command::DocFind { .. }
2135 | Command::DocCount { .. } => 50,
2136 _ => 32,
2137 }
2138 }
2139
2140 /// Get the TTL duration from EX/PX options.
2141 pub fn ttl_duration(ex: Option<u64>, px: Option<u64>) -> Option<Duration> {
2142 if let Some(s) = ex {
2143 Some(Duration::from_secs(s))
2144 } else {
2145 px.map(Duration::from_millis)
2146 }
2147 }
2148}
2149
2150/// Canonical supported command names exposed by `COMMAND LIST`.
2151///
2152/// Names are lowercase and sorted for binary search.
2153pub const SUPPORTED_COMMAND_NAMES: &[&str] = &[
2154 "append",
2155 "auth",
2156 "bgrewriteaof",
2157 "bgsave",
2158 "bitcount",
2159 "bitfield",
2160 "bitop",
2161 "bitpos",
2162 "blmove",
2163 "blpop",
2164 "brpop",
2165 "bzpopmax",
2166 "bzpopmin",
2167 "cdc.ack",
2168 "cdc.group",
2169 "cdc.pending",
2170 "cdcpoll",
2171 "client",
2172 "command",
2173 "config",
2174 "copy",
2175 "dbsize",
2176 "decr",
2177 "decrby",
2178 "del",
2179 "discard",
2180 "doc.count",
2181 "doc.create",
2182 "doc.createindex",
2183 "doc.del",
2184 "doc.dictinfo",
2185 "doc.drop",
2186 "doc.dropindex",
2187 "doc.exists",
2188 "doc.find",
2189 "doc.get",
2190 "doc.indexes",
2191 "doc.info",
2192 "doc.mget",
2193 "doc.mset",
2194 "doc.set",
2195 "doc.storage",
2196 "doc.update",
2197 "dump",
2198 "echo",
2199 "exec",
2200 "exists",
2201 "expire",
2202 "expireat",
2203 "flushall",
2204 "flushdb",
2205 "geoadd",
2206 "geodist",
2207 "geohash",
2208 "geopos",
2209 "geosearch",
2210 "get",
2211 "getbit",
2212 "getdel",
2213 "getex",
2214 "getrange",
2215 "getset",
2216 "hdel",
2217 "hello",
2218 "hexists",
2219 "hget",
2220 "hgetall",
2221 "hincrby",
2222 "hincrbyfloat",
2223 "hkeys",
2224 "hlen",
2225 "hmget",
2226 "hmset",
2227 "hrandfield",
2228 "hscan",
2229 "hset",
2230 "hsetnx",
2231 "hvals",
2232 "incr",
2233 "incrby",
2234 "incrbyfloat",
2235 "info",
2236 "keys",
2237 "lindex",
2238 "linsert",
2239 "llen",
2240 "lmove",
2241 "lpop",
2242 "lpos",
2243 "lpush",
2244 "lrange",
2245 "lrem",
2246 "lset",
2247 "ltrim",
2248 "mget",
2249 "mset",
2250 "msetnx",
2251 "multi",
2252 "object",
2253 "persist",
2254 "pexpire",
2255 "pexpireat",
2256 "pfadd",
2257 "pfcount",
2258 "pfmerge",
2259 "ping",
2260 "psetex",
2261 "psubscribe",
2262 "pttl",
2263 "publish",
2264 "punsubscribe",
2265 "quit",
2266 "randomkey",
2267 "rename",
2268 "renamenx",
2269 "rpop",
2270 "rpoplpush",
2271 "rpush",
2272 "sadd",
2273 "scan",
2274 "scard",
2275 "sdiff",
2276 "sdiffstore",
2277 "select",
2278 "set",
2279 "setbit",
2280 "setex",
2281 "setnx",
2282 "setrange",
2283 "sinter",
2284 "sintercard",
2285 "sinterstore",
2286 "sismember",
2287 "smembers",
2288 "smismember",
2289 "smove",
2290 "spop",
2291 "srandmember",
2292 "srem",
2293 "sscan",
2294 "stats.hotkeys",
2295 "stats.latency",
2296 "stats.memory",
2297 "strlen",
2298 "subscribe",
2299 "substr",
2300 "sunion",
2301 "sunionstore",
2302 "time",
2303 "touch",
2304 "ttl",
2305 "type",
2306 "unlink",
2307 "unsubscribe",
2308 "unwatch",
2309 "vecdel",
2310 "vecquery",
2311 "vecset",
2312 "wait",
2313 "watch",
2314 "xack",
2315 "xadd",
2316 "xautoclaim",
2317 "xclaim",
2318 "xdel",
2319 "xgroup",
2320 "xinfo",
2321 "xlen",
2322 "xpending",
2323 "xrange",
2324 "xread",
2325 "xreadgroup",
2326 "xrevrange",
2327 "xtrim",
2328 "zadd",
2329 "zcard",
2330 "zcount",
2331 "zincrby",
2332 "zlexcount",
2333 "zmscore",
2334 "zpopmax",
2335 "zpopmin",
2336 "zrandmember",
2337 "zrange",
2338 "zrangebylex",
2339 "zrangebyscore",
2340 "zrank",
2341 "zrem",
2342 "zrevrange",
2343 "zrevrangebylex",
2344 "zrevrangebyscore",
2345 "zrevrank",
2346 "zscan",
2347 "zscore",
2348];
2349
2350/// Human-readable help text for the `COMMAND HELP` reply.
2351pub const COMMAND_HELP_LINES: &[&str] = &[
2352 "COMMAND <subcommand> [<arg> [value] [opt] ...]. Subcommands are:",
2353 "(no subcommand)",
2354 " Return details about all Kora commands.",
2355 "COUNT",
2356 " Return the total number of commands in this Kora server.",
2357 "LIST",
2358 " Return a list of all commands in this Kora server.",
2359 "INFO [<command-name> ...]",
2360 " Return details about multiple Kora commands.",
2361 "DOCS [<command-name> ...]",
2362 " Return documentation details about multiple Kora commands.",
2363 "HELP",
2364 " Print this help.",
2365];
2366
2367/// Returns the number of supported command names.
2368pub fn supported_command_count() -> i64 {
2369 SUPPORTED_COMMAND_NAMES.len() as i64
2370}
2371
2372fn normalize_command_name(name: &[u8]) -> String {
2373 String::from_utf8_lossy(name).to_ascii_lowercase()
2374}
2375
2376fn command_supported(name: &str) -> bool {
2377 SUPPORTED_COMMAND_NAMES.binary_search(&name).is_ok()
2378}
2379
2380fn command_info_entry(name: &str) -> CommandResponse {
2381 CommandResponse::Array(vec![
2382 CommandResponse::BulkString(name.as_bytes().to_vec()),
2383 CommandResponse::Integer(-1),
2384 CommandResponse::Array(vec![CommandResponse::BulkString(b"fast".to_vec())]),
2385 CommandResponse::Integer(0),
2386 CommandResponse::Integer(0),
2387 CommandResponse::Integer(0),
2388 CommandResponse::Array(vec![CommandResponse::BulkString(b"@kora".to_vec())]),
2389 CommandResponse::Array(vec![]),
2390 CommandResponse::Array(vec![]),
2391 CommandResponse::Array(vec![]),
2392 ])
2393}
2394
2395/// Build a `COMMAND INFO`/`COMMAND` response.
2396pub fn command_info_response(names: &[Vec<u8>]) -> CommandResponse {
2397 if names.is_empty() {
2398 return CommandResponse::Array(
2399 SUPPORTED_COMMAND_NAMES
2400 .iter()
2401 .map(|name| command_info_entry(name))
2402 .collect(),
2403 );
2404 }
2405
2406 let mut entries = Vec::with_capacity(names.len());
2407 for name in names {
2408 let normalized = normalize_command_name(name);
2409 if command_supported(&normalized) {
2410 entries.push(command_info_entry(&normalized));
2411 } else {
2412 entries.push(CommandResponse::Nil);
2413 }
2414 }
2415 CommandResponse::Array(entries)
2416}
2417
2418/// Build a `COMMAND LIST` response.
2419pub fn command_list_response() -> CommandResponse {
2420 CommandResponse::Array(
2421 SUPPORTED_COMMAND_NAMES
2422 .iter()
2423 .map(|name| CommandResponse::BulkString(name.as_bytes().to_vec()))
2424 .collect(),
2425 )
2426}
2427
2428fn command_docs_entry(name: &str) -> CommandResponse {
2429 CommandResponse::Map(vec![
2430 (
2431 CommandResponse::BulkString(b"summary".to_vec()),
2432 CommandResponse::BulkString(format!("Kora implementation of `{}`.", name).into_bytes()),
2433 ),
2434 (
2435 CommandResponse::BulkString(b"since".to_vec()),
2436 CommandResponse::BulkString(b"0.1.0".to_vec()),
2437 ),
2438 (
2439 CommandResponse::BulkString(b"group".to_vec()),
2440 CommandResponse::BulkString(b"generic".to_vec()),
2441 ),
2442 ])
2443}
2444
2445/// Build a `COMMAND DOCS` response.
2446pub fn command_docs_response(names: &[Vec<u8>]) -> CommandResponse {
2447 let mut docs = Vec::new();
2448
2449 if names.is_empty() {
2450 docs.reserve(SUPPORTED_COMMAND_NAMES.len());
2451 for name in SUPPORTED_COMMAND_NAMES {
2452 docs.push((
2453 CommandResponse::BulkString(name.as_bytes().to_vec()),
2454 command_docs_entry(name),
2455 ));
2456 }
2457 return CommandResponse::Map(docs);
2458 }
2459
2460 for name in names {
2461 let normalized = normalize_command_name(name);
2462 if command_supported(&normalized) {
2463 docs.push((
2464 CommandResponse::BulkString(normalized.as_bytes().to_vec()),
2465 command_docs_entry(&normalized),
2466 ));
2467 }
2468 }
2469 CommandResponse::Map(docs)
2470}
2471
2472/// Build a `COMMAND HELP` response.
2473pub fn command_help_response() -> CommandResponse {
2474 CommandResponse::Array(
2475 COMMAND_HELP_LINES
2476 .iter()
2477 .map(|line| CommandResponse::BulkString(line.as_bytes().to_vec()))
2478 .collect(),
2479 )
2480}
2481
2482/// Response from executing a command on a shard.
2483#[derive(Debug, Clone, PartialEq)]
2484pub enum CommandResponse {
2485 /// +OK
2486 Ok,
2487 /// Null bulk string ($-1)
2488 Nil,
2489 /// Integer reply
2490 Integer(i64),
2491 /// Bulk string
2492 BulkString(Vec<u8>),
2493 /// Bulk string backed by shared bytes to avoid copying large values on reads.
2494 BulkStringShared(Arc<[u8]>),
2495 /// Simple string (without the +)
2496 SimpleString(String),
2497 /// Array of responses
2498 Array(Vec<CommandResponse>),
2499 /// Error message
2500 Error(String),
2501 /// RESP3 Map (key-value pairs)
2502 Map(Vec<(CommandResponse, CommandResponse)>),
2503 /// RESP3 Set (unique values)
2504 Set(Vec<CommandResponse>),
2505 /// RESP3 Double (floating-point)
2506 Double(f64),
2507 /// RESP3 Boolean
2508 Boolean(bool),
2509}
2510
2511impl CommandResponse {
2512 /// Returns the bulk-string payload if this response contains one.
2513 pub fn bulk_string_bytes(&self) -> Option<&[u8]> {
2514 match self {
2515 CommandResponse::BulkString(data) => Some(data),
2516 CommandResponse::BulkStringShared(data) => Some(data),
2517 _ => None,
2518 }
2519 }
2520
2521 /// Consumes the response and returns an owned bulk-string payload when present.
2522 pub fn into_bulk_string_bytes(self) -> Option<Vec<u8>> {
2523 match self {
2524 CommandResponse::BulkString(data) => Some(data),
2525 CommandResponse::BulkStringShared(data) => Some(data.as_ref().to_vec()),
2526 _ => None,
2527 }
2528 }
2529}