#![cfg_attr(rustfmt, rustfmt_skip)]
use crate::types::{FromRedisValue, ToRedisArgs, RedisResult, RedisFuture, NumericBehavior};
use crate::connection::{ConnectionLike, Msg, Connection};
use crate::cmd::{cmd, Cmd, Pipeline, Iter};
#[cfg(feature = "geospatial")]
use crate::geo;
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]
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])*
pub fn $name<$lifetime, $($tyargs: $ty),*>($($argname: $argty),*) -> Self {
::std::mem::replace($body, Cmd::new())
}
)*
}
pub trait AsyncCommands : crate::aio::ConnectionLike + Send + Sized {
$(
$(#[$attr])*
#[inline]
fn $name<$lifetime, $($tyargs: $ty + Send + Sync + $lifetime,)* RV>(
& $lifetime mut self
$(, $argname: $argty)*
) -> RedisFuture<'a, RV>
where RV: FromRedisValue,
{
Box::pin(async move { ($body).query_async(self).await })
}
)*
}
impl Pipeline {
$(
$(#[$attr])*
#[inline]
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 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 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 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 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("ZREMBYLEX").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 = "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)
}
}
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 {}
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),
}
};
}
}