redis_ac/
commands.rs

1// Copyright (c) 2019 by Yushi Omote.
2//
3// Some rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10//       notice, this list of conditions and the following disclaimer.
11//
12//     * Redistributions in binary form must reproduce the above
13//       copyright notice, this list of conditions and the following
14//       disclaimer in the documentation and/or other materials provided
15//       with the distribution.
16//
17//     * The names of the contributors may not be used to endorse or
18//       promote products derived from this software without specific
19//       prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33use redis::aio::ConnectionLike;
34use redis::{cmd, FromRedisValue, NumericBehavior, RedisFuture, ToRedisArgs};
35
36#[cfg(feature = "geospatial")]
37use redis::geo;
38
39use crate::stream::stream;
40pub use crate::stream::{RedisScanAll, RedisScanStream};
41
42impl<T> Commands for T where T: ConnectionLike + Send + Sized + 'static {}
43
44macro_rules! implement_commands {
45    (
46        $(
47            $(#[$attr:meta])+
48            fn $name:ident<$($tyargs:ident : $ty:ident),*>(
49                $($argname:ident: $argty:ty),*) $body:block
50        )*
51    ) =>
52    (
53
54        /// Asynchronous version of [`redis::Commands`][].
55        ///
56        /// # Constraints
57        ///
58        /// The arguments of scan commands are required to implement `Clone` because
59        /// they need to create multiple [`redis::Cmd`][] objects internally.
60        pub trait Commands : ConnectionLike+Send+Sized+'static {
61            $(
62                $(#[$attr])*
63                #[inline]
64                fn $name<$($tyargs: $ty,)* RV: FromRedisValue+Send+'static>(self $(, $argname: $argty)*) -> RedisFuture<(Self, RV)>
65                    { ($body).query_async(self) }
66            )*
67
68            /// Incrementally iterate the keys space.
69            #[inline]
70            fn scan<RV: FromRedisValue+Send+'static>(self) -> RedisScanStream<Self, RV> {
71                stream(self, |cur| {
72                    let mut c = cmd("SCAN");
73                    c.arg(cur);
74                    c
75                })
76            }
77
78            /// Incrementally iterate the keys space for keys matching a pattern.
79            #[inline]
80            fn scan_match<P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, pattern: P) -> RedisScanStream<Self, RV> {
81                stream(self, move |cur| {
82                    let mut c = cmd("SCAN");
83                    c.arg(cur)
84                        .arg("MATCH")
85                        .arg(pattern.clone());
86                    c
87                })
88            }
89
90            /// Incrementally iterate hash fields and associated values.
91            #[inline]
92            fn hscan<K: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, key: K) -> RedisScanStream<Self, RV> {
93                stream(self, move |cur| {
94                    let mut c = cmd("HSCAN");
95                    c.arg(key.clone()).arg(cur);
96                    c
97                })
98            }
99
100            /// Incrementally iterate hash fields and associated values for
101            /// field names matching a pattern.
102            #[inline]
103            fn hscan_match<K: ToRedisArgs+Clone+Send+'static, P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>
104                    (self, key: K, pattern: P) -> RedisScanStream<Self, RV> {
105                stream(self, move |cur| {
106                    let mut c = cmd("HSCAN");
107                    c.arg(key.clone()).arg(cur).arg("MATCH").arg(pattern.clone());
108                    c
109                })
110            }
111
112            /// Incrementally iterate set elements.
113            #[inline]
114            fn sscan<K: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, key: K) -> RedisScanStream<Self, RV> {
115                stream(self, move |cur| {
116                    let mut c = cmd("SSCAN");
117                    c.arg(key.clone()).cursor_arg(cur);
118                    c
119                })
120            }
121
122            /// Incrementally iterate set elements for elements matching a pattern.
123            #[inline]
124            fn sscan_match<K: ToRedisArgs+Clone+Send+'static, P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>
125                    (self, key: K, pattern: P) -> RedisScanStream<Self, RV> {
126                stream(self, move |cur| {
127                    let mut c = cmd("SSCAN");
128                    c.arg(key.clone()).arg(cur).arg("MATCH").arg(pattern.clone());
129                    c
130                })
131            }
132
133            /// Incrementally iterate sorted set elements.
134            #[inline]
135            fn zscan<K: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>(self, key: K) -> RedisScanStream<Self, RV> {
136                stream(self, move |cur| {
137                    let mut c = cmd("ZSCAN");
138                    c.arg(key.clone()).arg(cur);
139                    c
140                })
141            }
142
143            /// Incrementally iterate sorted set elements for elements matching a pattern.
144            #[inline]
145            fn zscan_match<K: ToRedisArgs+Clone+Send+'static, P: ToRedisArgs+Clone+Send+'static, RV: FromRedisValue+Send+'static>
146                    (self, key: K, pattern: P) -> RedisScanStream<Self, RV> {
147                stream(self, move |cur| {
148                    let mut c = cmd("ZSCAN");
149                    c.arg(key.clone()).arg(cur).arg("MATCH").arg(pattern.clone());
150                    c
151                })
152            }
153        }
154    )
155}
156
157// Copyright (c) 2013 by Armin Ronacher.
158//
159// Some rights reserved.
160//
161// Redistribution and use in source and binary forms, with or without
162// modification, are permitted provided that the following conditions are
163// met:
164//
165//     * Redistributions of source code must retain the above copyright
166//       notice, this list of conditions and the following disclaimer.
167//
168//     * Redistributions in binary form must reproduce the above
169//       copyright notice, this list of conditions and the following
170//       disclaimer in the documentation and/or other materials provided
171//       with the distribution.
172//
173//     * The names of the contributors may not be used to endorse or
174//       promote products derived from this software without specific
175//       prior written permission.
176//
177// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
178// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
179// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
180// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
181// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
182// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
183// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
184// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
185// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
186// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
187// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
188//
189// https://docs.rs/redis/0.13.0/src/redis/commands.rs.html
190//
191
192implement_commands! {
193    // most common operations
194
195    /// Get the value of a key.  If key is a vec this becomes an `MGET`.
196    fn get<K: ToRedisArgs>(key: K) {
197        cmd(if key.is_single_arg() { "GET" } else { "MGET" }).arg(key)
198    }
199
200    /// Gets all keys matching pattern
201    fn keys<K: ToRedisArgs>(key: K) {
202        cmd("KEYS").arg(key)
203    }
204
205    /// Set the string value of a key.
206    fn set<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
207        cmd("SET").arg(key).arg(value)
208    }
209
210    /// Sets multiple keys to their values.
211    fn set_multiple<K: ToRedisArgs, V: ToRedisArgs>(items: &[(K, V)]) {
212        cmd("MSET").arg(items)
213    }
214
215    /// Set the value and expiration of a key.
216    fn set_ex<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V, seconds: usize) {
217        cmd("SETEX").arg(key).arg(seconds).arg(value)
218    }
219
220    /// Set the value of a key, only if the key does not exist
221    fn set_nx<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
222        cmd("SETNX").arg(key).arg(value)
223    }
224
225    /// Sets multiple keys to their values failing if at least one already exists.
226    fn mset_nx<K: ToRedisArgs, V: ToRedisArgs>(items: &[(K, V)]) {
227        cmd("MSETNX").arg(items)
228    }
229
230    /// Set the string value of a key and return its old value.
231    fn getset<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
232        cmd("GETSET").arg(key).arg(value)
233    }
234
235    /// Get a range of bytes/substring from the value of a key. Negative values provide an offset from the end of the value.
236    fn getrange<K: ToRedisArgs>(key: K, from: isize, to: isize) {
237        cmd("GETRANGE").arg(key).arg(from).arg(to)
238    }
239
240    /// Overwrite the part of the value stored in key at the specified offset.
241    fn setrange<K: ToRedisArgs, V: ToRedisArgs>(key: K, offset: isize, value: V) {
242        cmd("SETRANGE").arg(key).arg(offset).arg(value)
243    }
244
245    /// Delete one or more keys.
246    fn del<K: ToRedisArgs>(key: K) {
247        cmd("DEL").arg(key)
248    }
249
250    /// Determine if a key exists.
251    fn exists<K: ToRedisArgs>(key: K) {
252        cmd("EXISTS").arg(key)
253    }
254
255    /// Set a key's time to live in seconds.
256    fn expire<K: ToRedisArgs>(key: K, seconds: usize) {
257        cmd("EXPIRE").arg(key).arg(seconds)
258    }
259
260    /// Set the expiration for a key as a UNIX timestamp.
261    fn expire_at<K: ToRedisArgs>(key: K, ts: usize) {
262        cmd("EXPIREAT").arg(key).arg(ts)
263    }
264
265    /// Set a key's time to live in milliseconds.
266    fn pexpire<K: ToRedisArgs>(key: K, ms: usize) {
267        cmd("PEXPIRE").arg(key).arg(ms)
268    }
269
270    /// Set the expiration for a key as a UNIX timestamp in milliseconds.
271    fn pexpire_at<K: ToRedisArgs>(key: K, ts: usize) {
272        cmd("PEXPIREAT").arg(key).arg(ts)
273    }
274
275    /// Remove the expiration from a key.
276    fn persist<K: ToRedisArgs>(key: K) {
277        cmd("PERSIST").arg(key)
278    }
279
280    /// Check the expiration time of a key.
281    fn ttl<K: ToRedisArgs>(key: K) {
282        cmd("TTL").arg(key)
283    }
284
285    /// Rename a key.
286    fn rename<K: ToRedisArgs>(key: K, new_key: K) {
287        cmd("RENAME").arg(key).arg(new_key)
288    }
289
290    /// Rename a key, only if the new key does not exist.
291    fn rename_nx<K: ToRedisArgs>(key: K, new_key: K) {
292        cmd("RENAMENX").arg(key).arg(new_key)
293    }
294
295    // common string operations
296
297    /// Append a value to a key.
298    fn append<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
299        cmd("APPEND").arg(key).arg(value)
300    }
301
302    /// Increment the numeric value of a key by the given amount.  This
303    /// issues a `INCRBY` or `INCRBYFLOAT` depending on the type.
304    fn incr<K: ToRedisArgs, V: ToRedisArgs>(key: K, delta: V) {
305        cmd(if delta.describe_numeric_behavior() == NumericBehavior::NumberIsFloat {
306            "INCRBYFLOAT"
307        } else {
308            "INCRBY"
309        }).arg(key).arg(delta)
310    }
311
312    /// Sets or clears the bit at offset in the string value stored at key.
313    fn setbit<K: ToRedisArgs>(key: K, offset: usize, value: bool) {
314        cmd("SETBIT").arg(key).arg(offset).arg(if value {1} else {0})
315    }
316
317    /// Returns the bit value at offset in the string value stored at key.
318    fn getbit<K: ToRedisArgs>(key: K, offset: usize) {
319        cmd("GETBIT").arg(key).arg(offset)
320    }
321
322    /// Count set bits in a string.
323    fn bitcount<K: ToRedisArgs>(key: K) {
324        cmd("BITCOUNT").arg(key)
325    }
326
327    /// Count set bits in a string in a range.
328    fn bitcount_range<K: ToRedisArgs>(key: K, start: usize, end: usize) {
329        cmd("BITCOUNT").arg(key).arg(start).arg(end)
330    }
331
332    /// Perform a bitwise AND between multiple keys (containing string values)
333    /// and store the result in the destination key.
334    fn bit_and<K: ToRedisArgs>(dstkey: K, srckeys: K) {
335        cmd("BITOP").arg("AND").arg(dstkey).arg(srckeys)
336    }
337
338    /// Perform a bitwise OR between multiple keys (containing string values)
339    /// and store the result in the destination key.
340    fn bit_or<K: ToRedisArgs>(dstkey: K, srckeys: K) {
341        cmd("BITOP").arg("OR").arg(dstkey).arg(srckeys)
342    }
343
344    /// Perform a bitwise XOR between multiple keys (containing string values)
345    /// and store the result in the destination key.
346    fn bit_xor<K: ToRedisArgs>(dstkey: K, srckeys: K) {
347        cmd("BITOP").arg("XOR").arg(dstkey).arg(srckeys)
348    }
349
350    /// Perform a bitwise NOT of the key (containing string values)
351    /// and store the result in the destination key.
352    fn bit_not<K: ToRedisArgs>(dstkey: K, srckey: K) {
353        cmd("BITOP").arg("NOT").arg(dstkey).arg(srckey)
354    }
355
356    /// Get the length of the value stored in a key.
357    fn strlen<K: ToRedisArgs>(key: K) {
358        cmd("STRLEN").arg(key)
359    }
360
361    // hash operations
362
363    /// Gets a single (or multiple) fields from a hash.
364    fn hget<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
365        cmd(if field.is_single_arg() { "HGET" } else { "HMGET" }).arg(key).arg(field)
366    }
367
368    /// Deletes a single (or multiple) fields from a hash.
369    fn hdel<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
370        cmd("HDEL").arg(key).arg(field)
371    }
372
373    /// Sets a single field in a hash.
374    fn hset<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, field: F, value: V) {
375        cmd("HSET").arg(key).arg(field).arg(value)
376    }
377
378    /// Sets a single field in a hash if it does not exist.
379    fn hset_nx<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, field: F, value: V) {
380        cmd("HSETNX").arg(key).arg(field).arg(value)
381    }
382
383    /// Sets a multiple fields in a hash.
384    fn hset_multiple<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, items: &[(F, V)]) {
385        cmd("HMSET").arg(key).arg(items)
386    }
387
388    /// Increments a value.
389    fn hincr<K: ToRedisArgs, F: ToRedisArgs, D: ToRedisArgs>(key: K, field: F, delta: D) {
390        cmd(if delta.describe_numeric_behavior() == NumericBehavior::NumberIsFloat {
391            "HINCRBYFLOAT"
392        } else {
393            "HINCRBY"
394        }).arg(key).arg(field).arg(delta)
395    }
396
397    /// Checks if a field in a hash exists.
398    fn hexists<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
399        cmd("HEXISTS").arg(key).arg(field)
400    }
401
402    /// Gets all the keys in a hash.
403    fn hkeys<K: ToRedisArgs>(key: K) {
404        cmd("HKEYS").arg(key)
405    }
406
407    /// Gets all the values in a hash.
408    fn hvals<K: ToRedisArgs>(key: K) {
409        cmd("HVALS").arg(key)
410    }
411
412    /// Gets all the fields and values in a hash.
413    fn hgetall<K: ToRedisArgs>(key: K) {
414        cmd("HGETALL").arg(key)
415    }
416
417    /// Gets the length of a hash.
418    fn hlen<K: ToRedisArgs>(key: K) {
419        cmd("HLEN").arg(key)
420    }
421
422    // list operations
423
424    /// Remove and get the first element in a list, or block until one is available.
425    fn blpop<K: ToRedisArgs>(key: K, timeout: usize) {
426        cmd("BLPOP").arg(key).arg(timeout)
427    }
428
429    /// Remove and get the last element in a list, or block until one is available.
430    fn brpop<K: ToRedisArgs>(key: K, timeout: usize) {
431        cmd("BRPOP").arg(key).arg(timeout)
432    }
433
434    /// Pop a value from a list, push it to another list and return it;
435    /// or block until one is available.
436    fn brpoplpush<K: ToRedisArgs>(srckey: K, dstkey: K, timeout: usize) {
437        cmd("BRPOPLPUSH").arg(srckey).arg(dstkey).arg(timeout)
438    }
439
440    /// Get an element from a list by its index.
441    fn lindex<K: ToRedisArgs>(key: K, index: isize) {
442        cmd("LINDEX").arg(key).arg(index)
443    }
444
445    /// Insert an element before another element in a list.
446    fn linsert_before<K: ToRedisArgs, P: ToRedisArgs, V: ToRedisArgs>(
447            key: K, pivot: P, value: V) {
448        cmd("LINSERT").arg(key).arg("BEFORE").arg(pivot).arg(value)
449    }
450
451    /// Insert an element after another element in a list.
452    fn linsert_after<K: ToRedisArgs, P: ToRedisArgs, V: ToRedisArgs>(
453            key: K, pivot: P, value: V) {
454        cmd("LINSERT").arg(key).arg("AFTER").arg(pivot).arg(value)
455    }
456
457    /// Returns the length of the list stored at key.
458    fn llen<K: ToRedisArgs>(key: K) {
459        cmd("LLEN").arg(key)
460    }
461
462    /// Removes and returns the first element of the list stored at key.
463    fn lpop<K: ToRedisArgs>(key: K) {
464        cmd("LPOP").arg(key)
465    }
466
467    /// Insert all the specified values at the head of the list stored at key.
468    fn lpush<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
469        cmd("LPUSH").arg(key).arg(value)
470    }
471
472    /// Inserts a value at the head of the list stored at key, only if key
473    /// already exists and holds a list.
474    fn lpush_exists<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
475        cmd("LPUSHX").arg(key).arg(value)
476    }
477
478    /// Returns the specified elements of the list stored at key.
479    fn lrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
480        cmd("LRANGE").arg(key).arg(start).arg(stop)
481    }
482
483    /// Removes the first count occurrences of elements equal to value
484    /// from the list stored at key.
485    fn lrem<K: ToRedisArgs, V: ToRedisArgs>(key: K, count: isize, value: V) {
486        cmd("LREM").arg(key).arg(count).arg(value)
487    }
488
489    /// Trim an existing list so that it will contain only the specified
490    /// range of elements specified.
491    fn ltrim<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
492        cmd("LTRIM").arg(key).arg(start).arg(stop)
493    }
494
495    /// Sets the list element at index to value
496    fn lset<K: ToRedisArgs, V: ToRedisArgs>(key: K, index: isize, value: V) {
497        cmd("LSET").arg(key).arg(index).arg(value)
498    }
499
500    /// Removes and returns the last element of the list stored at key.
501    fn rpop<K: ToRedisArgs>(key: K) {
502        cmd("RPOP").arg(key)
503    }
504
505    /// Pop a value from a list, push it to another list and return it.
506    fn rpoplpush<K: ToRedisArgs>(key: K, dstkey: K) {
507        cmd("RPOPLPUSH").arg(key).arg(dstkey)
508    }
509
510    /// Insert all the specified values at the tail of the list stored at key.
511    fn rpush<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
512        cmd("RPUSH").arg(key).arg(value)
513    }
514
515    /// Inserts value at the tail of the list stored at key, only if key
516    /// already exists and holds a list.
517    fn rpush_exists<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
518        cmd("RPUSHX").arg(key).arg(value)
519    }
520
521    // set commands
522
523    /// Add one or more members to a set.
524    fn sadd<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
525        cmd("SADD").arg(key).arg(member)
526    }
527
528    /// Get the number of members in a set.
529    fn scard<K: ToRedisArgs>(key: K) {
530        cmd("SCARD").arg(key)
531    }
532
533    /// Subtract multiple sets.
534    fn sdiff<K: ToRedisArgs>(keys: K) {
535        cmd("SDIFF").arg(keys)
536    }
537
538    /// Subtract multiple sets and store the resulting set in a key.
539    fn sdiffstore<K: ToRedisArgs>(dstkey: K, keys: K) {
540        cmd("SDIFFSTORE").arg(dstkey).arg(keys)
541    }
542
543    /// Intersect multiple sets.
544    fn sinter<K: ToRedisArgs>(keys: K) {
545        cmd("SINTER").arg(keys)
546    }
547
548    /// Intersect multiple sets and store the resulting set in a key.
549    fn sinterstore<K: ToRedisArgs>(dstkey: K, keys: K) {
550        cmd("SINTERSTORE").arg(dstkey).arg(keys)
551    }
552
553    /// Determine if a given value is a member of a set.
554    fn sismember<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
555        cmd("SISMEMBER").arg(key).arg(member)
556    }
557
558    /// Get all the members in a set.
559    fn smembers<K: ToRedisArgs>(key: K) {
560        cmd("SMEMBERS").arg(key)
561    }
562
563    /// Move a member from one set to another.
564    fn smove<K: ToRedisArgs, M: ToRedisArgs>(srckey: K, dstkey: K, member: M) {
565        cmd("SMOVE").arg(srckey).arg(dstkey).arg(member)
566    }
567
568    /// Remove and return a random member from a set.
569    fn spop<K: ToRedisArgs>(key: K) {
570        cmd("SPOP").arg(key)
571    }
572
573    /// Get one random member from a set.
574    fn srandmember<K: ToRedisArgs>(key: K) {
575        cmd("SRANDMEMBER").arg(key)
576    }
577
578    /// Get multiple random members from a set.
579    fn srandmember_multiple<K: ToRedisArgs>(key: K, count: usize) {
580        cmd("SRANDMEMBER").arg(key).arg(count)
581    }
582
583    /// Remove one or more members from a set.
584    fn srem<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
585        cmd("SREM").arg(key).arg(member)
586    }
587
588    /// Add multiple sets.
589    fn sunion<K: ToRedisArgs>(keys: K) {
590        cmd("SUNION").arg(keys)
591    }
592
593    /// Add multiple sets and store the resulting set in a key.
594    fn sunionstore<K: ToRedisArgs>(dstkey: K, keys: K) {
595        cmd("SUNIONSTORE").arg(dstkey).arg(keys)
596    }
597
598    // sorted set commands
599
600    /// Add one member to a sorted set, or update its score if it already exists.
601    fn zadd<K: ToRedisArgs, S: ToRedisArgs, M: ToRedisArgs>(key: K, member: M, score: S) {
602        cmd("ZADD").arg(key).arg(score).arg(member)
603    }
604
605    /// Add multiple members to a sorted set, or update its score if it already exists.
606    fn zadd_multiple<K: ToRedisArgs, S: ToRedisArgs, M: ToRedisArgs>(key: K, items: &[(S, M)]) {
607        cmd("ZADD").arg(key).arg(items)
608    }
609
610    /// Get the number of members in a sorted set.
611    fn zcard<K: ToRedisArgs>(key: K) {
612        cmd("ZCARD").arg(key)
613    }
614
615    /// Count the members in a sorted set with scores within the given values.
616    fn zcount<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
617        cmd("ZCOUNT").arg(key).arg(min).arg(max)
618    }
619
620    /// Increments the member in a sorted set at key by delta.
621    /// If the member does not exist, it is added with delta as its score.
622    fn zincr<K: ToRedisArgs, M: ToRedisArgs, D: ToRedisArgs>(key: K, member: M, delta: D) {
623        cmd("ZINCRBY").arg(key).arg(delta).arg(member)
624    }
625
626    /// Intersect multiple sorted sets and store the resulting sorted set in
627    /// a new key using SUM as aggregation function.
628    fn zinterstore<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
629        cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys)
630    }
631
632    /// Intersect multiple sorted sets and store the resulting sorted set in
633    /// a new key using MIN as aggregation function.
634    fn zinterstore_min<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
635        cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
636    }
637
638    /// Intersect multiple sorted sets and store the resulting sorted set in
639    /// a new key using MAX as aggregation function.
640    fn zinterstore_max<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
641        cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MAX")
642    }
643
644    /// Count the number of members in a sorted set between a given lexicographical range.
645    fn zlexcount<K: ToRedisArgs, L: ToRedisArgs>(key: K, min: L, max: L) {
646        cmd("ZLEXCOUNT").arg(key).arg(min).arg(max)
647    }
648
649    /// Return a range of members in a sorted set, by index
650    fn zrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
651        cmd("ZRANGE").arg(key).arg(start).arg(stop)
652    }
653
654    /// Return a range of members in a sorted set, by index with scores.
655    fn zrange_withscores<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
656        cmd("ZRANGE").arg(key).arg(start).arg(stop).arg("WITHSCORES")
657    }
658
659    /// Return a range of members in a sorted set, by lexicographical range.
660    fn zrangebylex<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
661        cmd("ZRANGEBYLEX").arg(key).arg(min).arg(max)
662    }
663
664    /// Return a range of members in a sorted set, by lexicographical
665    /// range with offset and limit.
666    fn zrangebylex_limit<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(
667            key: K, min: M, max: MM, offset: isize, count: isize) {
668        cmd("ZRANGEBYLEX").arg(key).arg(min).arg(max).arg("LIMIT").arg(offset).arg(count)
669    }
670
671    /// Return a range of members in a sorted set, by lexicographical range.
672    fn zrevrangebylex<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
673        cmd("ZREVRANGEBYLEX").arg(key).arg(max).arg(min)
674    }
675
676    /// Return a range of members in a sorted set, by lexicographical
677    /// range with offset and limit.
678    fn zrevrangebylex_limit<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(
679            key: K, max: MM, min: M, offset: isize, count: isize) {
680        cmd("ZREVRANGEBYLEX").arg(key).arg(max).arg(min).arg("LIMIT").arg(offset).arg(count)
681    }
682
683    /// Return a range of members in a sorted set, by score.
684    fn zrangebyscore<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
685        cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max)
686    }
687
688    /// Return a range of members in a sorted set, by score with scores.
689    fn zrangebyscore_withscores<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
690        cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("WITHSCORES")
691    }
692
693    /// Return a range of members in a sorted set, by score with limit.
694    fn zrangebyscore_limit<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>
695            (key: K, min: M, max: MM, offset: isize, count: isize) {
696        cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("LIMIT").arg(offset).arg(count)
697    }
698
699    /// Return a range of members in a sorted set, by score with limit with scores.
700    fn zrangebyscore_limit_withscores<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>
701            (key: K, min: M, max: MM, offset: isize, count: isize) {
702        cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("WITHSCORES")
703            .arg("LIMIT").arg(offset).arg(count)
704    }
705
706    /// Determine the index of a member in a sorted set.
707    fn zrank<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
708        cmd("ZRANK").arg(key).arg(member)
709    }
710
711    /// Remove one or more members from a sorted set.
712    fn zrem<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
713        cmd("ZREM").arg(key).arg(members)
714    }
715
716    /// Remove all members in a sorted set between the given lexicographical range.
717    fn zrembylex<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
718        cmd("ZREMBYLEX").arg(key).arg(min).arg(max)
719    }
720
721    /// Remove all members in a sorted set within the given indexes.
722    fn zrembyrank<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
723        cmd("ZREMBYRANK").arg(key).arg(start).arg(stop)
724    }
725
726    /// Remove all members in a sorted set within the given scores.
727    fn zrembyscore<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
728        cmd("ZREMRANGEBYSCORE").arg(key).arg(min).arg(max)
729    }
730
731    /// Return a range of members in a sorted set, by index, with scores
732    /// ordered from high to low.
733    fn zrevrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
734        cmd("ZREVRANGE").arg(key).arg(start).arg(stop)
735    }
736
737    /// Return a range of members in a sorted set, by index, with scores
738    /// ordered from high to low.
739    fn zrevrange_withscores<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
740        cmd("ZREVRANGE").arg(key).arg(start).arg(stop).arg("WITHSCORES")
741    }
742
743    /// Return a range of members in a sorted set, by score.
744    fn zrevrangebyscore<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
745        cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min)
746    }
747
748    /// Return a range of members in a sorted set, by score with scores.
749    fn zrevrangebyscore_withscores<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
750        cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("WITHSCORES")
751    }
752
753    /// Return a range of members in a sorted set, by score with limit.
754    fn zrevrangebyscore_limit<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>
755            (key: K, max: MM, min: M, offset: isize, count: isize) {
756        cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("LIMIT").arg(offset).arg(count)
757    }
758
759    /// Return a range of members in a sorted set, by score with limit with scores.
760    fn zrevrangebyscore_limit_withscores<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>
761            (key: K, max: MM, min: M, offset: isize, count: isize) {
762        cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("WITHSCORES")
763            .arg("LIMIT").arg(offset).arg(count)
764    }
765
766    /// Determine the index of a member in a sorted set, with scores ordered from high to low.
767    fn zrevrank<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
768        cmd("ZREVRANK").arg(key).arg(member)
769    }
770
771    /// Get the score associated with the given member in a sorted set.
772    fn zscore<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
773        cmd("ZSCORE").arg(key).arg(member)
774    }
775
776    /// Unions multiple sorted sets and store the resulting sorted set in
777    /// a new key using SUM as aggregation function.
778    fn zunionstore<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
779        cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys)
780    }
781
782    /// Unions multiple sorted sets and store the resulting sorted set in
783    /// a new key using MIN as aggregation function.
784    fn zunionstore_min<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
785        cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
786    }
787
788    /// Unions multiple sorted sets and store the resulting sorted set in
789    /// a new key using MAX as aggregation function.
790    fn zunionstore_max<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
791        cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MAX")
792    }
793
794    // hyperloglog commands
795
796    /// Adds the specified elements to the specified HyperLogLog.
797    fn pfadd<K: ToRedisArgs, E: ToRedisArgs>(key: K, element: E) {
798        cmd("PFADD").arg(key).arg(element)
799    }
800
801    /// Return the approximated cardinality of the set(s) observed by the
802    /// HyperLogLog at key(s).
803    fn pfcount<K: ToRedisArgs>(key: K) {
804        cmd("PFCOUNT").arg(key)
805    }
806
807    /// Merge N different HyperLogLogs into a single one.
808    fn pfmerge<K: ToRedisArgs>(dstkey: K, srckeys: K) {
809        cmd("PFMERGE").arg(dstkey).arg(srckeys)
810    }
811
812    /// Posts a message to the given channel.
813    fn publish<K: ToRedisArgs, E: ToRedisArgs>(channel: K, message: E) {
814        cmd("PUBLISH").arg(channel).arg(message)
815    }
816
817    // geospatial commands
818
819    /// Adds the specified geospatial items to the specified key.
820    ///
821    /// Every member has to be written as a tuple of `(longitude, latitude,
822    /// member_name)`. It can be a single tuple, or a vector of tuples.
823    ///
824    /// `longitude, latitude` can be set using [`redis::geo::Coord`][1].
825    ///
826    /// [1]: ./geo/struct.Coord.html
827    ///
828    /// Returns the number of elements added to the sorted set, not including
829    /// elements already existing for which the score was updated.
830    ///
831    /// # Example
832    ///
833    /// ```rust,no_run
834    /// use redis::{Commands, Connection, RedisFuture};
835    /// use redis::geo::Coord;
836    ///
837    /// fn add_point(con: &mut Connection) -> RedisFuture<isize> {
838    ///     con.geo_add("my_gis", (Coord::lon_lat(13.361389, 38.115556), "Palermo"))
839    /// }
840    ///
841    /// fn add_point_with_tuples(con: &mut Connection) -> RedisFuture<isize> {
842    ///     con.geo_add("my_gis", ("13.361389", "38.115556", "Palermo"))
843    /// }
844    ///
845    /// fn add_many_points(con: &mut Connection) -> RedisFuture<isize> {
846    ///     con.geo_add("my_gis", &[
847    ///         ("13.361389", "38.115556", "Palermo"),
848    ///         ("15.087269", "37.502669", "Catania")
849    ///     ])
850    /// }
851    /// ```
852    #[cfg(feature = "geospatial")]
853    fn geo_add<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
854        cmd("GEOADD").arg(key).arg(members)
855    }
856
857    /// Return the distance between two members in the geospatial index
858    /// represented by the sorted set.
859    ///
860    /// If one or both the members are missing, the command returns NULL, so
861    /// it may be convenient to parse its response as either `Option<f64>` or
862    /// `Option<String>`.
863    ///
864    /// # Example
865    ///
866    /// ```rust,no_run
867    /// use redis::{Commands, RedisFuture};
868    /// use redis::geo::Unit;
869    ///
870    /// fn get_dists(con: &mut redis::Connection) {
871    ///     let x: RedisFuture<f64> = con.geo_dist(
872    ///         "my_gis",
873    ///         "Palermo",
874    ///         "Catania",
875    ///         Unit::Kilometers
876    ///     );
877    ///     // x is Ok(166.2742)
878    ///
879    ///     let x: RedisFuture<Option<f64>> = con.geo_dist(
880    ///         "my_gis",
881    ///         "Palermo",
882    ///         "Atlantis",
883    ///         Unit::Meters
884    ///     );
885    ///     // x is Ok(None)
886    /// }
887    /// ```
888    #[cfg(feature = "geospatial")]
889    fn geo_dist<K: ToRedisArgs, M1: ToRedisArgs, M2: ToRedisArgs>(
890        key: K,
891        member1: M1,
892        member2: M2,
893        unit: geo::Unit
894    ) {
895        cmd("GEODIST")
896            .arg(key)
897            .arg(member1)
898            .arg(member2)
899            .arg(unit)
900    }
901
902    /// Return valid [Geohash][1] strings representing the position of one or
903    /// more members of the geospatial index represented by the sorted set at
904    /// key.
905    ///
906    /// [1]: https://en.wikipedia.org/wiki/Geohash
907    ///
908    /// # Example
909    ///
910    /// ```rust,no_run
911    /// use redis::{Commands, RedisFuture};
912    ///
913    /// fn get_hash(con: &mut redis::Connection) {
914    ///     let x: RedisFuture<Vec<String>> = con.geo_hash("my_gis", "Palermo");
915    ///     // x is vec!["sqc8b49rny0"]
916    ///
917    ///     let x: RedisFuture<Vec<String>> = con.geo_hash("my_gis", &["Palermo", "Catania"]);
918    ///     // x is vec!["sqc8b49rny0", "sqdtr74hyu0"]
919    /// }
920    /// ```
921    #[cfg(feature = "geospatial")]
922    fn geo_hash<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
923        cmd("GEOHASH").arg(key).arg(members)
924    }
925
926    /// Return the positions of all the specified members of the geospatial
927    /// index represented by the sorted set at key.
928    ///
929    /// Every position is a pair of `(longitude, latitude)`. [`redis::geo::Coord`][1]
930    /// can be used to convert these value in a struct.
931    ///
932    /// [1]: ./geo/struct.Coord.html
933    ///
934    /// # Example
935    ///
936    /// ```rust,no_run
937    /// use redis::{Commands, RedisFuture};
938    /// use redis::geo::Coord;
939    ///
940    /// fn get_position(con: &mut redis::Connection) {
941    ///     let x: RedisFuture<Vec<Vec<f64>>> = con.geo_pos("my_gis", &["Palermo", "Catania"]);
942    ///     // x is [ [ 13.361389, 38.115556 ], [ 15.087269, 37.502669 ] ];
943    ///
944    ///     let x: Vec<Coord<f64>> = con.geo_pos("my_gis", "Palermo").unwrap();
945    ///     // x[0].longitude is 13.361389
946    ///     // x[0].latitude is 38.115556
947    /// }
948    /// ```
949    #[cfg(feature = "geospatial")]
950    fn geo_pos<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
951        cmd("GEOPOS").arg(key).arg(members)
952    }
953
954    /// Return the members of a sorted set populated with geospatial information
955    /// using [`geo_add`](#method.geo_add), which are within the borders of the area
956    /// specified with the center location and the maximum distance from the center
957    /// (the radius).
958    ///
959    /// Every item in the result can be read with [`redis::geo::RadiusSearchResult`][1],
960    /// which support the multiple formats returned by `GEORADIUS`.
961    ///
962    /// [1]: ./geo/struct.RadiusSearchResult.html
963    ///
964    /// ```rust,no_run
965    /// use redis::{Commands, RedisFuture};
966    /// use redis::geo::{RadiusOptions, RadiusSearchResult, RadiusOrder, Unit};
967    ///
968    /// fn radius(con: &mut redis::Connection) -> Vec<RadiusSearchResult> {
969    ///     let opts = RadiusOptions::default().with_dist().order(RadiusOrder::Asc);
970    ///     con.geo_radius("my_gis", 15.90, 37.21, 51.39, Unit::Kilometers, opts).unwrap()
971    /// }
972    /// ```
973    #[cfg(feature = "geospatial")]
974    fn geo_radius<K: ToRedisArgs>(
975        key: K,
976        longitude: f64,
977        latitude: f64,
978        radius: f64,
979        unit: geo::Unit,
980        options: geo::RadiusOptions
981    ) {
982        cmd("GEORADIUS")
983            .arg(key)
984            .arg(longitude)
985            .arg(latitude)
986            .arg(radius)
987            .arg(unit)
988            .arg(options)
989    }
990
991    /// Retrieve members selected by distance with the center of `member`. The
992    /// member itself is always contained in the results.
993    #[cfg(feature = "geospatial")]
994    fn geo_radius_by_member<K: ToRedisArgs, M: ToRedisArgs>(
995        key: K,
996        member: M,
997        radius: f64,
998        unit: geo::Unit,
999        options: geo::RadiusOptions
1000    ) {
1001        cmd("GEORADIUSBYMEMBER")
1002            .arg(key)
1003            .arg(member)
1004            .arg(radius)
1005            .arg(unit)
1006            .arg(options)
1007    }
1008
1009}