Skip to main content

ember_protocol/command/
mod.rs

1//! Command parsing from RESP3 frames.
2//!
3//! Converts a parsed [`Frame`] (expected to be an array) into a typed
4//! [`Command`] enum. This keeps protocol-level concerns separate from
5//! the engine that actually executes commands.
6
7use bytes::Bytes;
8
9/// Expiration option for the SET command.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum SetExpire {
12    /// EX seconds — expire after N seconds.
13    Ex(u64),
14    /// PX milliseconds — expire after N milliseconds.
15    Px(u64),
16}
17
18/// A parsed client command, ready for execution.
19#[derive(Debug, Clone, PartialEq)]
20pub enum Command {
21    /// PING with an optional message. Returns PONG or echoes the message.
22    Ping(Option<Bytes>),
23
24    /// ECHO `message`. Returns the message back to the client.
25    Echo(Bytes),
26
27    /// GET `key`. Returns the value or nil.
28    Get { key: String },
29
30    /// SET `key` `value` \[EX seconds | PX milliseconds\] \[NX | XX\].
31    Set {
32        key: String,
33        value: Bytes,
34        expire: Option<SetExpire>,
35        /// Only set the key if it does not already exist.
36        nx: bool,
37        /// Only set the key if it already exists.
38        xx: bool,
39    },
40
41    /// INCR `key`. Increments the integer value of a key by 1.
42    Incr { key: String },
43
44    /// DECR `key`. Decrements the integer value of a key by 1.
45    Decr { key: String },
46
47    /// INCRBY `key` `increment`. Increments the integer value of a key by the given amount.
48    IncrBy { key: String, delta: i64 },
49
50    /// DECRBY `key` `decrement`. Decrements the integer value of a key by the given amount.
51    DecrBy { key: String, delta: i64 },
52
53    /// INCRBYFLOAT `key` `increment`. Increments the float value of a key by the given amount.
54    IncrByFloat { key: String, delta: f64 },
55
56    /// APPEND `key` `value`. Appends a value to a string key. Returns the new length.
57    Append { key: String, value: Bytes },
58
59    /// STRLEN `key`. Returns the length of the string value stored at key.
60    Strlen { key: String },
61
62    /// GETRANGE `key` `start` `end`. Returns a substring of the string at key.
63    GetRange { key: String, start: i64, end: i64 },
64
65    /// SETRANGE `key` `offset` `value`. Overwrites part of the string at key.
66    SetRange {
67        key: String,
68        offset: usize,
69        value: Bytes,
70    },
71
72    /// KEYS `pattern`. Returns all keys matching a glob pattern.
73    Keys { pattern: String },
74
75    /// RENAME `key` `newkey`. Renames a key.
76    Rename { key: String, newkey: String },
77
78    /// DEL `key` \[key ...\]. Returns the number of keys removed.
79    Del { keys: Vec<String> },
80
81    /// UNLINK `key` \[key ...\]. Like DEL but frees memory in the background.
82    Unlink { keys: Vec<String> },
83
84    /// EXISTS `key` \[key ...\]. Returns the number of keys that exist.
85    Exists { keys: Vec<String> },
86
87    /// MGET `key` \[key ...\]. Returns the values for all specified keys.
88    MGet { keys: Vec<String> },
89
90    /// MSET `key` `value` \[key value ...\]. Sets multiple key-value pairs.
91    MSet { pairs: Vec<(String, Bytes)> },
92
93    /// EXPIRE `key` `seconds`. Sets a TTL on an existing key.
94    Expire { key: String, seconds: u64 },
95
96    /// TTL `key`. Returns remaining time-to-live in seconds.
97    Ttl { key: String },
98
99    /// PERSIST `key`. Removes the expiration from a key.
100    Persist { key: String },
101
102    /// PTTL `key`. Returns remaining time-to-live in milliseconds.
103    Pttl { key: String },
104
105    /// PEXPIRE `key` `milliseconds`. Sets a TTL in milliseconds on an existing key.
106    Pexpire { key: String, milliseconds: u64 },
107
108    /// DBSIZE. Returns the number of keys in the database.
109    DbSize,
110
111    /// INFO \[section\]. Returns server info. Currently only supports "keyspace".
112    Info { section: Option<String> },
113
114    /// BGSAVE. Triggers a background snapshot.
115    BgSave,
116
117    /// BGREWRITEAOF. Triggers an AOF rewrite (snapshot + truncate).
118    BgRewriteAof,
119
120    /// FLUSHDB \[ASYNC\]. Removes all keys from the database.
121    FlushDb { async_mode: bool },
122
123    /// CONFIG GET `pattern`. Returns matching server configuration parameters.
124    ConfigGet { pattern: String },
125
126    /// CONFIG SET `param` `value`. Sets a server configuration parameter at runtime.
127    ConfigSet { param: String, value: String },
128
129    /// CONFIG REWRITE. Writes the current config to the file loaded at startup.
130    ConfigRewrite,
131
132    /// MULTI. Starts a transaction — subsequent commands are queued until EXEC.
133    Multi,
134
135    /// EXEC. Executes all queued commands atomically, returning an array of results.
136    Exec,
137
138    /// DISCARD. Aborts a transaction, discarding all queued commands.
139    Discard,
140
141    /// SCAN `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates keys.
142    Scan {
143        cursor: u64,
144        pattern: Option<String>,
145        count: Option<usize>,
146    },
147
148    /// SSCAN `key` `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates set members.
149    SScan {
150        key: String,
151        cursor: u64,
152        pattern: Option<String>,
153        count: Option<usize>,
154    },
155
156    /// HSCAN `key` `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates hash fields.
157    HScan {
158        key: String,
159        cursor: u64,
160        pattern: Option<String>,
161        count: Option<usize>,
162    },
163
164    /// ZSCAN `key` `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates sorted set members.
165    ZScan {
166        key: String,
167        cursor: u64,
168        pattern: Option<String>,
169        count: Option<usize>,
170    },
171
172    /// LPUSH `key` `value` \[value ...\]. Pushes values to the head of a list.
173    LPush { key: String, values: Vec<Bytes> },
174
175    /// RPUSH `key` `value` \[value ...\]. Pushes values to the tail of a list.
176    RPush { key: String, values: Vec<Bytes> },
177
178    /// LPOP `key`. Pops a value from the head of a list.
179    LPop { key: String },
180
181    /// RPOP `key`. Pops a value from the tail of a list.
182    RPop { key: String },
183
184    /// LRANGE `key` `start` `stop`. Returns a range of elements by index.
185    LRange { key: String, start: i64, stop: i64 },
186
187    /// LLEN `key`. Returns the length of a list.
188    LLen { key: String },
189
190    /// BLPOP `key` \[key ...\] `timeout`. Blocks until an element is available
191    /// at the head of one of the given lists, or the timeout expires.
192    BLPop {
193        keys: Vec<String>,
194        timeout_secs: f64,
195    },
196
197    /// BRPOP `key` \[key ...\] `timeout`. Blocks until an element is available
198    /// at the tail of one of the given lists, or the timeout expires.
199    BRPop {
200        keys: Vec<String>,
201        timeout_secs: f64,
202    },
203
204    /// LINDEX `key` `index`. Returns the element at `index` in the list.
205    LIndex { key: String, index: i64 },
206
207    /// LSET `key` `index` `element`. Sets the element at `index`.
208    LSet {
209        key: String,
210        index: i64,
211        value: Bytes,
212    },
213
214    /// LTRIM `key` `start` `stop`. Trims the list to the specified range.
215    LTrim { key: String, start: i64, stop: i64 },
216
217    /// LINSERT `key` BEFORE|AFTER `pivot` `element`. Inserts before or after pivot.
218    LInsert {
219        key: String,
220        before: bool,
221        pivot: Bytes,
222        value: Bytes,
223    },
224
225    /// LREM `key` `count` `element`. Removes elements equal to value.
226    LRem {
227        key: String,
228        count: i64,
229        value: Bytes,
230    },
231
232    /// LPOS `key` `element` \[RANK rank\] \[COUNT count\] \[MAXLEN maxlen\].
233    LPos {
234        key: String,
235        element: Bytes,
236        rank: i64,
237        count: Option<usize>,
238        maxlen: usize,
239    },
240
241    /// TYPE `key`. Returns the type of the value stored at key.
242    Type { key: String },
243
244    /// ZADD `key` \[NX|XX\] \[GT|LT\] \[CH\] `score` `member` \[score member ...\].
245    ZAdd {
246        key: String,
247        flags: ZAddFlags,
248        members: Vec<(f64, String)>,
249    },
250
251    /// ZREM `key` `member` \[member ...\]. Removes members from a sorted set.
252    ZRem { key: String, members: Vec<String> },
253
254    /// ZSCORE `key` `member`. Returns the score of a member.
255    ZScore { key: String, member: String },
256
257    /// ZRANK `key` `member`. Returns the rank of a member (0-based).
258    ZRank { key: String, member: String },
259
260    /// ZCARD `key`. Returns the cardinality (number of members) of a sorted set.
261    ZCard { key: String },
262
263    /// ZRANGE `key` `start` `stop` \[WITHSCORES\]. Returns a range by rank.
264    ZRange {
265        key: String,
266        start: i64,
267        stop: i64,
268        with_scores: bool,
269    },
270
271    /// ZREVRANGE `key` `start` `stop` \[WITHSCORES\]. Returns a range by rank in reverse order.
272    ZRevRange {
273        key: String,
274        start: i64,
275        stop: i64,
276        with_scores: bool,
277    },
278
279    /// ZREVRANK `key` `member`. Returns the reverse rank of a member.
280    ZRevRank { key: String, member: String },
281
282    /// ZCOUNT `key` `min` `max`. Counts members with scores in the given range.
283    ZCount {
284        key: String,
285        min: ScoreBound,
286        max: ScoreBound,
287    },
288
289    /// ZINCRBY `key` `increment` `member`. Increments the score of a member.
290    ZIncrBy {
291        key: String,
292        increment: f64,
293        member: String,
294    },
295
296    /// ZRANGEBYSCORE `key` `min` `max` \[WITHSCORES\] \[LIMIT offset count\].
297    ZRangeByScore {
298        key: String,
299        min: ScoreBound,
300        max: ScoreBound,
301        with_scores: bool,
302        offset: usize,
303        count: Option<usize>,
304    },
305
306    /// ZREVRANGEBYSCORE `key` `max` `min` \[WITHSCORES\] \[LIMIT offset count\].
307    ZRevRangeByScore {
308        key: String,
309        min: ScoreBound,
310        max: ScoreBound,
311        with_scores: bool,
312        offset: usize,
313        count: Option<usize>,
314    },
315
316    /// ZPOPMIN `key` \[count\]. Removes and returns the lowest scored members.
317    ZPopMin { key: String, count: usize },
318
319    /// ZPOPMAX `key` \[count\]. Removes and returns the highest scored members.
320    ZPopMax { key: String, count: usize },
321
322    /// HSET `key` `field` `value` \[field value ...\]. Sets field-value pairs in a hash.
323    HSet {
324        key: String,
325        fields: Vec<(String, Bytes)>,
326    },
327
328    /// HGET `key` `field`. Gets a field's value from a hash.
329    HGet { key: String, field: String },
330
331    /// HGETALL `key`. Gets all field-value pairs from a hash.
332    HGetAll { key: String },
333
334    /// HDEL `key` `field` \[field ...\]. Deletes fields from a hash.
335    HDel { key: String, fields: Vec<String> },
336
337    /// HEXISTS `key` `field`. Checks if a field exists in a hash.
338    HExists { key: String, field: String },
339
340    /// HLEN `key`. Returns the number of fields in a hash.
341    HLen { key: String },
342
343    /// HINCRBY `key` `field` `increment`. Increments a hash field's integer value.
344    HIncrBy {
345        key: String,
346        field: String,
347        delta: i64,
348    },
349
350    /// HKEYS `key`. Returns all field names in a hash.
351    HKeys { key: String },
352
353    /// HVALS `key`. Returns all values in a hash.
354    HVals { key: String },
355
356    /// HMGET `key` `field` \[field ...\]. Gets multiple field values from a hash.
357    HMGet { key: String, fields: Vec<String> },
358
359    /// SADD `key` `member` \[member ...\]. Adds members to a set.
360    SAdd { key: String, members: Vec<String> },
361
362    /// SREM `key` `member` \[member ...\]. Removes members from a set.
363    SRem { key: String, members: Vec<String> },
364
365    /// SMEMBERS `key`. Returns all members of a set.
366    SMembers { key: String },
367
368    /// SISMEMBER `key` `member`. Checks if a member exists in a set.
369    SIsMember { key: String, member: String },
370
371    /// SCARD `key`. Returns the cardinality (number of members) of a set.
372    SCard { key: String },
373
374    /// SUNION `key` \[key ...\]. Returns the union of all given sets.
375    SUnion { keys: Vec<String> },
376
377    /// SINTER `key` \[key ...\]. Returns the intersection of all given sets.
378    SInter { keys: Vec<String> },
379
380    /// SDIFF `key` \[key ...\]. Returns members of the first set not in the others.
381    SDiff { keys: Vec<String> },
382
383    /// SUNIONSTORE `destination` `key` \[key ...\]. Stores the union into `destination`.
384    SUnionStore { dest: String, keys: Vec<String> },
385
386    /// SINTERSTORE `destination` `key` \[key ...\]. Stores the intersection into `destination`.
387    SInterStore { dest: String, keys: Vec<String> },
388
389    /// SDIFFSTORE `destination` `key` \[key ...\]. Stores the difference into `destination`.
390    SDiffStore { dest: String, keys: Vec<String> },
391
392    /// SRANDMEMBER `key` \[count\]. Returns random members without removing them.
393    SRandMember { key: String, count: Option<i64> },
394
395    /// SPOP `key` \[count\]. Removes and returns random members.
396    SPop { key: String, count: usize },
397
398    /// SMISMEMBER `key` `member` \[member ...\]. Checks multiple members at once.
399    SMisMember { key: String, members: Vec<String> },
400
401    // --- cluster commands ---
402    /// CLUSTER INFO. Returns cluster state and configuration information.
403    ClusterInfo,
404
405    /// CLUSTER NODES. Returns the list of cluster nodes.
406    ClusterNodes,
407
408    /// CLUSTER SLOTS. Returns the slot distribution across nodes.
409    ClusterSlots,
410
411    /// CLUSTER KEYSLOT `key`. Returns the hash slot for a key.
412    ClusterKeySlot { key: String },
413
414    /// CLUSTER MYID. Returns the node's ID.
415    ClusterMyId,
416
417    /// CLUSTER SETSLOT `slot` IMPORTING `node-id`. Mark slot as importing from node.
418    ClusterSetSlotImporting { slot: u16, node_id: String },
419
420    /// CLUSTER SETSLOT `slot` MIGRATING `node-id`. Mark slot as migrating to node.
421    ClusterSetSlotMigrating { slot: u16, node_id: String },
422
423    /// CLUSTER SETSLOT `slot` NODE `node-id`. Assign slot to node.
424    ClusterSetSlotNode { slot: u16, node_id: String },
425
426    /// CLUSTER SETSLOT `slot` STABLE. Clear importing/migrating state.
427    ClusterSetSlotStable { slot: u16 },
428
429    /// CLUSTER MEET `ip` `port`. Add a node to the cluster.
430    ClusterMeet { ip: String, port: u16 },
431
432    /// CLUSTER ADDSLOTS `slot` \[slot...\]. Assign slots to the local node.
433    ClusterAddSlots { slots: Vec<u16> },
434
435    /// CLUSTER ADDSLOTSRANGE `start` `end` \[start end ...\]. Assign a contiguous range of hash slots.
436    ClusterAddSlotsRange { ranges: Vec<(u16, u16)> },
437
438    /// CLUSTER DELSLOTS `slot` \[slot...\]. Remove slots from the local node.
439    ClusterDelSlots { slots: Vec<u16> },
440
441    /// CLUSTER FORGET `node-id`. Remove a node from the cluster.
442    ClusterForget { node_id: String },
443
444    /// CLUSTER REPLICATE `node-id`. Make this node a replica of another.
445    ClusterReplicate { node_id: String },
446
447    /// CLUSTER FAILOVER [FORCE|TAKEOVER]. Trigger a manual failover.
448    ClusterFailover { force: bool, takeover: bool },
449
450    /// CLUSTER COUNTKEYSINSLOT `slot`. Return the number of keys in a slot.
451    ClusterCountKeysInSlot { slot: u16 },
452
453    /// CLUSTER GETKEYSINSLOT `slot` `count`. Return keys in a slot.
454    ClusterGetKeysInSlot { slot: u16, count: u32 },
455
456    /// MIGRATE `host` `port` `key` `db` `timeout` \[COPY\] \[REPLACE\] \[KEYS key...\].
457    /// Migrate a key to another node.
458    Migrate {
459        host: String,
460        port: u16,
461        key: String,
462        db: u32,
463        timeout_ms: u64,
464        copy: bool,
465        replace: bool,
466    },
467
468    /// RESTORE `key` `ttl` `serialized-value` \[REPLACE\].
469    /// Insert a key from serialized data (used by MIGRATE).
470    Restore {
471        key: String,
472        ttl_ms: u64,
473        data: Bytes,
474        replace: bool,
475    },
476
477    /// ASKING. Signals that the next command is for a migrating slot.
478    Asking,
479
480    /// SLOWLOG GET [count]. Returns recent slow log entries.
481    SlowLogGet { count: Option<usize> },
482
483    /// SLOWLOG LEN. Returns the number of entries in the slow log.
484    SlowLogLen,
485
486    /// SLOWLOG RESET. Clears the slow log.
487    SlowLogReset,
488
489    // --- pub/sub commands ---
490    /// SUBSCRIBE `channel` \[channel ...\]. Subscribe to one or more channels.
491    Subscribe { channels: Vec<String> },
492
493    /// UNSUBSCRIBE \[channel ...\]. Unsubscribe from channels (all if none given).
494    Unsubscribe { channels: Vec<String> },
495
496    /// PSUBSCRIBE `pattern` \[pattern ...\]. Subscribe to channels matching patterns.
497    PSubscribe { patterns: Vec<String> },
498
499    /// PUNSUBSCRIBE \[pattern ...\]. Unsubscribe from patterns (all if none given).
500    PUnsubscribe { patterns: Vec<String> },
501
502    /// PUBLISH `channel` `message`. Publish a message to a channel.
503    Publish { channel: String, message: Bytes },
504
505    /// PUBSUB CHANNELS \[pattern\]. List active channels, optionally matching a glob.
506    PubSubChannels { pattern: Option<String> },
507
508    /// PUBSUB NUMSUB \[channel ...\]. Returns subscriber counts for given channels.
509    PubSubNumSub { channels: Vec<String> },
510
511    /// PUBSUB NUMPAT. Returns the number of active pattern subscriptions.
512    PubSubNumPat,
513
514    // --- vector commands ---
515    /// VADD key element f32 [f32 ...] [METRIC COSINE|L2|IP] [QUANT F32|F16|I8]
516    /// [M n] [EF n]. Adds a vector to a vector set.
517    VAdd {
518        key: String,
519        element: String,
520        vector: Vec<f32>,
521        /// 0 = cosine (default), 1 = l2, 2 = inner product
522        metric: u8,
523        /// 0 = f32 (default), 1 = f16, 2 = i8
524        quantization: u8,
525        /// HNSW connectivity parameter (default 16)
526        connectivity: u32,
527        /// HNSW construction beam width (default 64)
528        expansion_add: u32,
529    },
530
531    /// VADD_BATCH key DIM n element1 f32... element2 f32... [METRIC COSINE|L2|IP]
532    /// [QUANT F32|F16|I8] [M n] [EF n]. Adds multiple vectors in a single command.
533    VAddBatch {
534        key: String,
535        entries: Vec<(String, Vec<f32>)>,
536        dim: usize,
537        /// 0 = cosine (default), 1 = l2, 2 = inner product
538        metric: u8,
539        /// 0 = f32 (default), 1 = f16, 2 = i8
540        quantization: u8,
541        /// HNSW connectivity parameter (default 16)
542        connectivity: u32,
543        /// HNSW construction beam width (default 64)
544        expansion_add: u32,
545    },
546
547    /// VSIM key f32 [f32 ...] COUNT k [EF n] [WITHSCORES].
548    /// Searches for k nearest neighbors.
549    VSim {
550        key: String,
551        query: Vec<f32>,
552        count: usize,
553        ef_search: usize,
554        with_scores: bool,
555    },
556
557    /// VREM key element. Removes a vector from a vector set.
558    VRem { key: String, element: String },
559
560    /// VGET key element. Retrieves the stored vector for an element.
561    VGet { key: String, element: String },
562
563    /// VCARD key. Returns the number of elements in a vector set.
564    VCard { key: String },
565
566    /// VDIM key. Returns the dimensionality of a vector set.
567    VDim { key: String },
568
569    /// VINFO key. Returns metadata about a vector set.
570    VInfo { key: String },
571
572    // --- protobuf commands ---
573    /// PROTO.REGISTER `name` `descriptor_bytes`. Registers a protobuf schema
574    /// (pre-compiled FileDescriptorSet) under the given name.
575    ProtoRegister { name: String, descriptor: Bytes },
576
577    /// PROTO.SET `key` `type_name` `data` \[EX s | PX ms\] \[NX | XX\].
578    /// Stores a validated protobuf value.
579    ProtoSet {
580        key: String,
581        type_name: String,
582        data: Bytes,
583        expire: Option<SetExpire>,
584        /// Only set the key if it does not already exist.
585        nx: bool,
586        /// Only set the key if it already exists.
587        xx: bool,
588    },
589
590    /// PROTO.GET `key`. Returns \[type_name, data\] or nil.
591    ProtoGet { key: String },
592
593    /// PROTO.TYPE `key`. Returns the message type name or nil.
594    ProtoType { key: String },
595
596    /// PROTO.SCHEMAS. Lists all registered schema names.
597    ProtoSchemas,
598
599    /// PROTO.DESCRIBE `name`. Lists message types in a registered schema.
600    ProtoDescribe { name: String },
601
602    /// PROTO.GETFIELD `key` `field_path`. Reads a single field from a
603    /// protobuf value, returning it as a native RESP3 type.
604    ProtoGetField { key: String, field_path: String },
605
606    /// PROTO.SETFIELD `key` `field_path` `value`. Updates a single scalar
607    /// field in a stored protobuf value.
608    ProtoSetField {
609        key: String,
610        field_path: String,
611        value: String,
612    },
613
614    /// PROTO.DELFIELD `key` `field_path`. Clears a field to its default value.
615    ProtoDelField { key: String, field_path: String },
616
617    // --- client commands ---
618    /// CLIENT ID. Returns the unique ID of the current connection.
619    ClientId,
620
621    /// CLIENT SETNAME `name`. Sets a human-readable name for the connection.
622    ClientSetName { name: String },
623
624    /// CLIENT GETNAME. Returns the name set by CLIENT SETNAME, or nil.
625    ClientGetName,
626
627    /// CLIENT LIST. Returns info about all connected clients.
628    ClientList,
629
630    /// AUTH \[username\] password. Authenticate the connection.
631    Auth {
632        /// Username for ACL-style auth. None for legacy AUTH.
633        username: Option<String>,
634        /// The password to validate.
635        password: String,
636    },
637
638    // --- ACL commands ---
639    /// ACL WHOAMI. Returns the username of the current connection.
640    AclWhoAmI,
641
642    /// ACL LIST. Returns all users and their ACL rules.
643    AclList,
644
645    /// ACL USERS. Returns all usernames.
646    AclUsers,
647
648    /// ACL GETUSER `username`. Returns detailed info about a user.
649    AclGetUser { username: String },
650
651    /// ACL DELUSER `username` \[username ...\]. Deletes users.
652    AclDelUser { usernames: Vec<String> },
653
654    /// ACL SETUSER `username` \[rule ...\]. Creates or modifies a user.
655    AclSetUser {
656        username: String,
657        rules: Vec<String>,
658    },
659
660    /// ACL CAT \[category\]. Lists categories, or commands in a category.
661    AclCat { category: Option<String> },
662
663    /// WATCH `key` \[key ...\]. Marks keys for optimistic locking.
664    /// If any watched key is modified before EXEC, the transaction aborts.
665    Watch { keys: Vec<String> },
666
667    /// UNWATCH. Clears all watched keys for the current connection.
668    Unwatch,
669
670    /// TIME. Returns the current server time as \[unix_seconds, microseconds\].
671    Time,
672
673    /// LASTSAVE. Returns the unix timestamp of the last successful save.
674    LastSave,
675
676    /// ROLE. Returns the replication role of the server.
677    Role,
678
679    /// OBJECT ENCODING `key`. Returns the internal encoding of the value.
680    ObjectEncoding { key: String },
681
682    /// OBJECT REFCOUNT `key`. Returns the reference count of the value (always 1).
683    ObjectRefcount { key: String },
684
685    /// COPY `source` `destination` \[DB db\] \[REPLACE\]. Copies the value at source to destination.
686    Copy {
687        source: String,
688        destination: String,
689        replace: bool,
690    },
691
692    /// QUIT. Requests the server to close the connection.
693    Quit,
694
695    /// MONITOR. Streams all commands processed by the server.
696    Monitor,
697
698    /// RANDOMKEY. Returns a random key from the database, or nil if empty.
699    RandomKey,
700
701    /// TOUCH `key` \[key ...\]. Updates last access time, returns count of existing keys.
702    Touch { keys: Vec<String> },
703
704    /// SORT `key` \[ASC|DESC\] \[ALPHA\] \[LIMIT offset count\] \[STORE dest\].
705    /// Sorts a list, set, or sorted set and returns the sorted elements.
706    Sort {
707        key: String,
708        desc: bool,
709        alpha: bool,
710        limit: Option<(i64, i64)>,
711        store: Option<String>,
712    },
713
714    /// A command we don't recognize (yet).
715    Unknown(String),
716}
717
718/// A score bound for sorted set range queries (ZRANGEBYSCORE, ZCOUNT, etc.).
719///
720/// Redis supports `-inf`, `+inf`, inclusive (default), and exclusive
721/// bounds (prefixed with `(`).
722#[derive(Debug, Clone, Copy, PartialEq)]
723pub enum ScoreBound {
724    /// Negative infinity — matches all scores from the bottom.
725    NegInf,
726    /// Positive infinity — matches all scores to the top.
727    PosInf,
728    /// Inclusive bound: score >= value (for min) or score <= value (for max).
729    Inclusive(f64),
730    /// Exclusive bound: score > value (for min) or score < value (for max).
731    Exclusive(f64),
732}
733
734/// Flags for the ZADD command.
735#[derive(Debug, Clone, Default, PartialEq)]
736pub struct ZAddFlags {
737    /// Only add new members, don't update existing scores.
738    pub nx: bool,
739    /// Only update existing members, don't add new ones.
740    pub xx: bool,
741    /// Only update when new score > current score.
742    pub gt: bool,
743    /// Only update when new score < current score.
744    pub lt: bool,
745    /// Return count of changed members (added + updated) instead of just added.
746    pub ch: bool,
747}
748
749impl Eq for ZAddFlags {}
750
751mod attributes;
752mod parse;
753#[cfg(test)]
754mod tests;