1pub mod hash;
6pub mod list;
7pub mod optimized;
8pub mod set;
9pub mod sorted_set;
10
11use crate::core::{error::RedisResult, value::RespValue};
12use crate::pipeline::PipelineCommand;
13use std::time::Duration;
14
15pub use hash::{
17 HDelCommand, HExistsCommand, HGetAllCommand, HGetCommand, HLenCommand, HMGetCommand,
18 HMSetCommand, HSetCommand,
19};
20
21pub use list::{
23 LIndexCommand, LLenCommand, LPopCommand, LPushCommand, LRangeCommand, LSetCommand, RPopCommand,
24 RPushCommand,
25};
26
27pub use set::{
29 SAddCommand, SCardCommand, SIsMemberCommand, SMembersCommand, SPopCommand, SRandMemberCommand,
30 SRemCommand,
31};
32
33pub use sorted_set::{
35 ZAddCommand, ZCardCommand, ZRangeCommand, ZRankCommand, ZRemCommand, ZRevRankCommand,
36 ZScoreCommand,
37};
38
39pub trait Command {
41 type Output;
43
44 fn command_name(&self) -> &str;
46
47 fn args(&self) -> Vec<RespValue>;
49
50 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output>;
52
53 fn keys(&self) -> Vec<&[u8]>;
55}
56
57pub struct GetCommand {
59 key: String,
60}
61
62impl GetCommand {
63 pub fn new(key: impl Into<String>) -> Self {
65 Self { key: key.into() }
66 }
67}
68
69impl Command for GetCommand {
70 type Output = Option<String>;
71
72 fn command_name(&self) -> &str {
73 "GET"
74 }
75
76 fn args(&self) -> Vec<RespValue> {
77 vec![RespValue::from(self.key.as_str())]
78 }
79
80 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
81 if response.is_null() {
82 Ok(None)
83 } else {
84 Ok(Some(response.as_string()?))
85 }
86 }
87
88 fn keys(&self) -> Vec<&[u8]> {
89 vec![self.key.as_bytes()]
90 }
91}
92
93pub struct SetCommand {
95 key: String,
96 value: String,
97 expiration: Option<Duration>,
98 nx: bool,
99 xx: bool,
100}
101
102impl SetCommand {
103 pub fn new(key: impl Into<String>, value: impl Into<String>) -> Self {
105 Self {
106 key: key.into(),
107 value: value.into(),
108 expiration: None,
109 nx: false,
110 xx: false,
111 }
112 }
113
114 pub fn expire(mut self, duration: Duration) -> Self {
116 self.expiration = Some(duration);
117 self
118 }
119
120 pub fn only_if_not_exists(mut self) -> Self {
122 self.nx = true;
123 self
124 }
125
126 pub fn only_if_exists(mut self) -> Self {
128 self.xx = true;
129 self
130 }
131}
132
133impl Command for SetCommand {
134 type Output = bool;
135
136 fn command_name(&self) -> &str {
137 "SET"
138 }
139
140 fn args(&self) -> Vec<RespValue> {
141 let mut args = vec![
142 RespValue::from(self.key.as_str()),
143 RespValue::from(self.value.as_str()),
144 ];
145
146 if let Some(duration) = self.expiration {
147 args.push(RespValue::from("EX"));
148 args.push(RespValue::from(duration.as_secs().to_string()));
149 }
150
151 if self.nx {
152 args.push(RespValue::from("NX"));
153 }
154
155 if self.xx {
156 args.push(RespValue::from("XX"));
157 }
158
159 args
160 }
161
162 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
163 match response {
164 RespValue::SimpleString(ref s) if s == "OK" => Ok(true),
165 _ => Ok(false),
167 }
168 }
169
170 fn keys(&self) -> Vec<&[u8]> {
171 vec![self.key.as_bytes()]
172 }
173}
174
175pub struct DelCommand {
177 keys: Vec<String>,
178}
179
180impl DelCommand {
181 pub fn new(keys: Vec<String>) -> Self {
183 Self { keys }
184 }
185}
186
187impl Command for DelCommand {
188 type Output = i64;
189
190 fn command_name(&self) -> &str {
191 "DEL"
192 }
193
194 fn args(&self) -> Vec<RespValue> {
195 self.keys
196 .iter()
197 .map(|k| RespValue::from(k.as_str()))
198 .collect()
199 }
200
201 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
202 response.as_int()
203 }
204
205 fn keys(&self) -> Vec<&[u8]> {
206 self.keys.iter().map(String::as_bytes).collect()
207 }
208}
209
210pub struct ExistsCommand {
212 keys: Vec<String>,
213}
214
215impl ExistsCommand {
216 pub fn new(keys: Vec<String>) -> Self {
218 Self { keys }
219 }
220}
221
222impl Command for ExistsCommand {
223 type Output = i64;
224
225 fn command_name(&self) -> &str {
226 "EXISTS"
227 }
228
229 fn args(&self) -> Vec<RespValue> {
230 self.keys
231 .iter()
232 .map(|k| RespValue::from(k.as_str()))
233 .collect()
234 }
235
236 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
237 response.as_int()
238 }
239
240 fn keys(&self) -> Vec<&[u8]> {
241 self.keys.iter().map(String::as_bytes).collect()
242 }
243}
244
245pub struct ExpireCommand {
247 key: String,
248 seconds: i64,
249}
250
251impl ExpireCommand {
252 pub fn new(key: impl Into<String>, duration: Duration) -> Self {
254 #[allow(clippy::cast_possible_wrap)]
255 Self {
256 key: key.into(),
257 seconds: duration.as_secs() as i64,
258 }
259 }
260}
261
262impl Command for ExpireCommand {
263 type Output = bool;
264
265 fn command_name(&self) -> &str {
266 "EXPIRE"
267 }
268
269 fn args(&self) -> Vec<RespValue> {
270 vec![
271 RespValue::from(self.key.as_str()),
272 RespValue::from(self.seconds.to_string()),
273 ]
274 }
275
276 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
277 Ok(response.as_int()? == 1)
278 }
279
280 fn keys(&self) -> Vec<&[u8]> {
281 vec![self.key.as_bytes()]
282 }
283}
284
285pub struct TtlCommand {
287 key: String,
288}
289
290impl TtlCommand {
291 pub fn new(key: impl Into<String>) -> Self {
293 Self { key: key.into() }
294 }
295}
296
297impl Command for TtlCommand {
298 type Output = Option<i64>;
299
300 fn command_name(&self) -> &str {
301 "TTL"
302 }
303
304 fn args(&self) -> Vec<RespValue> {
305 vec![RespValue::from(self.key.as_str())]
306 }
307
308 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
309 let ttl = response.as_int()?;
310 if ttl < 0 {
311 Ok(None) } else {
313 Ok(Some(ttl))
314 }
315 }
316
317 fn keys(&self) -> Vec<&[u8]> {
318 vec![self.key.as_bytes()]
319 }
320}
321
322pub struct IncrCommand {
324 key: String,
325}
326
327impl IncrCommand {
328 pub fn new(key: impl Into<String>) -> Self {
330 Self { key: key.into() }
331 }
332}
333
334impl Command for IncrCommand {
335 type Output = i64;
336
337 fn command_name(&self) -> &str {
338 "INCR"
339 }
340
341 fn args(&self) -> Vec<RespValue> {
342 vec![RespValue::from(self.key.as_str())]
343 }
344
345 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
346 response.as_int()
347 }
348
349 fn keys(&self) -> Vec<&[u8]> {
350 vec![self.key.as_bytes()]
351 }
352}
353
354pub struct DecrCommand {
356 key: String,
357}
358
359impl DecrCommand {
360 pub fn new(key: impl Into<String>) -> Self {
362 Self { key: key.into() }
363 }
364}
365
366impl Command for DecrCommand {
367 type Output = i64;
368
369 fn command_name(&self) -> &str {
370 "DECR"
371 }
372
373 fn args(&self) -> Vec<RespValue> {
374 vec![RespValue::from(self.key.as_str())]
375 }
376
377 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
378 response.as_int()
379 }
380
381 fn keys(&self) -> Vec<&[u8]> {
382 vec![self.key.as_bytes()]
383 }
384}
385
386pub struct IncrByCommand {
388 key: String,
389 increment: i64,
390}
391
392impl IncrByCommand {
393 pub fn new(key: impl Into<String>, increment: i64) -> Self {
395 Self {
396 key: key.into(),
397 increment,
398 }
399 }
400}
401
402impl Command for IncrByCommand {
403 type Output = i64;
404
405 fn command_name(&self) -> &str {
406 "INCRBY"
407 }
408
409 fn args(&self) -> Vec<RespValue> {
410 vec![
411 RespValue::from(self.key.as_str()),
412 RespValue::from(self.increment.to_string()),
413 ]
414 }
415
416 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
417 response.as_int()
418 }
419
420 fn keys(&self) -> Vec<&[u8]> {
421 vec![self.key.as_bytes()]
422 }
423}
424
425pub struct DecrByCommand {
427 key: String,
428 decrement: i64,
429}
430
431impl DecrByCommand {
432 pub fn new(key: impl Into<String>, decrement: i64) -> Self {
434 Self {
435 key: key.into(),
436 decrement,
437 }
438 }
439}
440
441impl Command for DecrByCommand {
442 type Output = i64;
443
444 fn command_name(&self) -> &str {
445 "DECRBY"
446 }
447
448 fn args(&self) -> Vec<RespValue> {
449 vec![
450 RespValue::from(self.key.as_str()),
451 RespValue::from(self.decrement.to_string()),
452 ]
453 }
454
455 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
456 response.as_int()
457 }
458
459 fn keys(&self) -> Vec<&[u8]> {
460 vec![self.key.as_bytes()]
461 }
462}
463
464#[cfg(test)]
465mod tests {
466 use super::*;
467
468 #[test]
469 fn test_get_command() {
470 let cmd = GetCommand::new("mykey");
471 assert_eq!(cmd.command_name(), "GET");
472 assert_eq!(cmd.keys(), vec![b"mykey"]);
473 }
474
475 #[test]
476 fn test_set_command_basic() {
477 let cmd = SetCommand::new("key", "value");
478 assert_eq!(cmd.command_name(), "SET");
479 let args = <SetCommand as Command>::args(&cmd);
480 assert_eq!(args.len(), 2);
481 }
482
483 #[test]
484 fn test_set_command_with_expiration() {
485 let cmd = SetCommand::new("key", "value").expire(Duration::from_secs(60));
486 let args = <SetCommand as Command>::args(&cmd);
487 assert_eq!(args.len(), 4); }
489
490 #[test]
491 fn test_set_command_nx() {
492 let cmd = SetCommand::new("key", "value").only_if_not_exists();
493 let args = <SetCommand as Command>::args(&cmd);
494 assert!(args.len() >= 3); }
496
497 #[test]
498 fn test_del_command() {
499 let cmd = DelCommand::new(vec!["key1".to_string(), "key2".to_string()]);
500 assert_eq!(cmd.command_name(), "DEL");
501 assert_eq!(cmd.keys().len(), 2);
502 }
503
504 #[test]
505 fn test_incr_command() {
506 let cmd = IncrCommand::new("counter");
507 assert_eq!(cmd.command_name(), "INCR");
508 assert_eq!(cmd.keys(), vec![b"counter"]);
509 }
510}
511
512impl PipelineCommand for GetCommand {
514 fn name(&self) -> &str {
515 self.command_name()
516 }
517
518 fn args(&self) -> Vec<RespValue> {
519 <Self as Command>::args(self)
520 }
521
522 fn key(&self) -> Option<String> {
523 Some(self.key.clone())
524 }
525}
526
527impl PipelineCommand for SetCommand {
528 fn name(&self) -> &str {
529 self.command_name()
530 }
531
532 fn args(&self) -> Vec<RespValue> {
533 <Self as Command>::args(self)
534 }
535
536 fn key(&self) -> Option<String> {
537 Some(self.key.clone())
538 }
539}
540
541impl PipelineCommand for DelCommand {
542 fn name(&self) -> &str {
543 self.command_name()
544 }
545
546 fn args(&self) -> Vec<RespValue> {
547 <Self as Command>::args(self)
548 }
549
550 fn key(&self) -> Option<String> {
551 self.keys.first().cloned()
552 }
553}
554
555impl PipelineCommand for IncrCommand {
556 fn name(&self) -> &str {
557 self.command_name()
558 }
559
560 fn args(&self) -> Vec<RespValue> {
561 <Self as Command>::args(self)
562 }
563
564 fn key(&self) -> Option<String> {
565 Some(self.key.clone())
566 }
567}
568
569impl PipelineCommand for DecrCommand {
570 fn name(&self) -> &str {
571 self.command_name()
572 }
573
574 fn args(&self) -> Vec<RespValue> {
575 <Self as Command>::args(self)
576 }
577
578 fn key(&self) -> Option<String> {
579 Some(self.key.clone())
580 }
581}
582
583impl PipelineCommand for IncrByCommand {
584 fn name(&self) -> &str {
585 self.command_name()
586 }
587
588 fn args(&self) -> Vec<RespValue> {
589 <Self as Command>::args(self)
590 }
591
592 fn key(&self) -> Option<String> {
593 Some(self.key.clone())
594 }
595}
596
597impl PipelineCommand for DecrByCommand {
598 fn name(&self) -> &str {
599 self.command_name()
600 }
601
602 fn args(&self) -> Vec<RespValue> {
603 <Self as Command>::args(self)
604 }
605
606 fn key(&self) -> Option<String> {
607 Some(self.key.clone())
608 }
609}
610
611impl PipelineCommand for ExistsCommand {
612 fn name(&self) -> &str {
613 self.command_name()
614 }
615
616 fn args(&self) -> Vec<RespValue> {
617 <Self as Command>::args(self)
618 }
619
620 fn key(&self) -> Option<String> {
621 self.keys.first().cloned()
622 }
623}
624
625impl PipelineCommand for ExpireCommand {
626 fn name(&self) -> &str {
627 self.command_name()
628 }
629
630 fn args(&self) -> Vec<RespValue> {
631 <Self as Command>::args(self)
632 }
633
634 fn key(&self) -> Option<String> {
635 Some(self.key.clone())
636 }
637}
638
639impl PipelineCommand for TtlCommand {
640 fn name(&self) -> &str {
641 self.command_name()
642 }
643
644 fn args(&self) -> Vec<RespValue> {
645 <Self as Command>::args(self)
646 }
647
648 fn key(&self) -> Option<String> {
649 Some(self.key.clone())
650 }
651}