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 and GETEX commands.
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 /// EXAT unix-seconds — expire at an absolute unix timestamp (seconds).
17 ExAt(u64),
18 /// PXAT unix-milliseconds — expire at an absolute unix timestamp (milliseconds).
19 PxAt(u64),
20}
21
22/// A parsed client command, ready for execution.
23#[derive(Debug, Clone, PartialEq)]
24pub enum Command {
25 /// PING with an optional message. Returns PONG or echoes the message.
26 Ping(Option<Bytes>),
27
28 /// ECHO `message`. Returns the message back to the client.
29 Echo(Bytes),
30
31 /// GET `key`. Returns the value or nil.
32 Get { key: String },
33
34 /// SET `key` `value` \[EX seconds | PX milliseconds\] \[NX | XX\].
35 Set {
36 key: String,
37 value: Bytes,
38 expire: Option<SetExpire>,
39 /// Only set the key if it does not already exist.
40 nx: bool,
41 /// Only set the key if it already exists.
42 xx: bool,
43 },
44
45 /// INCR `key`. Increments the integer value of a key by 1.
46 Incr { key: String },
47
48 /// DECR `key`. Decrements the integer value of a key by 1.
49 Decr { key: String },
50
51 /// INCRBY `key` `increment`. Increments the integer value of a key by the given amount.
52 IncrBy { key: String, delta: i64 },
53
54 /// DECRBY `key` `decrement`. Decrements the integer value of a key by the given amount.
55 DecrBy { key: String, delta: i64 },
56
57 /// INCRBYFLOAT `key` `increment`. Increments the float value of a key by the given amount.
58 IncrByFloat { key: String, delta: f64 },
59
60 /// APPEND `key` `value`. Appends a value to a string key. Returns the new length.
61 Append { key: String, value: Bytes },
62
63 /// STRLEN `key`. Returns the length of the string value stored at key.
64 Strlen { key: String },
65
66 /// GETRANGE `key` `start` `end`. Returns a substring of the string at key.
67 GetRange { key: String, start: i64, end: i64 },
68
69 /// SETRANGE `key` `offset` `value`. Overwrites part of the string at key.
70 SetRange {
71 key: String,
72 offset: usize,
73 value: Bytes,
74 },
75
76 /// GETBIT `key` `offset`. Returns the bit at `offset` in the string stored at key.
77 ///
78 /// Bit ordering is big-endian (Redis compatible): byte 0 holds bits 0–7, MSB first.
79 /// Returns 0 if the key does not exist.
80 GetBit { key: String, offset: u64 },
81
82 /// SETBIT `key` `offset` `value`. Sets or clears the bit at `offset`.
83 ///
84 /// The string is automatically grown to accommodate the offset.
85 /// Returns the original bit value.
86 SetBit { key: String, offset: u64, value: u8 },
87
88 /// BITCOUNT `key` \[start end \[BYTE\|BIT\]\]. Counts set bits in the string,
89 /// optionally restricted to a byte or bit range.
90 BitCount {
91 key: String,
92 range: Option<BitRange>,
93 },
94
95 /// BITPOS `key` `bit` \[start \[end \[BYTE\|BIT\]\]\]. Returns the position of the
96 /// first set (`bit=1`) or clear (`bit=0`) bit in the string.
97 BitPos {
98 key: String,
99 bit: u8,
100 range: Option<BitRange>,
101 },
102
103 /// BITOP `operation` `destkey` `key` \[key ...\]. Performs a bitwise operation
104 /// across source strings and stores the result in `destkey`.
105 BitOp {
106 op: BitOpKind,
107 dest: String,
108 keys: Vec<String>,
109 },
110
111 /// KEYS `pattern`. Returns all keys matching a glob pattern.
112 Keys { pattern: String },
113
114 /// RENAME `key` `newkey`. Renames a key.
115 Rename { key: String, newkey: String },
116
117 /// DEL `key` \[key ...\]. Returns the number of keys removed.
118 Del { keys: Vec<String> },
119
120 /// UNLINK `key` \[key ...\]. Like DEL but frees memory in the background.
121 Unlink { keys: Vec<String> },
122
123 /// EXISTS `key` \[key ...\]. Returns the number of keys that exist.
124 Exists { keys: Vec<String> },
125
126 /// MGET `key` \[key ...\]. Returns the values for all specified keys.
127 MGet { keys: Vec<String> },
128
129 /// MSET `key` `value` \[key value ...\]. Sets multiple key-value pairs.
130 MSet { pairs: Vec<(String, Bytes)> },
131
132 /// MSETNX `key` `value` \[key value ...\]. Sets multiple keys only if none already exist.
133 /// Returns 1 if all keys were set, 0 if any key already existed (atomic: all-or-nothing).
134 MSetNx { pairs: Vec<(String, Bytes)> },
135
136 /// GETSET `key` `value`. Atomically sets `key` to `value` and returns the old value.
137 /// Deprecated in Redis 6.2 but widely used; kept for compatibility.
138 GetSet { key: String, value: Bytes },
139
140 /// EXPIRE `key` `seconds`. Sets a TTL on an existing key.
141 Expire { key: String, seconds: u64 },
142
143 /// EXPIREAT `key` `timestamp`. Sets expiry at an absolute Unix timestamp (seconds).
144 Expireat { key: String, timestamp: u64 },
145
146 /// TTL `key`. Returns remaining time-to-live in seconds.
147 Ttl { key: String },
148
149 /// PERSIST `key`. Removes the expiration from a key.
150 Persist { key: String },
151
152 /// PTTL `key`. Returns remaining time-to-live in milliseconds.
153 Pttl { key: String },
154
155 /// PEXPIRE `key` `milliseconds`. Sets a TTL in milliseconds on an existing key.
156 Pexpire { key: String, milliseconds: u64 },
157
158 /// PEXPIREAT `key` `timestamp-ms`. Sets expiry at an absolute Unix timestamp (milliseconds).
159 Pexpireat { key: String, timestamp_ms: u64 },
160
161 /// DBSIZE. Returns the number of keys in the database.
162 DbSize,
163
164 /// INFO \[section\]. Returns server info. Currently only supports "keyspace".
165 Info { section: Option<String> },
166
167 /// BGSAVE. Triggers a background snapshot.
168 BgSave,
169
170 /// BGREWRITEAOF. Triggers an AOF rewrite (snapshot + truncate).
171 BgRewriteAof,
172
173 /// FLUSHDB \[ASYNC\]. Removes all keys from the database.
174 FlushDb { async_mode: bool },
175
176 /// FLUSHALL \[ASYNC\]. Removes all keys (alias for FLUSHDB — Ember is single-database).
177 FlushAll { async_mode: bool },
178
179 /// MEMORY USAGE key \[SAMPLES count\]. Returns estimated memory usage in bytes.
180 MemoryUsage { key: String },
181
182 /// CONFIG GET `pattern`. Returns matching server configuration parameters.
183 ConfigGet { pattern: String },
184
185 /// CONFIG SET `param` `value`. Sets a server configuration parameter at runtime.
186 ConfigSet { param: String, value: String },
187
188 /// CONFIG REWRITE. Writes the current config to the file loaded at startup.
189 ConfigRewrite,
190
191 /// MULTI. Starts a transaction — subsequent commands are queued until EXEC.
192 Multi,
193
194 /// EXEC. Executes all queued commands atomically, returning an array of results.
195 Exec,
196
197 /// DISCARD. Aborts a transaction, discarding all queued commands.
198 Discard,
199
200 /// SCAN `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates keys.
201 Scan {
202 cursor: u64,
203 pattern: Option<String>,
204 count: Option<usize>,
205 },
206
207 /// SSCAN `key` `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates set members.
208 SScan {
209 key: String,
210 cursor: u64,
211 pattern: Option<String>,
212 count: Option<usize>,
213 },
214
215 /// HSCAN `key` `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates hash fields.
216 HScan {
217 key: String,
218 cursor: u64,
219 pattern: Option<String>,
220 count: Option<usize>,
221 },
222
223 /// ZSCAN `key` `cursor` \[MATCH pattern\] \[COUNT count\]. Iterates sorted set members.
224 ZScan {
225 key: String,
226 cursor: u64,
227 pattern: Option<String>,
228 count: Option<usize>,
229 },
230
231 /// LPUSH `key` `value` \[value ...\]. Pushes values to the head of a list.
232 LPush { key: String, values: Vec<Bytes> },
233
234 /// RPUSH `key` `value` \[value ...\]. Pushes values to the tail of a list.
235 RPush { key: String, values: Vec<Bytes> },
236
237 /// LPOP `key` \[count\]. Pops one or more values from the head of a list.
238 ///
239 /// Without `count`: returns a bulk string (or nil). With `count`: returns
240 /// an array of up to `count` elements (Redis 6.2+ semantics).
241 LPop { key: String, count: Option<usize> },
242
243 /// RPOP `key` \[count\]. Pops one or more values from the tail of a list.
244 ///
245 /// Without `count`: returns a bulk string (or nil). With `count`: returns
246 /// an array of up to `count` elements (Redis 6.2+ semantics).
247 RPop { key: String, count: Option<usize> },
248
249 /// LRANGE `key` `start` `stop`. Returns a range of elements by index.
250 LRange { key: String, start: i64, stop: i64 },
251
252 /// LLEN `key`. Returns the length of a list.
253 LLen { key: String },
254
255 /// BLPOP `key` \[key ...\] `timeout`. Blocks until an element is available
256 /// at the head of one of the given lists, or the timeout expires.
257 BLPop {
258 keys: Vec<String>,
259 timeout_secs: f64,
260 },
261
262 /// BRPOP `key` \[key ...\] `timeout`. Blocks until an element is available
263 /// at the tail of one of the given lists, or the timeout expires.
264 BRPop {
265 keys: Vec<String>,
266 timeout_secs: f64,
267 },
268
269 /// LINDEX `key` `index`. Returns the element at `index` in the list.
270 LIndex { key: String, index: i64 },
271
272 /// LSET `key` `index` `element`. Sets the element at `index`.
273 LSet {
274 key: String,
275 index: i64,
276 value: Bytes,
277 },
278
279 /// LTRIM `key` `start` `stop`. Trims the list to the specified range.
280 LTrim { key: String, start: i64, stop: i64 },
281
282 /// LINSERT `key` BEFORE|AFTER `pivot` `element`. Inserts before or after pivot.
283 LInsert {
284 key: String,
285 before: bool,
286 pivot: Bytes,
287 value: Bytes,
288 },
289
290 /// LREM `key` `count` `element`. Removes elements equal to value.
291 LRem {
292 key: String,
293 count: i64,
294 value: Bytes,
295 },
296
297 /// LPOS `key` `element` \[RANK rank\] \[COUNT count\] \[MAXLEN maxlen\].
298 LPos {
299 key: String,
300 element: Bytes,
301 rank: i64,
302 count: Option<usize>,
303 maxlen: usize,
304 },
305
306 /// LMOVE `source` `destination` LEFT|RIGHT LEFT|RIGHT.
307 /// Atomically pops from the source list and pushes to the destination list.
308 LMove {
309 source: String,
310 destination: String,
311 /// Pop from the left (head) if true, right (tail) if false.
312 src_left: bool,
313 /// Push to the left (head) if true, right (tail) if false.
314 dst_left: bool,
315 },
316
317 /// GETDEL `key`. Returns the value of a key and deletes it atomically.
318 GetDel { key: String },
319
320 /// GETEX `key` \[EX seconds | PX ms | EXAT timestamp | PXAT timestamp-ms | PERSIST\].
321 /// Returns the value of a key and optionally updates its expiry.
322 GetEx {
323 key: String,
324 /// `None` — no change; `Some(None)` — remove TTL (PERSIST); `Some(Some(_))` — set TTL.
325 expire: Option<Option<SetExpire>>,
326 },
327
328 /// ZDIFF `numkeys` `key` \[key ...\] \[WITHSCORES\].
329 /// Returns members in the first sorted set not present in the others.
330 ZDiff {
331 keys: Vec<String>,
332 with_scores: bool,
333 },
334
335 /// ZINTER `numkeys` `key` \[key ...\] \[WITHSCORES\].
336 /// Returns members present in all of the given sorted sets.
337 ZInter {
338 keys: Vec<String>,
339 with_scores: bool,
340 },
341
342 /// ZUNION `numkeys` `key` \[key ...\] \[WITHSCORES\].
343 /// Returns the union of all given sorted sets.
344 ZUnion {
345 keys: Vec<String>,
346 with_scores: bool,
347 },
348
349 /// ZDIFFSTORE `destkey` `numkeys` `key` \[key ...\].
350 /// Stores the diff of sorted sets in destkey. Returns the cardinality.
351 ZDiffStore { dest: String, keys: Vec<String> },
352
353 /// ZINTERSTORE `destkey` `numkeys` `key` \[key ...\].
354 /// Stores the intersection of sorted sets in destkey. Returns the cardinality.
355 ZInterStore { dest: String, keys: Vec<String> },
356
357 /// ZUNIONSTORE `destkey` `numkeys` `key` \[key ...\].
358 /// Stores the union of sorted sets in destkey. Returns the cardinality.
359 ZUnionStore { dest: String, keys: Vec<String> },
360
361 /// TYPE `key`. Returns the type of the value stored at key.
362 Type { key: String },
363
364 /// ZADD `key` \[NX|XX\] \[GT|LT\] \[CH\] `score` `member` \[score member ...\].
365 ZAdd {
366 key: String,
367 flags: ZAddFlags,
368 members: Vec<(f64, String)>,
369 },
370
371 /// ZREM `key` `member` \[member ...\]. Removes members from a sorted set.
372 ZRem { key: String, members: Vec<String> },
373
374 /// ZSCORE `key` `member`. Returns the score of a member.
375 ZScore { key: String, member: String },
376
377 /// ZRANK `key` `member`. Returns the rank of a member (0-based).
378 ZRank { key: String, member: String },
379
380 /// ZCARD `key`. Returns the cardinality (number of members) of a sorted set.
381 ZCard { key: String },
382
383 /// ZRANGE `key` `start` `stop` \[WITHSCORES\]. Returns a range by rank.
384 ZRange {
385 key: String,
386 start: i64,
387 stop: i64,
388 with_scores: bool,
389 },
390
391 /// ZREVRANGE `key` `start` `stop` \[WITHSCORES\]. Returns a range by rank in reverse order.
392 ZRevRange {
393 key: String,
394 start: i64,
395 stop: i64,
396 with_scores: bool,
397 },
398
399 /// ZREVRANK `key` `member`. Returns the reverse rank of a member.
400 ZRevRank { key: String, member: String },
401
402 /// ZCOUNT `key` `min` `max`. Counts members with scores in the given range.
403 ZCount {
404 key: String,
405 min: ScoreBound,
406 max: ScoreBound,
407 },
408
409 /// ZINCRBY `key` `increment` `member`. Increments the score of a member.
410 ZIncrBy {
411 key: String,
412 increment: f64,
413 member: String,
414 },
415
416 /// ZRANGEBYSCORE `key` `min` `max` \[WITHSCORES\] \[LIMIT offset count\].
417 ZRangeByScore {
418 key: String,
419 min: ScoreBound,
420 max: ScoreBound,
421 with_scores: bool,
422 offset: usize,
423 count: Option<usize>,
424 },
425
426 /// ZREVRANGEBYSCORE `key` `max` `min` \[WITHSCORES\] \[LIMIT offset count\].
427 ZRevRangeByScore {
428 key: String,
429 min: ScoreBound,
430 max: ScoreBound,
431 with_scores: bool,
432 offset: usize,
433 count: Option<usize>,
434 },
435
436 /// ZPOPMIN `key` \[count\]. Removes and returns the lowest scored members.
437 ZPopMin { key: String, count: usize },
438
439 /// ZPOPMAX `key` \[count\]. Removes and returns the highest scored members.
440 ZPopMax { key: String, count: usize },
441
442 /// LMPOP `numkeys` `key` \[key ...\] LEFT|RIGHT \[COUNT n\].
443 /// Tries keys left-to-right, popping up to `count` elements from the first
444 /// non-empty list. Returns `[key_name, [elem, ...]]` or nil if all empty.
445 Lmpop {
446 keys: Vec<String>,
447 left: bool,
448 count: usize,
449 },
450
451 /// ZMPOP `numkeys` `key` \[key ...\] MIN|MAX \[COUNT n\].
452 /// Tries keys left-to-right, popping up to `count` elements from the first
453 /// non-empty sorted set. Returns `[key_name, [[member, score], ...]]` or nil.
454 Zmpop {
455 keys: Vec<String>,
456 min: bool,
457 count: usize,
458 },
459
460 /// HSET `key` `field` `value` \[field value ...\]. Sets field-value pairs in a hash.
461 HSet {
462 key: String,
463 fields: Vec<(String, Bytes)>,
464 },
465
466 /// HGET `key` `field`. Gets a field's value from a hash.
467 HGet { key: String, field: String },
468
469 /// HGETALL `key`. Gets all field-value pairs from a hash.
470 HGetAll { key: String },
471
472 /// HDEL `key` `field` \[field ...\]. Deletes fields from a hash.
473 HDel { key: String, fields: Vec<String> },
474
475 /// HEXISTS `key` `field`. Checks if a field exists in a hash.
476 HExists { key: String, field: String },
477
478 /// HLEN `key`. Returns the number of fields in a hash.
479 HLen { key: String },
480
481 /// HINCRBY `key` `field` `increment`. Increments a hash field's integer value.
482 HIncrBy {
483 key: String,
484 field: String,
485 delta: i64,
486 },
487
488 /// HKEYS `key`. Returns all field names in a hash.
489 HKeys { key: String },
490
491 /// HVALS `key`. Returns all values in a hash.
492 HVals { key: String },
493
494 /// HMGET `key` `field` \[field ...\]. Gets multiple field values from a hash.
495 HMGet { key: String, fields: Vec<String> },
496
497 /// HRANDFIELD `key` \[count \[WITHVALUES\]\].
498 /// Returns random field(s) from a hash. Positive count returns distinct fields;
499 /// negative allows duplicates. With WITHVALUES, returns interleaved field-value pairs.
500 HRandField {
501 key: String,
502 count: Option<i64>,
503 with_values: bool,
504 },
505
506 /// SADD `key` `member` \[member ...\]. Adds members to a set.
507 SAdd { key: String, members: Vec<String> },
508
509 /// SREM `key` `member` \[member ...\]. Removes members from a set.
510 SRem { key: String, members: Vec<String> },
511
512 /// SMEMBERS `key`. Returns all members of a set.
513 SMembers { key: String },
514
515 /// SISMEMBER `key` `member`. Checks if a member exists in a set.
516 SIsMember { key: String, member: String },
517
518 /// SCARD `key`. Returns the cardinality (number of members) of a set.
519 SCard { key: String },
520
521 /// SUNION `key` \[key ...\]. Returns the union of all given sets.
522 SUnion { keys: Vec<String> },
523
524 /// SINTER `key` \[key ...\]. Returns the intersection of all given sets.
525 SInter { keys: Vec<String> },
526
527 /// SDIFF `key` \[key ...\]. Returns members of the first set not in the others.
528 SDiff { keys: Vec<String> },
529
530 /// SUNIONSTORE `destination` `key` \[key ...\]. Stores the union into `destination`.
531 SUnionStore { dest: String, keys: Vec<String> },
532
533 /// SINTERSTORE `destination` `key` \[key ...\]. Stores the intersection into `destination`.
534 SInterStore { dest: String, keys: Vec<String> },
535
536 /// SDIFFSTORE `destination` `key` \[key ...\]. Stores the difference into `destination`.
537 SDiffStore { dest: String, keys: Vec<String> },
538
539 /// SRANDMEMBER `key` \[count\]. Returns random members without removing them.
540 SRandMember { key: String, count: Option<i64> },
541
542 /// ZRANDMEMBER `key` \[count \[WITHSCORES\]\].
543 /// Returns random member(s) from a sorted set. Positive count returns distinct members;
544 /// negative allows duplicates. With WITHSCORES, returns interleaved member-score pairs.
545 ZRandMember {
546 key: String,
547 count: Option<i64>,
548 with_scores: bool,
549 },
550
551 /// SPOP `key` \[count\]. Removes and returns random members.
552 SPop { key: String, count: usize },
553
554 /// SMISMEMBER `key` `member` \[member ...\]. Checks multiple members at once.
555 SMisMember { key: String, members: Vec<String> },
556
557 /// SMOVE `source` `destination` `member`. Atomically moves a member from one set to another.
558 /// Returns 1 if moved, 0 if the member was not in the source set.
559 SMove {
560 source: String,
561 destination: String,
562 member: String,
563 },
564
565 /// SINTERCARD `numkeys` `key` \[key ...\] \[LIMIT count\]. Returns the cardinality of the set
566 /// intersection. If LIMIT is given and nonzero, the result is capped at that value.
567 SInterCard { keys: Vec<String>, limit: usize },
568
569 /// EXPIRETIME `key`. Returns the absolute Unix timestamp (seconds) when the key expires.
570 /// Returns -1 if the key has no expiry, -2 if the key does not exist.
571 Expiretime { key: String },
572
573 /// PEXPIRETIME `key`. Returns the absolute Unix timestamp (milliseconds) when the key expires.
574 /// Returns -1 if the key has no expiry, -2 if the key does not exist.
575 Pexpiretime { key: String },
576
577 // --- cluster commands ---
578 /// CLUSTER INFO. Returns cluster state and configuration information.
579 ClusterInfo,
580
581 /// CLUSTER NODES. Returns the list of cluster nodes.
582 ClusterNodes,
583
584 /// CLUSTER SLOTS. Returns the slot distribution across nodes.
585 ClusterSlots,
586
587 /// CLUSTER KEYSLOT `key`. Returns the hash slot for a key.
588 ClusterKeySlot { key: String },
589
590 /// CLUSTER MYID. Returns the node's ID.
591 ClusterMyId,
592
593 /// CLUSTER SETSLOT `slot` IMPORTING `node-id`. Mark slot as importing from node.
594 ClusterSetSlotImporting { slot: u16, node_id: String },
595
596 /// CLUSTER SETSLOT `slot` MIGRATING `node-id`. Mark slot as migrating to node.
597 ClusterSetSlotMigrating { slot: u16, node_id: String },
598
599 /// CLUSTER SETSLOT `slot` NODE `node-id`. Assign slot to node.
600 ClusterSetSlotNode { slot: u16, node_id: String },
601
602 /// CLUSTER SETSLOT `slot` STABLE. Clear importing/migrating state.
603 ClusterSetSlotStable { slot: u16 },
604
605 /// CLUSTER MEET `ip` `port`. Add a node to the cluster.
606 ClusterMeet { ip: String, port: u16 },
607
608 /// CLUSTER ADDSLOTS `slot` \[slot...\]. Assign slots to the local node.
609 ClusterAddSlots { slots: Vec<u16> },
610
611 /// CLUSTER ADDSLOTSRANGE `start` `end` \[start end ...\]. Assign a contiguous range of hash slots.
612 ClusterAddSlotsRange { ranges: Vec<(u16, u16)> },
613
614 /// CLUSTER DELSLOTS `slot` \[slot...\]. Remove slots from the local node.
615 ClusterDelSlots { slots: Vec<u16> },
616
617 /// CLUSTER FORGET `node-id`. Remove a node from the cluster.
618 ClusterForget { node_id: String },
619
620 /// CLUSTER REPLICATE `node-id`. Make this node a replica of another.
621 ClusterReplicate { node_id: String },
622
623 /// CLUSTER FAILOVER [FORCE|TAKEOVER]. Trigger a manual failover.
624 ClusterFailover { force: bool, takeover: bool },
625
626 /// CLUSTER COUNTKEYSINSLOT `slot`. Return the number of keys in a slot.
627 ClusterCountKeysInSlot { slot: u16 },
628
629 /// CLUSTER GETKEYSINSLOT `slot` `count`. Return keys in a slot.
630 ClusterGetKeysInSlot { slot: u16, count: u32 },
631
632 /// MIGRATE `host` `port` `key` `db` `timeout` \[COPY\] \[REPLACE\] \[KEYS key...\].
633 /// Migrate a key to another node.
634 Migrate {
635 host: String,
636 port: u16,
637 key: String,
638 db: u32,
639 timeout_ms: u64,
640 copy: bool,
641 replace: bool,
642 },
643
644 /// RESTORE `key` `ttl` `serialized-value` \[REPLACE\].
645 /// Insert a key from serialized data (used by MIGRATE).
646 Restore {
647 key: String,
648 ttl_ms: u64,
649 data: Bytes,
650 replace: bool,
651 },
652
653 /// ASKING. Signals that the next command is for a migrating slot.
654 Asking,
655
656 /// SLOWLOG GET [count]. Returns recent slow log entries.
657 SlowLogGet { count: Option<usize> },
658
659 /// SLOWLOG LEN. Returns the number of entries in the slow log.
660 SlowLogLen,
661
662 /// SLOWLOG RESET. Clears the slow log.
663 SlowLogReset,
664
665 // --- pub/sub commands ---
666 /// SUBSCRIBE `channel` \[channel ...\]. Subscribe to one or more channels.
667 Subscribe { channels: Vec<String> },
668
669 /// UNSUBSCRIBE \[channel ...\]. Unsubscribe from channels (all if none given).
670 Unsubscribe { channels: Vec<String> },
671
672 /// PSUBSCRIBE `pattern` \[pattern ...\]. Subscribe to channels matching patterns.
673 PSubscribe { patterns: Vec<String> },
674
675 /// PUNSUBSCRIBE \[pattern ...\]. Unsubscribe from patterns (all if none given).
676 PUnsubscribe { patterns: Vec<String> },
677
678 /// PUBLISH `channel` `message`. Publish a message to a channel.
679 Publish { channel: String, message: Bytes },
680
681 /// PUBSUB CHANNELS \[pattern\]. List active channels, optionally matching a glob.
682 PubSubChannels { pattern: Option<String> },
683
684 /// PUBSUB NUMSUB \[channel ...\]. Returns subscriber counts for given channels.
685 PubSubNumSub { channels: Vec<String> },
686
687 /// PUBSUB NUMPAT. Returns the number of active pattern subscriptions.
688 PubSubNumPat,
689
690 // --- vector commands ---
691 /// VADD key element f32 [f32 ...] [METRIC COSINE|L2|IP] [QUANT F32|F16|I8]
692 /// [M n] [EF n]. Adds a vector to a vector set.
693 VAdd {
694 key: String,
695 element: String,
696 vector: Vec<f32>,
697 /// 0 = cosine (default), 1 = l2, 2 = inner product
698 metric: u8,
699 /// 0 = f32 (default), 1 = f16, 2 = i8
700 quantization: u8,
701 /// HNSW connectivity parameter (default 16)
702 connectivity: u32,
703 /// HNSW construction beam width (default 64)
704 expansion_add: u32,
705 },
706
707 /// VADD_BATCH key DIM n element1 f32... element2 f32... [METRIC COSINE|L2|IP]
708 /// [QUANT F32|F16|I8] [M n] [EF n]. Adds multiple vectors in a single command.
709 VAddBatch {
710 key: String,
711 entries: Vec<(String, Vec<f32>)>,
712 dim: usize,
713 /// 0 = cosine (default), 1 = l2, 2 = inner product
714 metric: u8,
715 /// 0 = f32 (default), 1 = f16, 2 = i8
716 quantization: u8,
717 /// HNSW connectivity parameter (default 16)
718 connectivity: u32,
719 /// HNSW construction beam width (default 64)
720 expansion_add: u32,
721 },
722
723 /// VSIM key f32 [f32 ...] COUNT k [EF n] [WITHSCORES].
724 /// Searches for k nearest neighbors.
725 VSim {
726 key: String,
727 query: Vec<f32>,
728 count: usize,
729 ef_search: usize,
730 with_scores: bool,
731 },
732
733 /// VREM key element. Removes a vector from a vector set.
734 VRem { key: String, element: String },
735
736 /// VGET key element. Retrieves the stored vector for an element.
737 VGet { key: String, element: String },
738
739 /// VCARD key. Returns the number of elements in a vector set.
740 VCard { key: String },
741
742 /// VDIM key. Returns the dimensionality of a vector set.
743 VDim { key: String },
744
745 /// VINFO key. Returns metadata about a vector set.
746 VInfo { key: String },
747
748 // --- protobuf commands ---
749 /// PROTO.REGISTER `name` `descriptor_bytes`. Registers a protobuf schema
750 /// (pre-compiled FileDescriptorSet) under the given name.
751 ProtoRegister { name: String, descriptor: Bytes },
752
753 /// PROTO.SET `key` `type_name` `data` \[EX s | PX ms\] \[NX | XX\].
754 /// Stores a validated protobuf value.
755 ProtoSet {
756 key: String,
757 type_name: String,
758 data: Bytes,
759 expire: Option<SetExpire>,
760 /// Only set the key if it does not already exist.
761 nx: bool,
762 /// Only set the key if it already exists.
763 xx: bool,
764 },
765
766 /// PROTO.GET `key`. Returns \[type_name, data\] or nil.
767 ProtoGet { key: String },
768
769 /// PROTO.TYPE `key`. Returns the message type name or nil.
770 ProtoType { key: String },
771
772 /// PROTO.SCHEMAS. Lists all registered schema names.
773 ProtoSchemas,
774
775 /// PROTO.DESCRIBE `name`. Lists message types in a registered schema.
776 ProtoDescribe { name: String },
777
778 /// PROTO.GETFIELD `key` `field_path`. Reads a single field from a
779 /// protobuf value, returning it as a native RESP3 type.
780 ProtoGetField { key: String, field_path: String },
781
782 /// PROTO.SETFIELD `key` `field_path` `value`. Updates a single scalar
783 /// field in a stored protobuf value.
784 ProtoSetField {
785 key: String,
786 field_path: String,
787 value: String,
788 },
789
790 /// PROTO.DELFIELD `key` `field_path`. Clears a field to its default value.
791 ProtoDelField { key: String, field_path: String },
792
793 // --- client commands ---
794 /// CLIENT ID. Returns the unique ID of the current connection.
795 ClientId,
796
797 /// CLIENT SETNAME `name`. Sets a human-readable name for the connection.
798 ClientSetName { name: String },
799
800 /// CLIENT GETNAME. Returns the name set by CLIENT SETNAME, or nil.
801 ClientGetName,
802
803 /// CLIENT LIST. Returns info about all connected clients.
804 ClientList,
805
806 /// AUTH \[username\] password. Authenticate the connection.
807 Auth {
808 /// Username for ACL-style auth. None for legacy AUTH.
809 username: Option<String>,
810 /// The password to validate.
811 password: String,
812 },
813
814 // --- ACL commands ---
815 /// ACL WHOAMI. Returns the username of the current connection.
816 AclWhoAmI,
817
818 /// ACL LIST. Returns all users and their ACL rules.
819 AclList,
820
821 /// ACL USERS. Returns all usernames.
822 AclUsers,
823
824 /// ACL GETUSER `username`. Returns detailed info about a user.
825 AclGetUser { username: String },
826
827 /// ACL DELUSER `username` \[username ...\]. Deletes users.
828 AclDelUser { usernames: Vec<String> },
829
830 /// ACL SETUSER `username` \[rule ...\]. Creates or modifies a user.
831 AclSetUser {
832 username: String,
833 rules: Vec<String>,
834 },
835
836 /// ACL CAT \[category\]. Lists categories, or commands in a category.
837 AclCat { category: Option<String> },
838
839 /// WATCH `key` \[key ...\]. Marks keys for optimistic locking.
840 /// If any watched key is modified before EXEC, the transaction aborts.
841 Watch { keys: Vec<String> },
842
843 /// UNWATCH. Clears all watched keys for the current connection.
844 Unwatch,
845
846 /// TIME. Returns the current server time as \[unix_seconds, microseconds\].
847 Time,
848
849 /// LASTSAVE. Returns the unix timestamp of the last successful save.
850 LastSave,
851
852 /// ROLE. Returns the replication role of the server.
853 Role,
854
855 /// WAIT numreplicas timeout-ms
856 ///
857 /// Blocks until `numreplicas` replicas have acknowledged all write
858 /// commands processed before this WAIT, or until `timeout_ms`
859 /// milliseconds elapse. Returns the count of replicas that
860 /// acknowledged in time.
861 Wait { numreplicas: u64, timeout_ms: u64 },
862
863 /// OBJECT ENCODING `key`. Returns the internal encoding of the value.
864 ObjectEncoding { key: String },
865
866 /// OBJECT REFCOUNT `key`. Returns the reference count of the value (always 1).
867 ObjectRefcount { key: String },
868
869 /// COPY `source` `destination` \[DB db\] \[REPLACE\]. Copies the value at source to destination.
870 Copy {
871 source: String,
872 destination: String,
873 replace: bool,
874 },
875
876 /// QUIT. Requests the server to close the connection.
877 Quit,
878
879 /// MONITOR. Streams all commands processed by the server.
880 Monitor,
881
882 /// RANDOMKEY. Returns a random key from the database, or nil if empty.
883 RandomKey,
884
885 /// TOUCH `key` \[key ...\]. Updates last access time, returns count of existing keys.
886 Touch { keys: Vec<String> },
887
888 /// SORT `key` \[ASC|DESC\] \[ALPHA\] \[LIMIT offset count\] \[STORE dest\].
889 /// Sorts a list, set, or sorted set and returns the sorted elements.
890 Sort {
891 key: String,
892 desc: bool,
893 alpha: bool,
894 limit: Option<(i64, i64)>,
895 store: Option<String>,
896 },
897
898 /// COMMAND \[COUNT | INFO name \[name ...\] | DOCS name \[name ...\]\]
899 ///
900 /// Returns metadata about supported commands. Used by client libraries
901 /// for capability discovery on connect.
902 Command {
903 /// Optional subcommand: COUNT, INFO, DOCS, LIST. None = list all commands.
904 subcommand: Option<String>,
905 /// Arguments to the subcommand (command names for INFO/DOCS).
906 args: Vec<String>,
907 },
908
909 /// HINCRBYFLOAT `key` `field` `increment`. Increments the float value of a hash field.
910 ///
911 /// If the field doesn't exist it is set to 0 before the operation.
912 /// Returns the new value as a bulk string.
913 HIncrByFloat {
914 key: String,
915 field: String,
916 delta: f64,
917 },
918
919 /// A command we don't recognize (yet).
920 Unknown(String),
921}
922
923/// Unit for BITCOUNT and BITPOS range arguments.
924#[derive(Debug, Clone, Copy, PartialEq, Eq)]
925pub enum BitRangeUnit {
926 /// Byte-granularity range (default for Redis).
927 Byte,
928 /// Bit-granularity range (Redis 7.0+).
929 Bit,
930}
931
932/// Range argument for BITCOUNT and BITPOS.
933#[derive(Debug, Clone, Copy, PartialEq, Eq)]
934pub struct BitRange {
935 pub start: i64,
936 pub end: i64,
937 pub unit: BitRangeUnit,
938}
939
940/// Operation kind for BITOP.
941#[derive(Debug, Clone, Copy, PartialEq, Eq)]
942pub enum BitOpKind {
943 And,
944 Or,
945 Xor,
946 Not,
947}
948
949/// A score bound for sorted set range queries (ZRANGEBYSCORE, ZCOUNT, etc.).
950///
951/// Redis supports `-inf`, `+inf`, inclusive (default), and exclusive
952/// bounds (prefixed with `(`).
953#[derive(Debug, Clone, Copy, PartialEq)]
954pub enum ScoreBound {
955 /// Negative infinity — matches all scores from the bottom.
956 NegInf,
957 /// Positive infinity — matches all scores to the top.
958 PosInf,
959 /// Inclusive bound: score >= value (for min) or score <= value (for max).
960 Inclusive(f64),
961 /// Exclusive bound: score > value (for min) or score < value (for max).
962 Exclusive(f64),
963}
964
965/// Flags for the ZADD command.
966#[derive(Debug, Clone, Default, PartialEq)]
967pub struct ZAddFlags {
968 /// Only add new members, don't update existing scores.
969 pub nx: bool,
970 /// Only update existing members, don't add new ones.
971 pub xx: bool,
972 /// Only update when new score > current score.
973 pub gt: bool,
974 /// Only update when new score < current score.
975 pub lt: bool,
976 /// Return count of changed members (added + updated) instead of just added.
977 pub ch: bool,
978}
979
980impl Eq for ZAddFlags {}
981
982mod attributes;
983mod parse;
984#[cfg(test)]
985mod tests;