redis/commands/macros.rs
1macro_rules! implement_commands {
2 (
3 $lifetime: lifetime
4 $(
5 $(#[$attr:meta])+
6 fn $name:ident<$($tyargs:ident : $ty:ident),*>(
7 $($argname:ident: $argty:ty),*) $body:block
8 )*
9 ) =>
10 (
11 /// Implements common redis commands for connection like objects.
12 ///
13 /// This allows you to send commands straight to a connection or client.
14 /// It is also implemented for redis results of clients which makes for
15 /// very convenient access in some basic cases.
16 ///
17 /// This allows you to use nicer syntax for some common operations.
18 /// For instance this code:
19 ///
20 /// ```rust,no_run
21 /// # fn do_something() -> redis::RedisResult<()> {
22 /// let client = redis::Client::open("redis://127.0.0.1/")?;
23 /// let mut con = client.get_connection()?;
24 /// redis::cmd("SET").arg("my_key").arg(42).exec(&mut con).unwrap();
25 /// assert_eq!(redis::cmd("GET").arg("my_key").query(&mut con), Ok(42));
26 /// # Ok(()) }
27 /// ```
28 ///
29 /// Will become this:
30 ///
31 /// ```rust,no_run
32 /// # fn do_something() -> redis::RedisResult<()> {
33 /// use redis::Commands;
34 /// let client = redis::Client::open("redis://127.0.0.1/")?;
35 /// let mut con = client.get_connection()?;
36 /// let _: () = con.set("my_key", 42)?;
37 /// assert_eq!(con.get("my_key"), Ok(42));
38 /// # Ok(()) }
39 /// ```
40 pub trait Commands : ConnectionLike+Sized {
41 $(
42 $(#[$attr])*
43 #[inline]
44 #[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
45 fn $name<$lifetime, $($tyargs: $ty, )* RV: FromRedisValue>(
46 &mut self $(, $argname: $argty)*) -> RedisResult<RV>
47 { Cmd::$name($($argname),*).query(self) }
48 )*
49
50 /// Incrementally iterate the keys space.
51 #[inline]
52 fn scan<RV: FromRedisValue>(&mut self) -> RedisResult<Iter<'_, RV>> {
53 let mut c = cmd("SCAN");
54 c.cursor_arg(0);
55 c.iter(self)
56 }
57
58 /// Incrementally iterate the keys space with options.
59 #[inline]
60 fn scan_options<RV: FromRedisValue>(&mut self, opts: ScanOptions) -> RedisResult<Iter<'_, RV>> {
61 let mut c = cmd("SCAN");
62 c.cursor_arg(0).arg(opts);
63 c.iter(self)
64 }
65
66 /// Incrementally iterate the keys space for keys matching a pattern.
67 #[inline]
68 fn scan_match<P: ToRedisArgs, RV: FromRedisValue>(&mut self, pattern: P) -> RedisResult<Iter<'_, RV>> {
69 let mut c = cmd("SCAN");
70 c.cursor_arg(0).arg("MATCH").arg(pattern);
71 c.iter(self)
72 }
73
74 /// Incrementally iterate hash fields and associated values.
75 #[inline]
76 fn hscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> RedisResult<Iter<'_, RV>> {
77 let mut c = cmd("HSCAN");
78 c.arg(key).cursor_arg(0);
79 c.iter(self)
80 }
81
82 /// Incrementally iterate hash fields and associated values for
83 /// field names matching a pattern.
84 #[inline]
85 fn hscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
86 (&mut self, key: K, pattern: P) -> RedisResult<Iter<'_, RV>> {
87 let mut c = cmd("HSCAN");
88 c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
89 c.iter(self)
90 }
91
92 /// Incrementally iterate set elements.
93 #[inline]
94 fn sscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> RedisResult<Iter<'_, RV>> {
95 let mut c = cmd("SSCAN");
96 c.arg(key).cursor_arg(0);
97 c.iter(self)
98 }
99
100 /// Incrementally iterate set elements for elements matching a pattern.
101 #[inline]
102 fn sscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
103 (&mut self, key: K, pattern: P) -> RedisResult<Iter<'_, RV>> {
104 let mut c = cmd("SSCAN");
105 c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
106 c.iter(self)
107 }
108
109 /// Incrementally iterate sorted set elements.
110 #[inline]
111 fn zscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> RedisResult<Iter<'_, RV>> {
112 let mut c = cmd("ZSCAN");
113 c.arg(key).cursor_arg(0);
114 c.iter(self)
115 }
116
117 /// Incrementally iterate sorted set elements for elements matching a pattern.
118 #[inline]
119 fn zscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
120 (&mut self, key: K, pattern: P) -> RedisResult<Iter<'_, RV>> {
121 let mut c = cmd("ZSCAN");
122 c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
123 c.iter(self)
124 }
125 }
126
127 impl Cmd {
128 $(
129 $(#[$attr])*
130 #[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
131 pub fn $name<$lifetime, $($tyargs: $ty),*>($($argname: $argty),*) -> Self {
132 ::std::mem::replace($body, Cmd::new())
133 }
134 )*
135 }
136
137 /// Implements common redis commands over asynchronous connections.
138 ///
139 /// This allows you to send commands straight to a connection or client.
140 ///
141 /// This allows you to use nicer syntax for some common operations.
142 /// For instance this code:
143 ///
144 /// ```rust,no_run
145 /// use redis::AsyncCommands;
146 /// # async fn do_something() -> redis::RedisResult<()> {
147 /// let client = redis::Client::open("redis://127.0.0.1/")?;
148 /// let mut con = client.get_multiplexed_async_connection().await?;
149 /// redis::cmd("SET").arg("my_key").arg(42i32).exec_async(&mut con).await?;
150 /// assert_eq!(redis::cmd("GET").arg("my_key").query_async(&mut con).await, Ok(42i32));
151 /// # Ok(()) }
152 /// ```
153 ///
154 /// Will become this:
155 ///
156 /// ```rust,no_run
157 /// use redis::AsyncCommands;
158 /// # async fn do_something() -> redis::RedisResult<()> {
159 /// use redis::Commands;
160 /// let client = redis::Client::open("redis://127.0.0.1/")?;
161 /// let mut con = client.get_multiplexed_async_connection().await?;
162 /// let _: () = con.set("my_key", 42i32).await?;
163 /// assert_eq!(con.get("my_key").await, Ok(42i32));
164 /// # Ok(()) }
165 /// ```
166 #[cfg(feature = "aio")]
167 pub trait AsyncCommands : crate::aio::ConnectionLike + Send + Sized {
168 $(
169 $(#[$attr])*
170 #[inline]
171 #[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
172 fn $name<$lifetime, $($tyargs: $ty + Send + Sync + $lifetime,)* RV>(
173 & $lifetime mut self
174 $(, $argname: $argty)*
175 ) -> crate::types::RedisFuture<'a, RV>
176 where
177 RV: FromRedisValue,
178 {
179 Box::pin(async move { ($body).query_async(self).await })
180 }
181 )*
182
183 /// Incrementally iterate the keys space.
184 #[inline]
185 fn scan<RV: FromRedisValue>(&mut self) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
186 let mut c = cmd("SCAN");
187 c.cursor_arg(0);
188 Box::pin(async move { c.iter_async(self).await })
189 }
190
191 /// Incrementally iterate the keys space with options.
192 #[inline]
193 fn scan_options<RV: FromRedisValue>(&mut self, opts: ScanOptions) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
194 let mut c = cmd("SCAN");
195 c.cursor_arg(0).arg(opts);
196 Box::pin(async move { c.iter_async(self).await })
197 }
198
199 /// Incrementally iterate set elements for elements matching a pattern.
200 #[inline]
201 fn scan_match<P: ToRedisArgs, RV: FromRedisValue>(&mut self, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
202 let mut c = cmd("SCAN");
203 c.cursor_arg(0).arg("MATCH").arg(pattern);
204 Box::pin(async move { c.iter_async(self).await })
205 }
206
207 /// Incrementally iterate hash fields and associated values.
208 #[inline]
209 fn hscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
210 let mut c = cmd("HSCAN");
211 c.arg(key).cursor_arg(0);
212 Box::pin(async move {c.iter_async(self).await })
213 }
214
215 /// Incrementally iterate hash fields and associated values for
216 /// field names matching a pattern.
217 #[inline]
218 fn hscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
219 (&mut self, key: K, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
220 let mut c = cmd("HSCAN");
221 c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
222 Box::pin(async move {c.iter_async(self).await })
223 }
224
225 /// Incrementally iterate set elements.
226 #[inline]
227 fn sscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
228 let mut c = cmd("SSCAN");
229 c.arg(key).cursor_arg(0);
230 Box::pin(async move {c.iter_async(self).await })
231 }
232
233 /// Incrementally iterate set elements for elements matching a pattern.
234 #[inline]
235 fn sscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
236 (&mut self, key: K, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
237 let mut c = cmd("SSCAN");
238 c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
239 Box::pin(async move {c.iter_async(self).await })
240 }
241
242 /// Incrementally iterate sorted set elements.
243 #[inline]
244 fn zscan<K: ToRedisArgs, RV: FromRedisValue>(&mut self, key: K) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
245 let mut c = cmd("ZSCAN");
246 c.arg(key).cursor_arg(0);
247 Box::pin(async move {c.iter_async(self).await })
248 }
249
250 /// Incrementally iterate sorted set elements for elements matching a pattern.
251 #[inline]
252 fn zscan_match<K: ToRedisArgs, P: ToRedisArgs, RV: FromRedisValue>
253 (&mut self, key: K, pattern: P) -> crate::types::RedisFuture<crate::cmd::AsyncIter<'_, RV>> {
254 let mut c = cmd("ZSCAN");
255 c.arg(key).cursor_arg(0).arg("MATCH").arg(pattern);
256 Box::pin(async move {c.iter_async(self).await })
257 }
258 }
259
260 /// Implements common redis commands for pipelines. Unlike the regular
261 /// commands trait, this returns the pipeline rather than a result
262 /// directly. Other than that it works the same however.
263 impl Pipeline {
264 $(
265 $(#[$attr])*
266 #[inline]
267 #[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
268 pub fn $name<$lifetime, $($tyargs: $ty),*>(
269 &mut self $(, $argname: $argty)*
270 ) -> &mut Self {
271 self.add_command(::std::mem::replace($body, Cmd::new()))
272 }
273 )*
274 }
275
276 // Implements common redis commands for cluster pipelines. Unlike the regular
277 // commands trait, this returns the cluster pipeline rather than a result
278 // directly. Other than that it works the same however.
279 #[cfg(feature = "cluster")]
280 impl ClusterPipeline {
281 $(
282 $(#[$attr])*
283 #[inline]
284 #[allow(clippy::extra_unused_lifetimes, clippy::needless_lifetimes)]
285 pub fn $name<$lifetime, $($tyargs: $ty),*>(
286 &mut self $(, $argname: $argty)*
287 ) -> &mut Self {
288 self.add_command(::std::mem::replace($body, Cmd::new()))
289 }
290 )*
291 }
292 )
293}