#![cfg_attr(rustfmt, rustfmt_skip)]
use types::{FromRedisValue, ToRedisArgs, RedisResult, NumericBehavior};
use client::Client;
use connection::{Connection, ConnectionLike, Msg};
use cmd::{cmd, Cmd, Pipeline, Iter};
macro_rules! implement_commands {
(
$(
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) $body:block
)*
) =>
(
pub trait Commands : ConnectionLike+Sized {
$(
$(#[$attr])*
#[inline]
fn $name<$($tyargs: $ty,)* RV: FromRedisValue>(
&self $(, $argname: $argty)*) -> RedisResult<RV>
{ ($body).query(self) }
)*
#[inline]
fn scan<RV: FromRedisValue>(&self) -> RedisResult<Iter<RV>> {
cmd("SCAN").cursor_arg(0).iter(self)
}
#[inline]
fn scan_match<P: ToRedisArgs, RV: FromRedisValue>(&self, pattern: P) -> RedisResult<Iter<RV>> {
cmd("SCAN").cursor_arg(0).arg("MATCH").arg(pattern).iter(self)
}
#[inline]
fn hscan<K: ToRedisArgs, RV: FromRedisValue>(&self, key: K) -> RedisResult<Iter<RV>> {
cmd("HSCAN").arg(key).cursor_arg(0).iter(self)
}
#[inline]
fn hscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&self, key: K, pattern: P) -> RedisResult<Iter<RV>> {
cmd("HSCAN").arg(key).cursor_arg(0).arg("MATCH").arg(pattern).iter(self)
}
#[inline]
fn sscan<K: ToRedisArgs, RV: FromRedisValue>(&self, key: K) -> RedisResult<Iter<RV>> {
cmd("SSCAN").arg(key).cursor_arg(0).iter(self)
}
#[inline]
fn sscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&self, key: K, pattern: P) -> RedisResult<Iter<RV>> {
cmd("SSCAN").arg(key).cursor_arg(0).arg("MATCH").arg(pattern).iter(self)
}
#[inline]
fn zscan<K: ToRedisArgs, RV: FromRedisValue>(&self, key: K) -> RedisResult<Iter<RV>> {
cmd("ZSCAN").arg(key).cursor_arg(0).iter(self)
}
#[inline]
fn zscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
(&self, key: K, pattern: P) -> RedisResult<Iter<RV>> {
cmd("ZSCAN").arg(key).cursor_arg(0).arg("MATCH").arg(pattern).iter(self)
}
}
pub trait PipelineCommands {
#[doc(hidden)]
#[inline]
fn perform(&mut self, con: &Cmd) -> &mut Self;
$(
$(#[$attr])*
#[inline]
fn $name<'a $(, $tyargs: $ty)*>(
&mut self $(, $argname: $argty)*) -> &mut Self
{ self.perform($body) }
)*
}
)
}
implement_commands! {
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: &[(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 set_nx<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("SETNX").arg(key).arg(value)
}
fn mset_nx<K: ToRedisArgs, V: ToRedisArgs>(items: &[(K, V)]) {
cmd("MSETNX").arg(items)
}
fn getset<K: ToRedisArgs, V: ToRedisArgs>(key: K, value: V) {
cmd("GETSET").arg(key).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 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: &[(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 sdinterstore<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: &[(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: &[K]) {
cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys)
}
fn zinterstore_min<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
cmd("ZINTERSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
}
fn zinterstore_max<K: ToRedisArgs>(dstkey: K, keys: &[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 zrembyrank<K: ToRedisArgs>(key: K, start: isize, stop: isize) {
cmd("ZREMBYRANK").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: &[K]) {
cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys)
}
fn zunionstore_min<K: ToRedisArgs>(dstkey: K, keys: &[K]) {
cmd("ZUNIONSTORE").arg(dstkey).arg(keys.len()).arg(keys).arg("AGGREGATE").arg("MIN")
}
fn zunionstore_max<K: ToRedisArgs>(dstkey: K, keys: &[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)
}
}
pub enum ControlFlow<U> {
Continue,
Break(U),
}
pub trait PubSubCommands: Sized {
fn subscribe<'a, C, F, U>(&mut self, _: C, _: F) -> RedisResult<U>
where F: FnMut(Msg) -> ControlFlow<U>,
C: ToRedisArgs;
fn psubscribe<'a, P, F, U>(&mut self, _: P, _: F) -> RedisResult<U>
where F: FnMut(Msg) -> ControlFlow<U>,
P: ToRedisArgs;
}
impl Commands for Connection {}
impl Commands for Client {}
impl PubSubCommands for Connection {
fn subscribe<'a, 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<'a, 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),
}
};
}
}
impl PipelineCommands for Pipeline {
fn perform(&mut self, cmd: &Cmd) -> &mut Pipeline {
self.add_command(cmd)
}
}