#[cfg(feature = "aio")]
macro_rules! implement_command_async {
(
$lifetime: lifetime
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) $body:block Generic
) => {
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
fn $name<$lifetime, RV: FromRedisValue, $($tyargs: $ty + Send + Sync + $lifetime,)*>(
& $lifetime mut self
$(, $argname: $argty)*
) -> crate::types::RedisFuture<$lifetime, RV>
{
Box::pin(async move { $body.query_async(self).await })
}
};
(
$lifetime: lifetime
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) $body:block $rettype:ty
) => {
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
fn $name<$lifetime, $($tyargs: $ty + Send + Sync + $lifetime,)*>(
& $lifetime mut self
$(, $argname: $argty)*
) -> crate::types::RedisFuture<$lifetime, $rettype>
{
Box::pin(async move { $body.query_async(self).await })
}
};
}
macro_rules! implement_command_sync {
(
$lifetime: lifetime
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) $body:block Generic
) => {
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
fn $name<$lifetime, RV: FromRedisValue, $($tyargs: $ty + Send + Sync + $lifetime,)*>(
& $lifetime mut self
$(, $argname: $argty)*
) -> RedisResult<RV>
{
Cmd::$name($($argname),*).query(self)
}
};
(
$lifetime: lifetime
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) $body:block $rettype:ty
) => {
$(#[$attr])*
#[inline]
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
fn $name<$lifetime, $($tyargs: $ty + Send + Sync + $lifetime,)*>(
& $lifetime mut self
$(, $argname: $argty)*
) -> RedisResult<$rettype>
{
Cmd::$name($($argname),*).query(self)
}
};
}
macro_rules! implement_iterators {
($iter:expr, $ret:ty) => {
#[inline]
fn scan<RV: FromRedisValue>(&mut self) -> $ret {
let mut c = cmd("SCAN");
c.cursor_arg(0);
$iter(c, self)
}
#[inline]
fn scan_options<RV: FromRedisValue>(&mut self, opts: ScanOptions) -> $ret {
let mut c = cmd("SCAN");
c.cursor_arg(0).arg(opts);
$iter(c, self)
}
#[inline]
fn scan_match<P: ToSingleRedisArg, RV: FromRedisValue>(&mut self, pattern: P) -> $ret {
let mut c = cmd("SCAN");
c.cursor_arg(0).arg("MATCH").arg(pattern);
$iter(c, self)
}
#[inline]
fn hscan<K: ToSingleRedisArg, RV: FromRedisValue>(&mut self, key: K) -> $ret {
let mut c = cmd("HSCAN");
c.arg(key).cursor_arg(0);
$iter(c, self)
}
#[inline]
fn hscan_match<K: ToSingleRedisArg, P: ToSingleRedisArg, RV: FromRedisValue>(
&mut self,
key: K,
pattern: P,
) -> $ret {
let mut c = cmd("HSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
$iter(c, self)
}
#[inline]
fn sscan<K: ToSingleRedisArg, RV: FromRedisValue>(&mut self, key: K) -> $ret {
let mut c = cmd("SSCAN");
c.arg(key).cursor_arg(0);
$iter(c, self)
}
#[inline]
fn sscan_match<K: ToSingleRedisArg, P: ToSingleRedisArg, RV: FromRedisValue>(
&mut self,
key: K,
pattern: P,
) -> $ret {
let mut c = cmd("SSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
$iter(c, self)
}
#[inline]
fn zscan<K: ToSingleRedisArg, RV: FromRedisValue>(&mut self, key: K) -> $ret {
let mut c = cmd("ZSCAN");
c.arg(key).cursor_arg(0);
$iter(c, self)
}
#[inline]
fn zscan_match<K: ToSingleRedisArg, P: ToSingleRedisArg, RV: FromRedisValue>(
&mut self,
key: K,
pattern: P,
) -> $ret {
let mut c = cmd("ZSCAN");
c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
$iter(c, self)
}
};
}
macro_rules! implement_commands {
(
$lifetime: lifetime
$(
$(#[$attr:meta])+
fn $name:ident<$($tyargs:ident : $ty:ident),*>(
$($argname:ident: $argty:ty),*) -> $rettype:tt $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) }
)*
implement_iterators! {
|c: Cmd, this| c.iter(this),
RedisResult<Iter<'_, RV>>
}
}
impl Cmd {
$(
$(#[$attr])*
#[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
pub fn $name<$lifetime, $($tyargs: $ty),*>($($argname: $argty),*) -> Self {
$body
}
)*
}
#[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<$lifetime, RV>
where
RV: FromRedisValue,
{
Box::pin(async move { ($body).query_async(self).await })
}
)*
implement_iterators! {
|c: Cmd, this| Box::pin(async move { c.iter_async(this).await }),
crate::types::RedisFuture<'_, crate::cmd::AsyncIter<'_, RV>>
}
}
pub trait TypedCommands : ConnectionLike+Sized {
$(
implement_command_sync! {
$lifetime
$(#[$attr])*
fn $name<$($tyargs: $ty),*>(
$($argname: $argty),*
)
{
$body
} $rettype
}
)*
implement_iterators! {
|c: Cmd, this| c.iter(this),
RedisResult<Iter<'_, RV>>
}
fn get_int<K: ToSingleRedisArg>(&mut self, key: K) -> RedisResult<Option<isize>> {
cmd("GET").arg(key).query(self)
}
fn mget_ints<K: ToRedisArgs>(&mut self, key: K) -> RedisResult<Vec<Option<isize>>> {
cmd("MGET").arg(key).query(self)
}
}
#[cfg(feature = "aio")]
pub trait AsyncTypedCommands : crate::aio::ConnectionLike + Send + Sized {
$(
implement_command_async! {
$lifetime
$(#[$attr])*
fn $name<$($tyargs: $ty),*>(
$($argname: $argty),*
)
{
$body
} $rettype
}
)*
implement_iterators! {
|c: Cmd, this| Box::pin(async move { c.iter_async(this).await }),
crate::types::RedisFuture<'_, crate::cmd::AsyncIter<'_, RV>>
}
fn get_int<$lifetime, K: ToSingleRedisArg + Send + Sync + $lifetime>(&$lifetime mut self, key: K) -> crate::types::RedisFuture<$lifetime, Option<isize>> {
Box::pin(async move { cmd("GET").arg(key).query_async(self).await })
}
fn mget_ints<$lifetime, K: ToRedisArgs + Send + Sync + $lifetime>(&$lifetime mut self, key: K) -> crate::types::RedisFuture<$lifetime, Vec<Option<isize>>> {
Box::pin(async move { cmd("MGET").arg(key).query_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($body)
}
)*
}
#[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($body)
}
)*
}
);
}