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}