Skip to main content

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}