ntex_redis/cmd/hashes.rs
1use std::convert::TryFrom;
2
3use ntex::util::{Bytes, HashMap};
4
5use super::{utils, Command, CommandError};
6use crate::codec::{BulkString, Request, Response};
7
8/// HGET redis command
9///
10/// Returns the value associated with field in the hash stored at key.
11///
12/// ```rust
13/// use ntex_redis::{cmd, RedisConnector};
14/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
15/// # fn gen_random_key() -> String {
16/// # thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
17/// # }
18///
19/// #[ntex::main]
20/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
21/// let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
22/// let key = gen_random_key();
23///
24/// // create hashmap
25/// redis.exec(cmd::HSet(&key, "test-key", "value")).await?;
26///
27/// // get field value
28/// let value = redis.exec(cmd::HGet(&key, "test-key")).await?;
29///
30/// assert_eq!(value.unwrap(), "value");
31/// Ok(())
32/// }
33/// ```
34pub fn HGet<T, V>(key: T, field: V) -> utils::BulkOutputCommand
35where
36 BulkString: From<T> + From<V>,
37{
38 utils::BulkOutputCommand(Request::Array(vec![
39 Request::from_static("HGET"),
40 Request::BulkString(key.into()),
41 Request::BulkString(field.into()),
42 ]))
43}
44
45/// HGETALL redis command
46///
47/// Returns all fields and values of the hash stored at `key`
48pub fn HGetAll<T>(key: T) -> HGetAllCommand
49where
50 BulkString: From<T>,
51{
52 HGetAllCommand(vec![
53 Request::from_static("HGETALL"),
54 Request::BulkString(key.into()),
55 ])
56}
57
58pub struct HGetAllCommand(Vec<Request>);
59
60impl Command for HGetAllCommand {
61 type Output = HashMap<Bytes, Bytes>;
62
63 fn to_request(self) -> Request {
64 Request::Array(self.0)
65 }
66
67 fn to_output(val: Response) -> Result<Self::Output, CommandError> {
68 Ok(HashMap::try_from(val)?)
69 }
70}
71
72/// HSET redis command
73///
74/// Sets field in the hash stored at key to value.
75///
76/// ```rust
77/// use ntex_redis::{cmd, RedisConnector};
78/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
79/// # fn gen_random_key() -> String {
80/// # thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
81/// # }
82///
83/// #[ntex::main]
84/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
85/// let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
86/// let key = gen_random_key();
87///
88/// // create hashmap and set field
89/// redis.exec(cmd::HSet(&key, "test-key", "value")).await?;
90///
91/// // get field value
92/// let value = redis.exec(cmd::HGet(&key, "test-key")).await?;
93///
94/// assert_eq!(value.unwrap(), "value");
95/// Ok(())
96/// }
97/// ```
98pub fn HSet<T, K, V>(key: T, field: K, value: V) -> HSetCommand
99where
100 BulkString: From<T> + From<K> + From<V>,
101{
102 HSetCommand(vec![
103 Request::from_static("HSET"),
104 Request::BulkString(key.into()),
105 Request::BulkString(field.into()),
106 Request::BulkString(value.into()),
107 ])
108}
109
110pub struct HSetCommand(Vec<Request>);
111
112impl HSetCommand {
113 /// Insert new entry to a redis hashmap
114 pub fn entry<K, V>(mut self, field: K, value: V) -> Self
115 where
116 BulkString: From<K> + From<V>,
117 {
118 self.0.push(field.into());
119 self.0.push(value.into());
120 self
121 }
122
123 /// Insert new entry to a redis hashmap
124 pub fn add_entry<K, V>(&mut self, field: K, value: V)
125 where
126 BulkString: From<K> + From<V>,
127 {
128 self.0.push(field.into());
129 self.0.push(value.into());
130 }
131}
132
133impl Command for HSetCommand {
134 type Output = usize;
135
136 fn to_request(self) -> Request {
137 Request::Array(self.0)
138 }
139
140 fn to_output(val: Response) -> Result<Self::Output, CommandError> {
141 match val {
142 Response::Integer(val) => Ok(val as usize),
143 _ => Err(CommandError::Output("Cannot parse response", val)),
144 }
145 }
146}
147
148/// HDEL redis command
149///
150/// Removes the specified fields from the hash stored at key.
151///
152/// ```rust
153/// use ntex_redis::{cmd, RedisConnector};
154/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
155/// # fn gen_random_key() -> String {
156/// # thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
157/// # }
158///
159/// #[ntex::main]
160/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
161/// let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
162/// let key = gen_random_key();
163///
164/// // create hashmap and set field
165/// redis.exec(cmd::HSet(&key, "test-key", "value")).await?;
166///
167/// // delete hashmap field
168/// let value = redis.exec(cmd::HDel(&key, "test-key")).await?;
169///
170/// assert_eq!(value, 1);
171/// Ok(())
172/// }
173/// ```
174pub fn HDel<T, K>(key: T, field: K) -> HDelCommand
175where
176 BulkString: From<T> + From<K>,
177{
178 HDelCommand(vec![
179 Request::from_static("HDEL"),
180 Request::BulkString(key.into()),
181 Request::BulkString(field.into()),
182 ])
183}
184
185pub struct HDelCommand(Vec<Request>);
186
187impl HDelCommand {
188 /// Remove field
189 pub fn remove<K>(mut self, field: K) -> Self
190 where
191 BulkString: From<K>,
192 {
193 self.0.push(field.into());
194 self
195 }
196
197 /// Add more fields to remove
198 pub fn remove_all<T>(mut self, other: impl IntoIterator<Item = T>) -> Self
199 where
200 BulkString: From<T>,
201 {
202 self.0.extend(other.into_iter().map(|t| t.into()));
203 self
204 }
205}
206
207impl Command for HDelCommand {
208 type Output = usize;
209
210 fn to_request(self) -> Request {
211 Request::Array(self.0)
212 }
213
214 fn to_output(val: Response) -> Result<Self::Output, CommandError> {
215 match val {
216 Response::Integer(val) => Ok(val as usize),
217 _ => Err(CommandError::Output("Cannot parse response", val)),
218 }
219 }
220}
221
222/// HLEN redis command
223///
224/// Returns the number of fields contained in the hash stored at key.
225///
226/// ```rust
227/// use ntex_redis::{cmd, RedisConnector};
228/// # use rand::{thread_rng, Rng, distributions::Alphanumeric};
229/// # fn gen_random_key() -> String {
230/// # thread_rng().sample_iter(&Alphanumeric).take(12).map(char::from).collect::<String>()
231/// # }
232///
233/// #[ntex::main]
234/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
235/// let redis = RedisConnector::new("127.0.0.1:6379").connect().await?;
236/// let key = gen_random_key();
237///
238/// // create hashmap and set field
239/// redis.exec(cmd::HSet(&key, "test-key", "value")).await?;
240///
241/// // get len of hashmap
242/// let value = redis.exec(cmd::HLen(&key)).await?;
243///
244/// assert_eq!(value, 1);
245/// Ok(())
246/// }
247/// ```
248pub fn HLen<T>(key: T) -> utils::IntOutputCommand
249where
250 BulkString: From<T>,
251{
252 utils::IntOutputCommand(Request::Array(vec![
253 Request::from_static("HLEN"),
254 Request::BulkString(key.into()),
255 ]))
256}
257
258/// HINCRBY redis command
259///
260/// Increments the number stored at `field` in the hash stored at `key` by `increment`.
261pub fn HIncrBy<T, K, I>(key: T, field: K, increment: I) -> utils::IntOutputCommand
262where
263 BulkString: From<T> + From<K>,
264 i64: From<I>,
265{
266 utils::IntOutputCommand(Request::Array(vec![
267 Request::from_static("HINCRBY"),
268 Request::BulkString(key.into()),
269 Request::BulkString(field.into()),
270 Request::BulkString(i64::from(increment).to_string().into()),
271 ]))
272}