fred/commands/interfaces/
lists.rs

1use crate::{
2  commands,
3  error::Error,
4  interfaces::{ClientLike, FredResult},
5  types::{
6    lists::{LMoveDirection, ListLocation},
7    FromValue,
8    Key,
9    Limit,
10    MultipleKeys,
11    MultipleStrings,
12    MultipleValues,
13    SortOrder,
14    Value,
15  },
16};
17use bytes_utils::Str;
18use fred_macros::rm_send_if;
19use futures::Future;
20use std::convert::TryInto;
21
22/// Functions that implement the [lists](https://redis.io/commands#lists) interface.
23#[rm_send_if(feature = "glommio")]
24pub trait ListInterface: ClientLike + Sized {
25  /// The blocking variant of [Self::lmpop].
26  ///
27  /// <https://redis.io/commands/blmpop/>
28  fn blmpop<R, K>(
29    &self,
30    timeout: f64,
31    keys: K,
32    direction: LMoveDirection,
33    count: Option<i64>,
34  ) -> impl Future<Output = FredResult<R>> + Send
35  where
36    R: FromValue,
37    K: Into<MultipleKeys> + Send,
38  {
39    async move {
40      into!(keys);
41      commands::lists::blmpop(self, timeout, keys, direction, count)
42        .await?
43        .convert()
44    }
45  }
46
47  /// BLPOP is a blocking list pop primitive. It is the blocking version of LPOP because it blocks the connection when
48  /// there are no elements to pop from any of the given lists. An element is popped from the head of the first list
49  /// that is non-empty, with the given keys being checked in the order that they are given.
50  ///
51  /// <https://redis.io/commands/blpop>
52  fn blpop<R, K>(&self, keys: K, timeout: f64) -> impl Future<Output = FredResult<R>> + Send
53  where
54    R: FromValue,
55    K: Into<MultipleKeys> + Send,
56  {
57    async move {
58      into!(keys);
59      commands::lists::blpop(self, keys, timeout).await?.convert()
60    }
61  }
62
63  /// BRPOP is a blocking list pop primitive. It is the blocking version of RPOP because it blocks the connection when
64  /// there are no elements to pop from any of the given lists. An element is popped from the tail of the first list
65  /// that is non-empty, with the given keys being checked in the order that they are given.
66  ///
67  /// <https://redis.io/commands/brpop>
68  fn brpop<R, K>(&self, keys: K, timeout: f64) -> impl Future<Output = FredResult<R>> + Send
69  where
70    R: FromValue,
71    K: Into<MultipleKeys> + Send,
72  {
73    async move {
74      into!(keys);
75      commands::lists::brpop(self, keys, timeout).await?.convert()
76    }
77  }
78
79  /// The blocking equivalent of [Self::rpoplpush].
80  ///
81  /// <https://redis.io/commands/brpoplpush>
82  fn brpoplpush<R, S, D>(&self, source: S, destination: D, timeout: f64) -> impl Future<Output = FredResult<R>> + Send
83  where
84    R: FromValue,
85    S: Into<Key> + Send,
86    D: Into<Key> + Send,
87  {
88    async move {
89      into!(source, destination);
90      commands::lists::brpoplpush(self, source, destination, timeout)
91        .await?
92        .convert()
93    }
94  }
95
96  /// The blocking equivalent of [Self::lmove].
97  ///
98  /// <https://redis.io/commands/blmove>
99  fn blmove<R, S, D>(
100    &self,
101    source: S,
102    destination: D,
103    source_direction: LMoveDirection,
104    destination_direction: LMoveDirection,
105    timeout: f64,
106  ) -> impl Future<Output = FredResult<R>> + Send
107  where
108    R: FromValue,
109    S: Into<Key> + Send,
110    D: Into<Key> + Send,
111  {
112    async move {
113      into!(source, destination);
114      commands::lists::blmove(
115        self,
116        source,
117        destination,
118        source_direction,
119        destination_direction,
120        timeout,
121      )
122      .await?
123      .convert()
124    }
125  }
126
127  /// Pops one or more elements from the first non-empty list key from the list of provided key names.
128  ///
129  /// <https://redis.io/commands/lmpop/>
130  fn lmpop<R, K>(
131    &self,
132    keys: K,
133    direction: LMoveDirection,
134    count: Option<i64>,
135  ) -> impl Future<Output = FredResult<R>> + Send
136  where
137    R: FromValue,
138    K: Into<MultipleKeys> + Send,
139  {
140    async move {
141      into!(keys);
142      commands::lists::lmpop(self, keys, direction, count).await?.convert()
143    }
144  }
145
146  /// Returns the element at index in the list stored at key.
147  ///
148  /// <https://redis.io/commands/lindex>
149  fn lindex<R, K>(&self, key: K, index: i64) -> impl Future<Output = FredResult<R>> + Send
150  where
151    R: FromValue,
152    K: Into<Key> + Send,
153  {
154    async move {
155      into!(key);
156      commands::lists::lindex(self, key, index).await?.convert()
157    }
158  }
159
160  /// Inserts element in the list stored at key either before or after the reference value `pivot`.
161  ///
162  /// <https://redis.io/commands/linsert>
163  fn linsert<R, K, P, V>(
164    &self,
165    key: K,
166    location: ListLocation,
167    pivot: P,
168    element: V,
169  ) -> impl Future<Output = FredResult<R>> + Send
170  where
171    R: FromValue,
172    K: Into<Key> + Send,
173    P: TryInto<Value> + Send,
174    P::Error: Into<Error> + Send,
175    V: TryInto<Value> + Send,
176    V::Error: Into<Error> + Send,
177  {
178    async move {
179      into!(key);
180      try_into!(pivot, element);
181      commands::lists::linsert(self, key, location, pivot, element)
182        .await?
183        .convert()
184    }
185  }
186
187  /// Returns the length of the list stored at key.
188  ///
189  /// <https://redis.io/commands/llen>
190  fn llen<R, K>(&self, key: K) -> impl Future<Output = FredResult<R>> + Send
191  where
192    R: FromValue,
193    K: Into<Key> + Send,
194  {
195    async move {
196      into!(key);
197      commands::lists::llen(self, key).await?.convert()
198    }
199  }
200
201  /// Removes and returns the first elements of the list stored at key.
202  ///
203  /// <https://redis.io/commands/lpop>
204  fn lpop<R, K>(&self, key: K, count: Option<usize>) -> impl Future<Output = FredResult<R>> + Send
205  where
206    R: FromValue,
207    K: Into<Key> + Send,
208  {
209    async move {
210      into!(key);
211      commands::lists::lpop(self, key, count).await?.convert()
212    }
213  }
214
215  /// The command returns the index of matching elements inside a Redis list.
216  ///
217  /// <https://redis.io/commands/lpos>
218  fn lpos<R, K, V>(
219    &self,
220    key: K,
221    element: V,
222    rank: Option<i64>,
223    count: Option<i64>,
224    maxlen: Option<i64>,
225  ) -> impl Future<Output = FredResult<R>> + Send
226  where
227    R: FromValue,
228    K: Into<Key> + Send,
229    V: TryInto<Value> + Send,
230    V::Error: Into<Error> + Send,
231  {
232    async move {
233      into!(key);
234      try_into!(element);
235      commands::lists::lpos(self, key, element, rank, count, maxlen)
236        .await?
237        .convert()
238    }
239  }
240
241  /// Insert all the specified values at the head of the list stored at `key`.
242  ///
243  /// <https://redis.io/commands/lpush>
244  fn lpush<R, K, V>(&self, key: K, elements: V) -> impl Future<Output = FredResult<R>> + Send
245  where
246    R: FromValue,
247    K: Into<Key> + Send,
248    V: TryInto<MultipleValues> + Send,
249    V::Error: Into<Error> + Send,
250  {
251    async move {
252      into!(key);
253      try_into!(elements);
254      commands::lists::lpush(self, key, elements).await?.convert()
255    }
256  }
257
258  /// Inserts specified values at the head of the list stored at `key`, only if `key` already exists and holds a list.
259  ///
260  /// <https://redis.io/commands/lpushx>
261  fn lpushx<R, K, V>(&self, key: K, elements: V) -> impl Future<Output = FredResult<R>> + Send
262  where
263    R: FromValue,
264    K: Into<Key> + Send,
265    V: TryInto<MultipleValues> + Send,
266    V::Error: Into<Error> + Send,
267  {
268    async move {
269      into!(key);
270      try_into!(elements);
271      commands::lists::lpushx(self, key, elements).await?.convert()
272    }
273  }
274
275  /// Returns the specified elements of the list stored at `key`.
276  ///
277  /// <https://redis.io/commands/lrange>
278  fn lrange<R, K>(&self, key: K, start: i64, stop: i64) -> impl Future<Output = FredResult<R>> + Send
279  where
280    R: FromValue,
281    K: Into<Key> + Send,
282  {
283    async move {
284      into!(key);
285      commands::lists::lrange(self, key, start, stop).await?.convert()
286    }
287  }
288
289  /// Removes the first `count` occurrences of elements equal to `element` from the list stored at `key`.
290  ///
291  /// <https://redis.io/commands/lrem>
292  fn lrem<R, K, V>(&self, key: K, count: i64, element: V) -> impl Future<Output = FredResult<R>> + Send
293  where
294    R: FromValue,
295    K: Into<Key> + Send,
296    V: TryInto<Value> + Send,
297    V::Error: Into<Error> + Send,
298  {
299    async move {
300      into!(key);
301      try_into!(element);
302      commands::lists::lrem(self, key, count, element).await?.convert()
303    }
304  }
305
306  /// Sets the list element at `index` to `element`.
307  ///
308  /// <https://redis.io/commands/lset>
309  fn lset<R, K, V>(&self, key: K, index: i64, element: V) -> impl Future<Output = FredResult<R>> + Send
310  where
311    R: FromValue,
312    K: Into<Key> + Send,
313    V: TryInto<Value> + Send,
314    V::Error: Into<Error> + Send,
315  {
316    async move {
317      into!(key);
318      try_into!(element);
319      commands::lists::lset(self, key, index, element).await?.convert()
320    }
321  }
322
323  /// Trim an existing list so that it will contain only the specified range of elements specified.
324  ///
325  /// <https://redis.io/commands/ltrim>
326  fn ltrim<R, K>(&self, key: K, start: i64, stop: i64) -> impl Future<Output = FredResult<R>> + Send
327  where
328    R: FromValue,
329    K: Into<Key> + Send,
330  {
331    async move {
332      into!(key);
333      commands::lists::ltrim(self, key, start, stop).await?.convert()
334    }
335  }
336
337  /// Removes and returns the last elements of the list stored at `key`.
338  ///
339  /// <https://redis.io/commands/rpop>
340  fn rpop<R, K>(&self, key: K, count: Option<usize>) -> impl Future<Output = FredResult<R>> + Send
341  where
342    R: FromValue,
343    K: Into<Key> + Send,
344  {
345    async move {
346      into!(key);
347      commands::lists::rpop(self, key, count).await?.convert()
348    }
349  }
350
351  /// Atomically returns and removes the last element (tail) of the list stored at `source`, and pushes the element at
352  /// the first element (head) of the list stored at `destination`.
353  ///
354  /// <https://redis.io/commands/rpoplpush>
355  fn rpoplpush<R, S, D>(&self, source: S, dest: D) -> impl Future<Output = FredResult<R>> + Send
356  where
357    R: FromValue,
358    S: Into<Key> + Send,
359    D: Into<Key> + Send,
360  {
361    async move {
362      into!(source, dest);
363      commands::lists::rpoplpush(self, source, dest).await?.convert()
364    }
365  }
366
367  /// Atomically returns and removes the first/last element (head/tail depending on the source direction argument) of
368  /// the list stored at `source`, and pushes the element at the first/last element (head/tail depending on the
369  /// destination direction argument) of the list stored at `destination`.
370  ///
371  /// <https://redis.io/commands/lmove>
372  fn lmove<R, S, D>(
373    &self,
374    source: S,
375    dest: D,
376    source_direction: LMoveDirection,
377    dest_direction: LMoveDirection,
378  ) -> impl Future<Output = FredResult<R>> + Send
379  where
380    R: FromValue,
381    S: Into<Key> + Send,
382    D: Into<Key> + Send,
383  {
384    async move {
385      into!(source, dest);
386      commands::lists::lmove(self, source, dest, source_direction, dest_direction)
387        .await?
388        .convert()
389    }
390  }
391
392  /// Insert all the specified values at the tail of the list stored at `key`.
393  ///
394  /// <https://redis.io/commands/rpush>
395  fn rpush<R, K, V>(&self, key: K, elements: V) -> impl Future<Output = FredResult<R>> + Send
396  where
397    R: FromValue,
398    K: Into<Key> + Send,
399    V: TryInto<MultipleValues> + Send,
400    V::Error: Into<Error> + Send,
401  {
402    async move {
403      into!(key);
404      try_into!(elements);
405      commands::lists::rpush(self, key, elements).await?.convert()
406    }
407  }
408
409  /// Inserts specified values at the tail of the list stored at `key`, only if key already exists and holds a list.
410  ///
411  /// <https://redis.io/commands/rpushx>
412  fn rpushx<R, K, V>(&self, key: K, elements: V) -> impl Future<Output = FredResult<R>> + Send
413  where
414    R: FromValue,
415    K: Into<Key> + Send,
416    V: TryInto<MultipleValues> + Send,
417    V::Error: Into<Error> + Send,
418  {
419    async move {
420      into!(key);
421      try_into!(elements);
422      commands::lists::rpushx(self, key, elements).await?.convert()
423    }
424  }
425
426  /// Returns or stores the elements contained in the list, set or sorted set at `key`.
427  ///
428  /// <https://redis.io/commands/sort/>
429  fn sort<R, K, S>(
430    &self,
431    key: K,
432    by: Option<Str>,
433    limit: Option<Limit>,
434    get: S,
435    order: Option<SortOrder>,
436    alpha: bool,
437    store: Option<Key>,
438  ) -> impl Future<Output = FredResult<R>> + Send
439  where
440    R: FromValue,
441    K: Into<Key> + Send,
442    S: Into<MultipleStrings> + Send,
443  {
444    async move {
445      into!(key, get);
446      commands::lists::sort(self, key, by, limit, get, order, alpha, store)
447        .await?
448        .convert()
449    }
450  }
451
452  /// Read-only variant of the SORT command. It is exactly like the original SORT but refuses the STORE option and can
453  /// safely be used in read-only replicas.
454  ///
455  /// <https://redis.io/commands/sort_ro/>
456  fn sort_ro<R, K, S>(
457    &self,
458    key: K,
459    by: Option<Str>,
460    limit: Option<Limit>,
461    get: S,
462    order: Option<SortOrder>,
463    alpha: bool,
464  ) -> impl Future<Output = FredResult<R>> + Send
465  where
466    R: FromValue,
467    K: Into<Key> + Send,
468    S: Into<MultipleStrings> + Send,
469  {
470    async move {
471      into!(key, get);
472      commands::lists::sort_ro(self, key, by, limit, get, order, alpha)
473        .await?
474        .convert()
475    }
476  }
477}