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