mco_redis/cmd/
lists.rs

1use super::{utils, Command, CommandError};
2use crate::codec_redis::{BulkString, Request, Response};
3
4/// LINDEX redis command
5///
6/// Returns the element at index index in the list stored at key.
7///
8/// ```rust
9/// use ntex_redis::{cmd, RedisConnector};
10/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
11/// # fn gen_random_key() -> String {
12/// #    thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
13/// # }
14///
15/// #[ntex::main]
16/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
17///     let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
18///     let key = gen_random_key();
19///
20///     // create list with one value
21///     redis.exec(cmd::LPush(&key, "value")).await?;
22///
23///     // get value by index
24///     let value = redis.exec(cmd::LIndex(&key, 0)).await?;
25///
26///     assert_eq!(value.unwrap(), "value");
27///     Ok(())
28/// }
29/// ```
30pub fn LIndex<T>(key: T, index: i64) -> utils::BulkOutputCommand
31where
32    BulkString: From<T>,
33{
34    utils::BulkOutputCommand(Request::Array(vec![
35        Request::from_static("LINDEX"),
36        Request::BulkString(key.into()),
37        Request::BulkInteger(index),
38    ]))
39}
40
41/// LPOP redis command
42///
43/// Removes and returns the first element of the list stored at key.
44///
45/// ```rust
46/// use ntex_redis::{cmd, RedisConnector};
47/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
48/// # fn gen_random_key() -> String {
49/// #    thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
50/// # }
51///
52/// #[ntex::main]
53/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
54///     let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
55///     let key = gen_random_key();
56///
57///     // create list with one value
58///     redis.exec(cmd::LPush(&key, "value")).await?;
59///
60///     // pop first elements from the list
61///     let value = redis.exec(cmd::LPop(&key)).await?;
62///
63///     assert_eq!(value.unwrap(), "value");
64///     Ok(())
65/// }
66/// ```
67pub fn LPop<T>(key: T) -> utils::BulkOutputCommand
68where
69    BulkString: From<T>,
70{
71    utils::BulkOutputCommand(Request::Array(vec![
72        Request::from_static("LPOP"),
73        Request::BulkString(key.into()),
74    ]))
75}
76
77/// RPOP redis command
78///
79/// Removes and returns the last element of the list stored at key.
80///
81/// ```rust
82/// use ntex_redis::{cmd, RedisConnector};
83/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
84/// # fn gen_random_key() -> String {
85/// #    thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
86/// # }
87///
88/// #[ntex::main]
89/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
90///     let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
91///     let key = gen_random_key();
92///
93///     // create list with one value
94///     redis.exec(cmd::LPush(&key, "value")).await?;
95///
96///     // pop last elements from the list
97///     let value = redis.exec(cmd::RPop(&key)).await?;
98///
99///     assert_eq!(value.unwrap(), "value");
100///     Ok(())
101/// }
102/// ```
103pub fn RPop<T>(key: T) -> utils::BulkOutputCommand
104where
105    BulkString: From<T>,
106{
107    utils::BulkOutputCommand(Request::Array(vec![
108        Request::from_static("RPOP"),
109        Request::BulkString(key.into()),
110    ]))
111}
112
113/// LPUSH redis command
114///
115/// Insert all the specified values at the head of the list stored at key.
116///
117/// ```rust
118/// use ntex_redis::{cmd, RedisConnector};
119/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
120/// # fn gen_random_key() -> String {
121/// #    thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
122/// # }
123///
124/// #[ntex::main]
125/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
126///     let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
127///     let key = gen_random_key();
128///
129///     // create list with one value
130///     redis.exec(
131///         cmd::LPush(&key, "value1")
132///            .extend(vec!["value2", "value3", "value4"])
133///     ).await?;
134///
135///     Ok(())
136/// }
137/// ```
138///
139/// `LPushCommand::if_exists()` method changes `LPUSH` command to `LPUSHX` command
140///
141/// ```rust
142/// use ntex_redis::{cmd, RedisConnector};
143/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
144/// # fn gen_random_key() -> String {
145/// #    thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
146/// # }
147///
148/// #[ntex::main]
149/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
150///     let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
151///     let key = gen_random_key();
152///
153///     // create list with one value only if key already exists
154///     redis.exec(
155///         cmd::LPush(&key, "value1")
156///             .value("value2")
157///             .if_exists()
158///     ).await?;
159///
160///     Ok(())
161/// }
162/// ```
163pub fn LPush<T, V>(key: T, value: V) -> LPushCommand
164where
165    BulkString: From<T> + From<V>,
166{
167    LPushCommand(vec![
168        Request::from_static("LPUSH"),
169        Request::BulkString(key.into()),
170        Request::BulkString(value.into()),
171    ])
172}
173
174/// RPUSH redis command
175///
176/// Insert all the specified values at the tail of the list stored at key.
177pub fn RPush<T, V>(key: T, value: V) -> LPushCommand
178where
179    BulkString: From<T> + From<V>,
180{
181    LPushCommand(vec![
182        Request::from_static("RPUSH"),
183        Request::BulkString(key.into()),
184        Request::BulkString(value.into()),
185    ])
186}
187
188pub struct LPushCommand(Vec<Request>);
189
190impl LPushCommand {
191    /// Inserts specified values only if key already exists and holds a list.
192    pub fn if_exists(mut self) -> Self {
193        let cmd = if let Request::BulkStatic(ref s) = self.0[0] {
194            if s == b"LPUSH" || s == b"LPUSHX" {
195                "LPUSHX"
196            } else {
197                "RPUSHX"
198            }
199        } else {
200            "LPUSHX"
201        };
202        self.0[0] = Request::from_static(cmd);
203        self
204    }
205
206    /// Add a value to this command.
207    pub fn value<T>(mut self, other: T) -> Self
208    where
209        BulkString: From<T>,
210    {
211        self.0.push(other.into());
212        self
213    }
214
215    /// Add more values to this command.
216    pub fn extend<T>(mut self, other: impl IntoIterator<Item = T>) -> Self
217    where
218        BulkString: From<T>,
219    {
220        self.0.extend(other.into_iter().map(|t| t.into()));
221        self
222    }
223}
224
225impl Command for LPushCommand {
226    type Output = usize;
227
228    fn to_request(self) -> Request {
229        Request::Array(self.0)
230    }
231
232    fn to_output(val: Response) -> Result<Self::Output, CommandError> {
233        match val {
234            Response::Integer(val) => Ok(val as usize),
235            _ => Err(CommandError::Output("Cannot parse response", val)),
236        }
237    }
238}