#![cfg_attr(rustfmt, rustfmt_skip)]
use crate::cmd::{cmd, Cmd, Iter};
use crate::connection::{Connection, ConnectionLike, Msg};
use crate::pipeline::Pipeline;
use crate::types::{FromRedisValue, NumericBehavior, RedisResult, ToRedisArgs, RedisWrite};
#[cfg(feature = "cluster")]
use crate::cluster_pipeline::ClusterPipeline;
#[cfg(feature = "geospatial")]
use crate::geo;
#[cfg(feature = "streams")]
use crate::streams;
#[cfg(feature = "acl")]
use crate::acl;
macro_rules! implement_commands {
(
$lifetime: lifetime
$(
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) $body:block
)*
) =>
(
/// Implements common redis commands for connection like objects. This
/// allows you to send commands straight to a connection or client. It
/// is also implemented for redis results of clients which makes for
/// very convenient access in some basic cases.
///
/// This allows you to use nicer syntax for some common operations.
/// For instance this code:
///
/// ```rust,no_run
/// # fn do_something() -> redis::RedisResult<()> {
pub trait Commands : ConnectionLike+Sized {
$(
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
fn $name<$lifetime, $($tyargs: $ty, )* RV: FromRedisValue>(
&mut self $(, $argname: $argty)*) -> RedisResult<RV>
{ Cmd::$name($($argname),*).query(self) }
)*
#[inline]
fn scan<RV: FromRedisValue>(&mut self) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("SCAN");
c.cursor_arg(0);
c.iter(self)
}
#[inline]
fn scan_match<P: ToRedisArgs, RV: FromRedisValue>(&mut self, pattern: P) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("SCAN");
c.cursor_arg(0).arg("MATCH").arg(pattern);
c.iter(self)
}
#[inline]
fn hscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("HSCAN");
c.arg(key).cursor_arg(0);
c.iter(self)
}
#[inline]
fn hscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&mut self, key: K, pattern: P) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("HSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
c.iter(self)
}
#[inline]
fn sscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("SSCAN");
c.arg(key).cursor_arg(0);
c.iter(self)
}
#[inline]
fn sscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&mut self, key: K, pattern: P) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("SSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
c.iter(self)
}
#[inline]
fn zscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("ZSCAN");
c.arg(key).cursor_arg(0);
c.iter(self)
}
#[inline]
fn zscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&mut self, key: K, pattern: P) -> RedisResult<Iter<'_, RV>> {
let mut c = cmd("ZSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
c.iter(self)
}
}
impl Cmd {
$(
$(#[$attr])*
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
pub fn $name<$lifetime, $($tyargs: $ty),*>($($argname: $argty),*) -> Self {
::std::mem::replace($body, Cmd::new())
}
)*
}
#[cfg(feature = "aio")]
pub trait AsyncCommands : crate::aio::ConnectionLike + Send + Sized {
$(
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
fn $name<$lifetime, $($tyargs: $ty + Send + Sync + $lifetime,)* RV>(
& $lifetime mut self
$(, $argname: $argty)*
) -> crate::types::RedisFuture<'a, RV>
where
RV: FromRedisValue,
{
Box::pin(async move { ($body).query_async(self).await })
}
)*
#[inline]
fn scan<RV: FromRedisValue>(&mut self) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("SCAN");
c.cursor_arg(0);
Box::pin(async move { c.iter_async(self).await })
}
#[inline]
fn scan_match<P: ToRedisArgs, RV: FromRedisValue>(&mut self, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("SCAN");
c.cursor_arg(0).arg("MATCH").arg(pattern);
Box::pin(async move { c.iter_async(self).await })
}
#[inline]
fn hscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("HSCAN");
c.arg(key).cursor_arg(0);
Box::pin(async move {c.iter_async(self).await })
}
#[inline]
fn hscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&mut self, key: K, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("HSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
Box::pin(async move {c.iter_async(self).await })
}
#[inline]
fn sscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("SSCAN");
c.arg(key).cursor_arg(0);
Box::pin(async move {c.iter_async(self).await })
}
#[inline]
fn sscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&mut self, key: K, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("SSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
Box::pin(async move {c.iter_async(self).await })
}
#[inline]
fn zscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("ZSCAN");
c.arg(key).cursor_arg(0);
Box::pin(async move {c.iter_async(self).await })
}
#[inline]
fn zscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&mut self, key: K, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
let mut c = cmd("ZSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
Box::pin(async move {c.iter_async(self).await })
}
}
impl Pipeline {
$(
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
pub fn $name<$lifetime, $($tyargs: $ty),*>(
&mut self $(, $argname: $argty)*
) -> &mut Self {
self.add_command(::std::mem::replace($body, Cmd::new()))
}
)*
}
#[cfg(feature = "cluster")]
impl ClusterPipeline {
$(
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
pub fn $name<$lifetime, $($tyargs: $ty),*>(
&mut self $(, $argname: $argty)*
) -> &mut Self {
self.add_command(::std::mem::replace($body, Cmd::new()))
}
)*
}
)
}
implement_commands! {
'a
fn get<K: ToRedisArgs>(key: K) {
cmd(if key.is_single_arg() { "GET" } else { "MGET" }).arg(key)
}
fn keys<K: ToRedisArgs>(key: K) {
cmd("KEYS").arg(key)
}
fn set<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("SET").arg(key).arg(value)
}
fn set_multiple<K: ToRedisArgs, V: ToRedisArgs>(items: &'a [(K, V)]) {
cmd("MSET").arg(items)
}
fn set_ex<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V, seconds: usize) {
cmd("SETEX").arg(key).arg(seconds).arg(value)
}
fn pset_ex<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V, milliseconds: usize) {
cmd("PSETEX").arg(key).arg(milliseconds).arg(value)
}
fn set_nx<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("SETNX").arg(key).arg(value)
}
fn mset_nx<K: ToRedisArgs, V: ToRedisArgs>(items: &'a [(K, V)]) {
cmd("MSETNX").arg(items)
}
fn getset<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("GETSET").arg(key).arg(value)
}
fn getrange<K: ToRedisArgs>(key: K, from: isize, to: isize) {
cmd("GETRANGE").arg(key).arg(from).arg(to)
}
fn setrange<K: ToRedisArgs, V: ToRedisArgs>(key: K, offset: isize, value: V) {
cmd("SETRANGE").arg(key).arg(offset).arg(value)
}
fn del<K: ToRedisArgs>(key: K) {
cmd("DEL").arg(key)
}
fn exists<K: ToRedisArgs>(key: K) {
cmd("EXISTS").arg(key)
}
fn expire<K: ToRedisArgs>(key: K, seconds: usize) {
cmd("EXPIRE").arg(key).arg(seconds)
}
fn expire_at<K: ToRedisArgs>(key: K, ts: usize) {
cmd("EXPIREAT").arg(key).arg(ts)
}
fn pexpire<K: ToRedisArgs>(key: K, ms: usize) {
cmd("PEXPIRE").arg(key).arg(ms)
}
fn pexpire_at<K: ToRedisArgs>(key: K, ts: usize) {
cmd("PEXPIREAT").arg(key).arg(ts)
}
fn persist<K: ToRedisArgs>(key: K) {
cmd("PERSIST").arg(key)
}
fn ttl<K: ToRedisArgs>(key: K) {
cmd("TTL").arg(key)
}
fn pttl<K: ToRedisArgs>(key: K) {
cmd("PTTL").arg(key)
}
fn rename<K: ToRedisArgs>(key: K, new_key: K) {
cmd("RENAME").arg(key).arg(new_key)
}
fn rename_nx<K: ToRedisArgs>(key: K, new_key: K) {
cmd("RENAMENX").arg(key).arg(new_key)
}
fn unlink<K: ToRedisArgs>(key: K) {
cmd("UNLINK").arg(key)
}
fn append<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("APPEND").arg(key).arg(value)
}
fn incr<K: ToRedisArgs, V: ToRedisArgs>(key: K, delta: V) {
cmd(if delta.describe_numeric_behavior() == NumericBehavior::NumberIsFloat {
"INCRBYFLOAT"
} else {
"INCRBY"
}).arg(key).arg(delta)
}
fn decr<K: ToRedisArgs, V: ToRedisArgs>(key: K, delta: V) {
cmd("DECRBY").arg(key).arg(delta)
}
fn setbit<K: ToRedisArgs>(key: K, offset: usize, value: bool) {
cmd("SETBIT").arg(key).arg(offset).arg(if value {1} else {0})
}
fn getbit<K: ToRedisArgs>(key: K, offset: usize) {
cmd("GETBIT").arg(key).arg(offset)
}
fn bitcount<K: ToRedisArgs>(key: K) {
cmd("BITCOUNT").arg(key)
}
fn bitcount_range<K: ToRedisArgs>(key: K, start: usize, end: usize) {
cmd("BITCOUNT").arg(key).arg(start).arg(end)
}
fn bit_and<K: ToRedisArgs>(dstkey: K, srckeys: K) {
cmd("BITOP").arg("AND").arg(dstkey).arg(srckeys)
}
fn bit_or<K: ToRedisArgs>(dstkey: K, srckeys: K) {
cmd("BITOP").arg("OR").arg(dstkey).arg(srckeys)
}
fn bit_xor<K: ToRedisArgs>(dstkey: K, srckeys: K) {
cmd("BITOP").arg("XOR").arg(dstkey).arg(srckeys)
}
fn bit_not<K: ToRedisArgs>(dstkey: K, srckey: K) {
cmd("BITOP").arg("NOT").arg(dstkey).arg(srckey)
}
fn strlen<K: ToRedisArgs>(key: K) {
cmd("STRLEN").arg(key)
}
fn hget<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
cmd(if field.is_single_arg() { "HGET" } else { "HMGET" }).arg(key).arg(field)
}
fn hdel<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
cmd("HDEL").arg(key).arg(field)
}
fn hset<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, field: F, value: V) {
cmd("HSET").arg(key).arg(field).arg(value)
}
fn hset_nx<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, field: F, value: V) {
cmd("HSETNX").arg(key).arg(field).arg(value)
}
fn hset_multiple<K: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(key: K, items: &'a [(F, V)]) {
cmd("HMSET").arg(key).arg(items)
}
fn hincr<K: ToRedisArgs, F: ToRedisArgs, D: ToRedisArgs>(key: K, field: F, delta: D) {
cmd(if delta.describe_numeric_behavior() == NumericBehavior::NumberIsFloat {
"HINCRBYFLOAT"
} else {
"HINCRBY"
}).arg(key).arg(field).arg(delta)
}
fn hexists<K: ToRedisArgs, F: ToRedisArgs>(key: K, field: F) {
cmd("HEXISTS").arg(key).arg(field)
}
fn hkeys<K: ToRedisArgs>(key: K) {
cmd("HKEYS").arg(key)
}
fn hvals<K: ToRedisArgs>(key: K) {
cmd("HVALS").arg(key)
}
fn hgetall<K: ToRedisArgs>(key: K) {
cmd("HGETALL").arg(key)
}
fn hlen<K: ToRedisArgs>(key: K) {
cmd("HLEN").arg(key)
}
fn blpop<K: ToRedisArgs>(key: K, timeout: usize) {
cmd("BLPOP").arg(key).arg(timeout)
}
fn brpop<K: ToRedisArgs>(key: K, timeout: usize) {
cmd("BRPOP").arg(key).arg(timeout)
}
fn brpoplpush<K: ToRedisArgs>(srckey: K, dstkey: K, timeout: usize) {
cmd("BRPOPLPUSH").arg(srckey).arg(dstkey).arg(timeout)
}
fn lindex<K: ToRedisArgs>(key: K, index: isize) {
cmd("LINDEX").arg(key).arg(index)
}
fn linsert_before<K: ToRedisArgs, P: ToRedisArgs, V: ToRedisArgs>(
key: K, pivot: P, value: V) {
cmd("LINSERT").arg(key).arg("BEFORE").arg(pivot).arg(value)
}
fn linsert_after<K: ToRedisArgs, P: ToRedisArgs, V: ToRedisArgs>(
key: K, pivot: P, value: V) {
cmd("LINSERT").arg(key).arg("AFTER").arg(pivot).arg(value)
}
fn llen<K: ToRedisArgs>(key: K) {
cmd("LLEN").arg(key)
}
fn lpop<K: ToRedisArgs>(key: K) {
cmd("LPOP").arg(key)
}
fn lpos<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V, options: LposOptions) {
cmd("LPOS").arg(key).arg(value).arg(options)
}
fn lpush<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("LPUSH").arg(key).arg(value)
}
fn lpush_exists<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("LPUSHX").arg(key).arg(value)
}
fn lrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("LRANGE").arg(key).arg(start).arg(stop)
}
fn lrem<K: ToRedisArgs, V: ToRedisArgs>(key: K, count: isize, value: V) {
cmd("LREM").arg(key).arg(count).arg(value)
}
fn ltrim<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("LTRIM").arg(key).arg(start).arg(stop)
}
fn lset<K: ToRedisArgs, V: ToRedisArgs>(key: K, index: isize, value: V) {
cmd("LSET").arg(key).arg(index).arg(value)
}
fn rpop<K: ToRedisArgs>(key: K) {
cmd("RPOP").arg(key)
}
fn rpoplpush<K: ToRedisArgs>(key: K, dstkey: K) {
cmd("RPOPLPUSH").arg(key).arg(dstkey)
}
fn rpush<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("RPUSH").arg(key).arg(value)
}
fn rpush_exists<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("RPUSHX").arg(key).arg(value)
}
fn sadd<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
cmd("SADD").arg(key).arg(member)
}
fn scard<K: ToRedisArgs>(key: K) {
cmd("SCARD").arg(key)
}
fn sdiff<K: ToRedisArgs>(keys: K) {
cmd("SDIFF").arg(keys)
}
fn sdiffstore<K: ToRedisArgs>(dstkey: K, keys: K) {
cmd("SDIFFSTORE").arg(dstkey).arg(keys)
}
fn sinter<K: ToRedisArgs>(keys: K) {
cmd("SINTER").arg(keys)
}
fn sinterstore<K: ToRedisArgs>(dstkey: K, keys: K) {
cmd("SINTERSTORE").arg(dstkey).arg(keys)
}
fn sismember<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
cmd("SISMEMBER").arg(key).arg(member)
}
fn smembers<K: ToRedisArgs>(key: K) {
cmd("SMEMBERS").arg(key)
}
fn smove<K: ToRedisArgs, M: ToRedisArgs>(srckey: K, dstkey: K, member: M) {
cmd("SMOVE").arg(srckey).arg(dstkey).arg(member)
}
fn spop<K: ToRedisArgs>(key: K) {
cmd("SPOP").arg(key)
}
fn srandmember<K: ToRedisArgs>(key: K) {
cmd("SRANDMEMBER").arg(key)
}
fn srandmember_multiple<K: ToRedisArgs>(key: K, count: usize) {
cmd("SRANDMEMBER").arg(key).arg(count)
}
fn srem<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
cmd("SREM").arg(key).arg(member)
}
fn sunion<K: ToRedisArgs>(keys: K) {
cmd("SUNION").arg(keys)
}
fn sunionstore<K: ToRedisArgs>(dstkey: K, keys: K) {
cmd("SUNIONSTORE").arg(dstkey).arg(keys)
}
fn zadd<K: ToRedisArgs, S: ToRedisArgs, M: ToRedisArgs>(key: K, member: M, score: S) {
cmd("ZADD").arg(key).arg(score).arg(member)
}
fn zadd_multiple<K: ToRedisArgs, S: ToRedisArgs, M: ToRedisArgs>(key: K, items: &'a [(S, M)]) {
cmd("ZADD").arg(key).arg(items)
}
fn zcard<K: ToRedisArgs>(key: K) {
cmd("ZCARD").arg(key)
}
fn zcount<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
cmd("ZCOUNT").arg(key).arg(min).arg(max)
}
fn zincr<K: ToRedisArgs, M: ToRedisArgs, D: ToRedisArgs>(key: K, member: M, delta: D) {
cmd("ZINCRBY").arg(key).arg(delta).arg(member)
}
fn zinterstore<K: ToRedisArgs>(dstkey: K, keys: &'a [K]) {
cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys)
}
fn zinterstore_min<K: ToRedisArgs>(dstkey: K, keys: &'a [K]) {
cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
}
fn zinterstore_max<K: ToRedisArgs>(dstkey: K, keys: &'a [K]) {
cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MAX")
}
fn zlexcount<K: ToRedisArgs, L: ToRedisArgs>(key: K, min: L, max: L) {
cmd("ZLEXCOUNT").arg(key).arg(min).arg(max)
}
fn zpopmax<K: ToRedisArgs>(key: K, count: isize) {
cmd("ZPOPMAX").arg(key).arg(count)
}
fn zpopmin<K: ToRedisArgs>(key: K, count: isize) {
cmd("ZPOPMIN").arg(key).arg(count)
}
fn zrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("ZRANGE").arg(key).arg(start).arg(stop)
}
fn zrange_withscores<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("ZRANGE").arg(key).arg(start).arg(stop).arg("WITHSCORES")
}
fn zrangebylex<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
cmd("ZRANGEBYLEX").arg(key).arg(min).arg(max)
}
fn zrangebylex_limit<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(
key: K, min: M, max: MM, offset: isize, count: isize) {
cmd("ZRANGEBYLEX").arg(key).arg(min).arg(max).arg("LIMIT").arg(offset).arg(count)
}
fn zrevrangebylex<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
cmd("ZREVRANGEBYLEX").arg(key).arg(max).arg(min)
}
fn zrevrangebylex_limit<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(
key: K, max: MM, min: M, offset: isize, count: isize) {
cmd("ZREVRANGEBYLEX").arg(key).arg(max).arg(min).arg("LIMIT").arg(offset).arg(count)
}
fn zrangebyscore<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max)
}
fn zrangebyscore_withscores<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("WITHSCORES")
}
fn zrangebyscore_limit<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>
(key: K, min: M, max: MM, offset: isize, count: isize) {
cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("LIMIT").arg(offset).arg(count)
}
fn zrangebyscore_limit_withscores<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>
(key: K, min: M, max: MM, offset: isize, count: isize) {
cmd("ZRANGEBYSCORE").arg(key).arg(min).arg(max).arg("WITHSCORES")
.arg("LIMIT").arg(offset).arg(count)
}
fn zrank<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
cmd("ZRANK").arg(key).arg(member)
}
fn zrem<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
cmd("ZREM").arg(key).arg(members)
}
fn zrembylex<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
cmd("ZREMRANGEBYLEX").arg(key).arg(min).arg(max)
}
fn zremrangebyrank<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("ZREMRANGEBYRANK").arg(key).arg(start).arg(stop)
}
fn zrembyscore<K: ToRedisArgs, M: ToRedisArgs, MM: ToRedisArgs>(key: K, min: M, max: MM) {
cmd("ZREMRANGEBYSCORE").arg(key).arg(min).arg(max)
}
fn zrevrange<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("ZREVRANGE").arg(key).arg(start).arg(stop)
}
fn zrevrange_withscores<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("ZREVRANGE").arg(key).arg(start).arg(stop).arg("WITHSCORES")
}
fn zrevrangebyscore<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min)
}
fn zrevrangebyscore_withscores<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>(key: K, max: MM, min: M) {
cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("WITHSCORES")
}
fn zrevrangebyscore_limit<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>
(key: K, max: MM, min: M, offset: isize, count: isize) {
cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("LIMIT").arg(offset).arg(count)
}
fn zrevrangebyscore_limit_withscores<K: ToRedisArgs, MM: ToRedisArgs, M: ToRedisArgs>
(key: K, max: MM, min: M, offset: isize, count: isize) {
cmd("ZREVRANGEBYSCORE").arg(key).arg(max).arg(min).arg("WITHSCORES")
.arg("LIMIT").arg(offset).arg(count)
}
fn zrevrank<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
cmd("ZREVRANK").arg(key).arg(member)
}
fn zscore<K: ToRedisArgs, M: ToRedisArgs>(key: K, member: M) {
cmd("ZSCORE").arg(key).arg(member)
}
fn zunionstore<K: ToRedisArgs>(dstkey: K, keys: &'a [K]) {
cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys)
}
fn zunionstore_min<K: ToRedisArgs>(dstkey: K, keys: &'a [K]) {
cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
}
fn zunionstore_max<K: ToRedisArgs>(dstkey: K, keys: &'a [K]) {
cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MAX")
}
fn pfadd<K: ToRedisArgs, E: ToRedisArgs>(key: K, element: E) {
cmd("PFADD").arg(key).arg(element)
}
fn pfcount<K: ToRedisArgs>(key: K) {
cmd("PFCOUNT").arg(key)
}
fn pfmerge<K: ToRedisArgs>(dstkey: K, srckeys: K) {
cmd("PFMERGE").arg(dstkey).arg(srckeys)
}
fn publish<K: ToRedisArgs, E: ToRedisArgs>(channel: K, message: E) {
cmd("PUBLISH").arg(channel).arg(message)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_load<>() {
cmd("ACL").arg("LOAD")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_save<>() {
cmd("ACL").arg("SAVE")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_list<>() {
cmd("ACL").arg("LIST")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_users<>() {
cmd("ACL").arg("USERS")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_getuser<K: ToRedisArgs>(username: K) {
cmd("ACL").arg("GETUSER").arg(username)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_setuser<K: ToRedisArgs>(username: K) {
cmd("ACL").arg("SETUSER").arg(username)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_setuser_rules<K: ToRedisArgs>(username: K, rules: &'a [acl::Rule]) {
cmd("ACL").arg("SETUSER").arg(username).arg(rules)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_deluser<K: ToRedisArgs>(usernames: &'a [K]) {
cmd("ACL").arg("DELUSER").arg(usernames)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_cat<>() {
cmd("ACL").arg("CAT")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_cat_categoryname<K: ToRedisArgs>(categoryname: K) {
cmd("ACL").arg("CAT").arg(categoryname)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_genpass<>() {
cmd("ACL").arg("GENPASS")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_genpass_bits<>(bits: isize) {
cmd("ACL").arg("GENPASS").arg(bits)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_whoami<>() {
cmd("ACL").arg("WHOAMI")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_log<>(count: isize) {
cmd("ACL").arg("LOG").arg(count)
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_log_reset<>() {
cmd("ACL").arg("LOG").arg("RESET")
}
#[cfg(feature = "acl")]
#[cfg_attr(docsrs, doc(cfg(feature = "acl")))]
fn acl_help<>() {
cmd("ACL").arg("HELP")
}
#[cfg(feature = "geospatial")]
#[cfg_attr(docsrs, doc(cfg(feature = "geospatial")))]
fn geo_add<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
cmd("GEOADD").arg(key).arg(members)
}
#[cfg(feature = "geospatial")]
#[cfg_attr(docsrs, doc(cfg(feature = "geospatial")))]
fn geo_dist<K: ToRedisArgs, M1: ToRedisArgs, M2: ToRedisArgs>(
key: K,
member1: M1,
member2: M2,
unit: geo::Unit
) {
cmd("GEODIST")
.arg(key)
.arg(member1)
.arg(member2)
.arg(unit)
}
#[cfg(feature = "geospatial")]
#[cfg_attr(docsrs, doc(cfg(feature = "geospatial")))]
fn geo_hash<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
cmd("GEOHASH").arg(key).arg(members)
}
#[cfg(feature = "geospatial")]
#[cfg_attr(docsrs, doc(cfg(feature = "geospatial")))]
fn geo_pos<K: ToRedisArgs, M: ToRedisArgs>(key: K, members: M) {
cmd("GEOPOS").arg(key).arg(members)
}
#[cfg(feature = "geospatial")]
#[cfg_attr(docsrs, doc(cfg(feature = "geospatial")))]
fn geo_radius<K: ToRedisArgs>(
key: K,
longitude: f64,
latitude: f64,
radius: f64,
unit: geo::Unit,
options: geo::RadiusOptions
) {
cmd("GEORADIUS")
.arg(key)
.arg(longitude)
.arg(latitude)
.arg(radius)
.arg(unit)
.arg(options)
}
#[cfg(feature = "geospatial")]
#[cfg_attr(docsrs, doc(cfg(feature = "geospatial")))]
fn geo_radius_by_member<K: ToRedisArgs, M: ToRedisArgs>(
key: K,
member: M,
radius: f64,
unit: geo::Unit,
options: geo::RadiusOptions
) {
cmd("GEORADIUSBYMEMBER")
.arg(key)
.arg(member)
.arg(radius)
.arg(unit)
.arg(options)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xack<K: ToRedisArgs, G: ToRedisArgs, I: ToRedisArgs>(
key: K,
group: G,
ids: &'a [I]) {
cmd("XACK")
.arg(key)
.arg(group)
.arg(ids)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xadd<K: ToRedisArgs, ID: ToRedisArgs, F: ToRedisArgs, V: ToRedisArgs>(
key: K,
id: ID,
items: &'a [(F, V)]
) {
cmd("XADD").arg(key).arg(id).arg(items)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xadd_map<K: ToRedisArgs, ID: ToRedisArgs, BTM: ToRedisArgs>(
key: K,
id: ID,
map: BTM
) {
cmd("XADD").arg(key).arg(id).arg(map)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xadd_maxlen<
K: ToRedisArgs,
ID: ToRedisArgs,
F: ToRedisArgs,
V: ToRedisArgs
>(
key: K,
maxlen: streams::StreamMaxlen,
id: ID,
items: &'a [(F, V)]
) {
cmd("XADD")
.arg(key)
.arg(maxlen)
.arg(id)
.arg(items)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xadd_maxlen_map<K: ToRedisArgs, ID: ToRedisArgs, BTM: ToRedisArgs>(
key: K,
maxlen: streams::StreamMaxlen,
id: ID,
map: BTM
) {
cmd("XADD")
.arg(key)
.arg(maxlen)
.arg(id)
.arg(map)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xclaim<K: ToRedisArgs, G: ToRedisArgs, C: ToRedisArgs, MIT: ToRedisArgs, ID: ToRedisArgs>(
key: K,
group: G,
consumer: C,
min_idle_time: MIT,
ids: &'a [ID]
) {
cmd("XCLAIM")
.arg(key)
.arg(group)
.arg(consumer)
.arg(min_idle_time)
.arg(ids)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xclaim_options<
K: ToRedisArgs,
G: ToRedisArgs,
C: ToRedisArgs,
MIT: ToRedisArgs,
ID: ToRedisArgs
>(
key: K,
group: G,
consumer: C,
min_idle_time: MIT,
ids: &'a [ID],
options: streams::StreamClaimOptions
) {
cmd("XCLAIM")
.arg(key)
.arg(group)
.arg(consumer)
.arg(min_idle_time)
.arg(ids)
.arg(options)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xdel<K: ToRedisArgs, ID: ToRedisArgs>(
key: K,
ids: &'a [ID]
) {
cmd("XDEL").arg(key).arg(ids)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xgroup_create<K: ToRedisArgs, G: ToRedisArgs, ID: ToRedisArgs>(
key: K,
group: G,
id: ID
) {
cmd("XGROUP")
.arg("CREATE")
.arg(key)
.arg(group)
.arg(id)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xgroup_create_mkstream<
K: ToRedisArgs,
G: ToRedisArgs,
ID: ToRedisArgs
>(
key: K,
group: G,
id: ID
) {
cmd("XGROUP")
.arg("CREATE")
.arg(key)
.arg(group)
.arg(id)
.arg("MKSTREAM")
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xgroup_setid<K: ToRedisArgs, G: ToRedisArgs, ID: ToRedisArgs>(
key: K,
group: G,
id: ID
) {
cmd("XGROUP")
.arg("SETID")
.arg(key)
.arg(group)
.arg(id)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xgroup_destroy<K: ToRedisArgs, G: ToRedisArgs>(
key: K,
group: G
) {
cmd("XGROUP").arg("DESTROY").arg(key).arg(group)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xgroup_delconsumer<K: ToRedisArgs, G: ToRedisArgs, C: ToRedisArgs>(
key: K,
group: G,
consumer: C
) {
cmd("XGROUP")
.arg("DELCONSUMER")
.arg(key)
.arg(group)
.arg(consumer)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xinfo_consumers<K: ToRedisArgs, G: ToRedisArgs>(
key: K,
group: G
) {
cmd("XINFO")
.arg("CONSUMERS")
.arg(key)
.arg(group)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xinfo_groups<K: ToRedisArgs>(key: K) {
cmd("XINFO").arg("GROUPS").arg(key)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xinfo_stream<K: ToRedisArgs>(key: K) {
cmd("XINFO").arg("STREAM").arg(key)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xlen<K: ToRedisArgs>(key: K) {
cmd("XLEN").arg(key)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xpending<K: ToRedisArgs, G: ToRedisArgs>(
key: K,
group: G
) {
cmd("XPENDING").arg(key).arg(group)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xpending_count<
K: ToRedisArgs,
G: ToRedisArgs,
S: ToRedisArgs,
E: ToRedisArgs,
C: ToRedisArgs
>(
key: K,
group: G,
start: S,
end: E,
count: C
) {
cmd("XPENDING")
.arg(key)
.arg(group)
.arg(start)
.arg(end)
.arg(count)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xpending_consumer_count<
K: ToRedisArgs,
G: ToRedisArgs,
S: ToRedisArgs,
E: ToRedisArgs,
C: ToRedisArgs,
CN: ToRedisArgs
>(
key: K,
group: G,
start: S,
end: E,
count: C,
consumer: CN
) {
cmd("XPENDING")
.arg(key)
.arg(group)
.arg(start)
.arg(end)
.arg(count)
.arg(consumer)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xrange<K: ToRedisArgs, S: ToRedisArgs, E: ToRedisArgs>(
key: K,
start: S,
end: E
) {
cmd("XRANGE").arg(key).arg(start).arg(end)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xrange_all<K: ToRedisArgs>(key: K) {
cmd("XRANGE").arg(key).arg("-").arg("+")
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xrange_count<K: ToRedisArgs, S: ToRedisArgs, E: ToRedisArgs, C: ToRedisArgs>(
key: K,
start: S,
end: E,
count: C
) {
cmd("XRANGE")
.arg(key)
.arg(start)
.arg(end)
.arg("COUNT")
.arg(count)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xread<K: ToRedisArgs, ID: ToRedisArgs>(
keys: &'a [K],
ids: &'a [ID]
) {
cmd("XREAD").arg("STREAMS").arg(keys).arg(ids)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xread_options<K: ToRedisArgs, ID: ToRedisArgs>(
keys: &'a [K],
ids: &'a [ID],
options: streams::StreamReadOptions
) {
cmd(if options.read_only() {
"XREAD"
} else {
"XREADGROUP"
})
.arg(options)
.arg("STREAMS")
.arg(keys)
.arg(ids)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xrevrange<K: ToRedisArgs, E: ToRedisArgs, S: ToRedisArgs>(
key: K,
end: E,
start: S
) {
cmd("XREVRANGE").arg(key).arg(end).arg(start)
}
fn xrevrange_all<K: ToRedisArgs>(key: K) {
cmd("XREVRANGE").arg(key).arg("+").arg("-")
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xrevrange_count<K: ToRedisArgs, E: ToRedisArgs, S: ToRedisArgs, C: ToRedisArgs>(
key: K,
end: E,
start: S,
count: C
) {
cmd("XREVRANGE")
.arg(key)
.arg(end)
.arg(start)
.arg("COUNT")
.arg(count)
}
#[cfg(feature = "streams")]
#[cfg_attr(docsrs, doc(cfg(feature = "streams")))]
fn xtrim<K: ToRedisArgs>(
key: K,
maxlen: streams::StreamMaxlen
) {
cmd("XTRIM").arg(key).arg(maxlen)
}
}
pub enum ControlFlow<U> {
Continue,
Break(U),
}
pub trait PubSubCommands: Sized {
fn subscribe<C, F, U>(&mut self, _: C, _: F) -> RedisResult<U>
where
F: FnMut(Msg) -> ControlFlow<U>,
C: ToRedisArgs;
fn psubscribe<P, F, U>(&mut self, _: P, _: F) -> RedisResult<U>
where
F: FnMut(Msg) -> ControlFlow<U>,
P: ToRedisArgs;
}
impl<T> Commands for T where T: ConnectionLike {}
#[cfg(feature = "aio")]
impl<T> AsyncCommands for T where T: crate::aio::ConnectionLike + Send + Sized {}
impl PubSubCommands for Connection {
fn subscribe<C, F, U>(&mut self, channels: C, mut func: F) -> RedisResult<U>
where
F: FnMut(Msg) -> ControlFlow<U>,
C: ToRedisArgs,
{
let mut pubsub = self.as_pubsub();
pubsub.subscribe(channels)?;
loop {
let msg = pubsub.get_message()?;
match func(msg) {
ControlFlow::Continue => continue,
ControlFlow::Break(value) => return Ok(value),
}
}
}
fn psubscribe<P, F, U>(&mut self, patterns: P, mut func: F) -> RedisResult<U>
where
F: FnMut(Msg) -> ControlFlow<U>,
P: ToRedisArgs,
{
let mut pubsub = self.as_pubsub();
pubsub.psubscribe(patterns)?;
loop {
let msg = pubsub.get_message()?;
match func(msg) {
ControlFlow::Continue => continue,
ControlFlow::Break(value) => return Ok(value),
}
}
}
}
#[derive(Default)]
pub struct LposOptions {
count: Option<usize>,
maxlen: Option<usize>,
rank: Option<isize>,
}
impl LposOptions {
pub fn count(mut self, n: usize) -> Self {
self.count = Some(n);
self
}
pub fn rank(mut self, n: isize) -> Self {
self.rank = Some(n);
self
}
pub fn maxlen(mut self, n: usize) -> Self {
self.maxlen = Some(n);
self
}
}
impl ToRedisArgs for LposOptions {
fn write_redis_args<W>(&self, out: &mut W)
where
W: ?Sized + RedisWrite,
{
if let Some(n) = self.count {
out.write_arg(b"COUNT");
out.write_arg_fmt(n);
}
if let Some(n) = self.rank {
out.write_arg(b"RANK");
out.write_arg_fmt(n);
}
if let Some(n) = self.maxlen {
out.write_arg(b"MAXLEN");
out.write_arg_fmt(n);
}
}
fn is_single_arg(&self) -> bool {
false
}
}