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}