mco_redis/cmd/
strings.rs

1use super::{utils, Command, CommandError};
2use crate::codec_redis::{BulkString, Request, Response};
3
4/// GET redis command
5pub fn Get<T>(key: T) -> utils::BulkOutputCommand
6where
7    BulkString: From<T>,
8{
9    utils::BulkOutputCommand(Request::Array(vec![
10        Request::from_static("GET"),
11        Request::BulkString(key.into()),
12    ]))
13}
14
15/// SET redis command
16///
17/// Set key to hold the string value. Command returns true if value is set
18/// otherwise it returns false
19pub fn Set<T, V>(key: T, value: V) -> SetCommand
20where
21    BulkString: From<T> + From<V>,
22{
23    SetCommand {
24        req: vec![
25            Request::from_bstatic(b"SET"),
26            Request::BulkString(key.into()),
27            Request::BulkString(value.into()),
28        ],
29        expire: Expire::None,
30        keepttl: false,
31        exists: None,
32    }
33}
34
35enum Expire {
36    None,
37    Ex(Request),
38    Px(Request),
39}
40
41pub struct SetCommand {
42    req: Vec<Request>,
43    expire: Expire,
44    keepttl: bool,
45    exists: Option<bool>,
46}
47
48impl SetCommand {
49    /// Set the specified expire time, in seconds.
50    pub fn expire_secs(mut self, secs: i64) -> Self {
51        self.expire = Expire::Ex(Request::BulkInteger(secs));
52        self
53    }
54
55    /// Set the specified expire time, in milliseconds.
56    pub fn expire_millis(mut self, secs: i64) -> Self {
57        self.expire = Expire::Px(Request::BulkInteger(secs));
58        self
59    }
60
61    /// Only set the key if it already exist.
62    pub fn if_exists(mut self) -> Self {
63        self.exists = Some(true);
64        self
65    }
66
67    /// Only set the key if it does not already exist.
68    pub fn if_not_exists(mut self) -> Self {
69        self.exists = Some(false);
70        self
71    }
72
73    /// Retain the time to live associated with the key.
74    pub fn keepttl(mut self) -> Self {
75        self.keepttl = true;
76        self
77    }
78}
79
80impl Command for SetCommand {
81    type Output = bool;
82
83    fn to_request(mut self) -> Request {
84        // EX|PX
85        match self.expire {
86            Expire::None => (),
87            Expire::Ex(r) => {
88                self.req.push(Request::from_bstatic(b"EX"));
89                self.req.push(r);
90            }
91            Expire::Px(r) => {
92                self.req.push(Request::from_bstatic(b"PX"));
93                self.req.push(r);
94            }
95        }
96
97        // NX|XX
98        if let Some(exists) = self.exists {
99            self.req.push(if exists {
100                Request::from_bstatic(b"XX")
101            } else {
102                Request::from_bstatic(b"NX")
103            });
104        }
105
106        // KEEPTTL
107        if self.keepttl {
108            self.req.push(Request::from_bstatic(b"KEEPTTL"))
109        }
110
111        Request::Array(self.req)
112    }
113
114    fn to_output(val: Response) -> Result<Self::Output, CommandError> {
115        match val {
116            Response::Nil => Ok(false),
117            Response::String(string) => match string.as_ref() {
118                "OK" => Ok(true),
119                _ => Err(CommandError::Output(
120                    "Unexpected value within String",
121                    Response::String(string),
122                )),
123            },
124            _ => Err(CommandError::Output("Unexpected value", val)),
125        }
126    }
127}
128
129/// INCRBY redis command
130///
131/// Increments the number stored at `key` by `increment`.
132pub fn IncrBy<T, I>(key: T, increment: I) -> utils::IntOutputCommand
133where
134    BulkString: From<T>,
135    i64: From<I>,
136{
137    utils::IntOutputCommand(Request::Array(vec![
138        Request::from_static("INCRBY"),
139        Request::BulkString(key.into()),
140        Request::BulkString(i64::from(increment).to_string().into()),
141    ]))
142}