Skip to main content

rustis/commands/
hash_commands.rs

1use crate::{
2    client::{PreparedCommand, prepare_command},
3    commands::{ExpireOption, GetExOptions, SetExpiration},
4    resp::{
5        ArgCounter, FastPathCommandBuilder, Response, cmd, deserialize_vec_of_pairs, serialize_flag,
6    },
7};
8use serde::{Deserialize, Serialize, de::DeserializeOwned};
9
10/// A group of Redis commands related to [`Hashes`](https://redis.io/docs/data-types/hashes/)
11///
12/// # See Also
13/// [Redis Hash Commands](https://redis.io/commands/?group=hash)
14pub trait HashCommands<'a>: Sized {
15    /// Removes the specified fields from the hash stored at key.
16    ///
17    /// # Return
18    /// the number of fields that were removed from the hash, not including specified but non existing fields.
19    ///
20    /// # See Also
21    /// [<https://redis.io/commands/hdel/>](https://redis.io/commands/hdel/)
22    #[must_use]
23    fn hdel(self, key: impl Serialize, fields: impl Serialize) -> PreparedCommand<'a, Self, usize> {
24        prepare_command(self, cmd("HDEL").key(key).arg(fields))
25    }
26
27    /// Returns if field is an existing field in the hash stored at key.
28    ///
29    /// # Return
30    /// * `true` - if the hash contains field.
31    /// * `false` - if the hash does not contain field, or key does not exist.
32    ///
33    /// # See Also
34    /// [<https://redis.io/commands/hexists/>](https://redis.io/commands/hexists/)
35    #[must_use]
36    fn hexists(
37        self,
38        key: impl Serialize,
39        field: impl Serialize,
40    ) -> PreparedCommand<'a, Self, bool> {
41        prepare_command(self, cmd("HEXISTS").key(key).arg(field))
42    }
43
44    /// Set an expiration (TTL or time to live) on one or more fields of a given hash key.
45    ///
46    /// Field(s) will automatically be deleted from the hash key when their TTLs expire.
47    ///
48    /// # Arguments
49    /// * `key` - The hash key
50    /// * `seconds ` - The expiration time in seconds
51    /// * `option` - The [`ExpireOption`](crate::commands::ExpireOption) option.
52    /// * `fields` - The fields to expire.
53    ///
54    /// # Return
55    /// For each field:
56    /// * `-2` - if no such field exists in the provided hash key, or the provided key does not exist.
57    /// * `0` - if the specified NX | XX | GT | LT condition has not been met.
58    /// * `1` - if the expiration time was set/updated.
59    /// * `2` - when the command is called with 0 seconds.
60    ///
61    /// # See Also
62    /// [<https://redis.io/commands/hexpire/>](https://redis.io/commands/hexpire/)
63    #[must_use]
64    fn hexpire<R: Response>(
65        self,
66        key: impl Serialize,
67        seconds: u64,
68        option: impl Into<Option<ExpireOption>>,
69        fields: impl Serialize,
70    ) -> PreparedCommand<'a, Self, R> {
71        prepare_command(
72            self,
73            cmd("HEXPIRE")
74                .key(key)
75                .arg(seconds)
76                .arg(option.into())
77                .arg("FIELDS")
78                .arg_with_count(fields),
79        )
80    }
81
82    /// HEXPIREAT has the same effect and semantics as HEXPIRE,
83    /// but instead of specifying the number of seconds for the TTL (time to live),
84    /// it takes an absolute Unix timestamp in seconds since Unix epoch.
85    ///
86    /// A timestamp in the past will delete the field immediately.
87    ///
88    /// # Arguments
89    /// * `key` - The hash key
90    /// * `unix_time_seconds ` - The aboslute unix timestamp the fields will expire at.
91    /// * `option` - The [`ExpireOption`](crate::commands::ExpireOption) option.
92    /// * `fields` - The fields to expire.
93    ///
94    /// # Return
95    /// For each field:
96    /// * `-2` - if no such field exists in the provided hash key, or the provided key does not exist.
97    /// * `0` - if the specified NX | XX | GT | LT condition has not been met.
98    /// * `1` - if the expiration time was set/updated.
99    /// * `2` - when the command is called with a past Unix time in seconds.
100    ///
101    /// # See Also
102    /// [<https://redis.io/commands/hexpireat/>](https://redis.io/commands/hexpireat/)
103    #[must_use]
104    fn hexpireat<R: Response>(
105        self,
106        key: impl Serialize,
107        unix_time_seconds: u64,
108        option: impl Into<Option<ExpireOption>>,
109        fields: impl Serialize,
110    ) -> PreparedCommand<'a, Self, R> {
111        prepare_command(
112            self,
113            cmd("HEXPIREAT")
114                .key(key)
115                .arg(unix_time_seconds)
116                .arg(option.into())
117                .arg("FIELDS")
118                .arg_with_count(fields),
119        )
120    }
121
122    /// Returns the absolute Unix timestamp in seconds since Unix epoch
123    /// at which the given key's field(s) will expire.
124    ///
125    /// # Arguments
126    /// * `key` - The hash key
127    /// * `fields` - The fields to get the expiration time from.
128    ///
129    /// # Return
130    /// For each field, the expiration (Unix timestamp) in seconds.
131    /// - The command returns -2 if no such field exists in the provided hash key, or the provided key does not exist.
132    /// - The command returns -1 if the field exists but has no associated expiration set.
133    ///
134    /// # See Also
135    /// [<https://redis.io/commands/hexpiretime/>](https://redis.io/commands/hexpiretime/)
136    #[must_use]
137    fn hexpiretime<R: Response>(
138        self,
139        key: impl Serialize,
140        fields: impl Serialize,
141    ) -> PreparedCommand<'a, Self, R> {
142        prepare_command(
143            self,
144            cmd("HEXPIRETIME")
145                .key(key)
146                .arg("FIELDS")
147                .arg_with_count(fields),
148        )
149    }
150
151    /// Returns the value associated with field in the hash stored at key.
152    ///
153    /// # Return
154    /// The value associated with field, or nil when field is not present in the hash or key does not exist.
155    ///
156    /// # See Also
157    /// [<https://redis.io/commands/hget/>](https://redis.io/commands/hget/)
158    #[must_use]
159    fn hget<R: Response>(
160        self,
161        key: impl Serialize,
162        field: impl Serialize,
163    ) -> PreparedCommand<'a, Self, R> {
164        prepare_command(self, FastPathCommandBuilder::hget(key, field))
165    }
166
167    /// Returns all fields and values of the hash stored at key.
168    ///
169    /// # Return
170    /// The list of fields and their values stored in the hash, or an empty list when key does not exist.
171    ///
172    /// # See Also
173    /// [<https://redis.io/commands/hgetall/>](https://redis.io/commands/hgetall/)
174    #[must_use]
175    fn hgetall<R: Response>(self, key: impl Serialize) -> PreparedCommand<'a, Self, R> {
176        prepare_command(self, cmd("HGETALL").key(key))
177    }
178
179    /// Get and delete the value of one or more fields of a given hash key.
180    ///
181    /// When the last field is deleted, the key will also be deleted.
182    ///
183    /// # Arguments
184    /// * `key` - The hash key
185    /// * `fields` - The fields to get and delete.
186    ///
187    /// # Return
188    /// A list of deleted fields and their values or nil for fields that do not exist.
189    ///
190    /// # See Also
191    /// [<https://redis.io/commands/hgetdel/>](https://redis.io/commands/hgetdel/)
192    #[must_use]
193    fn hgetdel<R: Response>(
194        self,
195        key: impl Serialize,
196        fields: impl Serialize,
197    ) -> PreparedCommand<'a, Self, R> {
198        prepare_command(
199            self,
200            cmd("HGETDEL").key(key).arg("FIELDS").arg_with_count(fields),
201        )
202    }
203
204    /// Get the value of one or more fields of a given hash key
205    /// and optionally set their expiration time or time-to-live (TTL).
206    ///
207    /// # Arguments
208    /// * `key` - The hash key
209    /// * `options` - The [`GetExOptions`](crate::commands::GetExOptions) options.
210    /// * `fields` - The fields to get.
211    ///
212    /// # Return
213    /// a list of values associated with the given fields, in the same order as they are requested.
214    ///
215    /// # See Also
216    /// [<https://redis.io/commands/hgetex/>](https://redis.io/commands/hgetex/)
217    #[must_use]
218    fn hgetex<R: Response>(
219        self,
220        key: impl Serialize,
221        options: GetExOptions,
222        fields: impl Serialize,
223    ) -> PreparedCommand<'a, Self, R> {
224        prepare_command(
225            self,
226            cmd("HGETEX")
227                .key(key)
228                .arg(options)
229                .arg("FIELDS")
230                .arg_with_count(fields),
231        )
232    }
233
234    /// Increments the number stored at field in the hash stored at key by increment.
235    ///
236    /// # Return
237    /// The value at field after the increment operation.
238    ///
239    /// # See Also
240    /// [<https://redis.io/commands/hincrby/>](https://redis.io/commands/hincrby/)
241    #[must_use]
242    fn hincrby(
243        self,
244        key: impl Serialize,
245        field: impl Serialize,
246        increment: i64,
247    ) -> PreparedCommand<'a, Self, i64> {
248        prepare_command(self, FastPathCommandBuilder::hincrby(key, field, increment))
249    }
250
251    /// Increment the specified field of a hash stored at key,
252    /// and representing a floating point number, by the specified increment.
253    ///
254    /// # Return
255    /// The value at field after the increment operation.
256    ///
257    /// # See Also
258    /// [<https://redis.io/commands/hincrbyfloat/>](https://redis.io/commands/hincrbyfloat/)
259    #[must_use]
260    fn hincrbyfloat(
261        self,
262        key: impl Serialize,
263        field: impl Serialize,
264        increment: f64,
265    ) -> PreparedCommand<'a, Self, f64> {
266        prepare_command(self, cmd("HINCRBYFLOAT").key(key).arg(field).arg(increment))
267    }
268
269    /// Returns all field names in the hash stored at key.
270    ///
271    /// # Return
272    /// The list of fields in the hash, or an empty list when key does not exist.
273    ///
274    /// # See Also
275    /// [<https://redis.io/commands/hkeys/>](https://redis.io/commands/hkeys/)
276    #[must_use]
277    fn hkeys<R: Response>(self, key: impl Serialize) -> PreparedCommand<'a, Self, R> {
278        prepare_command(self, cmd("HKEYS").key(key))
279    }
280
281    /// Returns the number of fields contained in the hash stored at key.
282    ///
283    /// # Return
284    /// The number of fields in the hash, or 0 when key does not exist.
285    ///
286    /// # See Also
287    /// [<https://redis.io/commands/hlen/>](https://redis.io/commands/hlen/)
288    #[must_use]
289    fn hlen(self, key: impl Serialize) -> PreparedCommand<'a, Self, usize> {
290        prepare_command(self, cmd("HLEN").key(key))
291    }
292
293    /// Returns the values associated with the specified fields in the hash stored at key.
294    ///
295    /// # Return
296    /// The list of values associated with the given fields, in the same order as they are requested.
297    ///
298    /// # See Also
299    /// [<https://redis.io/commands/hmget/>](https://redis.io/commands/hmget/)
300    #[must_use]
301    fn hmget<R: Response>(
302        self,
303        key: impl Serialize,
304        fields: impl Serialize,
305    ) -> PreparedCommand<'a, Self, R> {
306        prepare_command(self, cmd("HMGET").key(key).arg(fields))
307    }
308
309    /// Remove the existing expiration on a hash key's field(s),
310    /// turning the field(s) from volatile (a field with expiration set)
311    /// to persistent (a field that will never expire as no TTL (time to live) is associated).
312    ///
313    /// # Return
314    /// For each field:
315    /// * `-2` - if no such field exists in the provided hash key, or the provided key does not exist.
316    /// * `-1` - if the field exists but has no associated expiration set.
317    /// * `1` - the expiration was removed.
318    ///
319    /// # See Also
320    /// [<https://redis.io/commands/hpersist/>](https://redis.io/commands/hpersist/)
321    #[must_use]
322    fn hpersist<R: Response>(
323        self,
324        key: impl Serialize,
325        fields: impl Serialize,
326    ) -> PreparedCommand<'a, Self, R> {
327        prepare_command(self, cmd("HPERSIST").key(key).arg(fields))
328    }
329
330    /// This command works like [`hexpire`](HashCommands::hexpire), but the expiration of a field is specified in milliseconds instead of seconds.
331    ///
332    /// # Arguments
333    /// * `key` - The hash key
334    /// * `milliseconds ` - The expiration time in milliseconds
335    /// * `option` - The [`ExpireOption`](crate::commands::ExpireOption) option.
336    /// * `fields` - The fields to expire.
337    ///
338    /// # Return
339    /// For each field:
340    /// * `-2` - if no such field exists in the provided hash key, or the provided key does not exist.
341    /// * `0` - if the specified NX | XX | GT | LT condition has not been met.
342    /// * `1` - if the expiration time was set/updated.
343    /// * `2` - when the command is called with 0 milliseconds.
344    ///
345    /// # See Also
346    /// [<https://redis.io/commands/hpexpire/>](https://redis.io/commands/hpexpire/)
347    #[must_use]
348    fn hpexpire<R: Response>(
349        self,
350        key: impl Serialize,
351        milliseconds: u64,
352        option: impl Into<Option<ExpireOption>>,
353        fields: impl Serialize,
354    ) -> PreparedCommand<'a, Self, R> {
355        prepare_command(
356            self,
357            cmd("HPEXPIRE")
358                .key(key)
359                .arg(milliseconds)
360                .arg(option.into())
361                .arg("FIELDS")
362                .arg_with_count(fields),
363        )
364    }
365
366    /// This command has the same effect and semantics as [`hexpireat`](HashCommands::hexpireat),
367    /// but the Unix time at which the field will expire
368    /// is specified in milliseconds since Unix epoch instead of seconds.
369    ///
370    /// # Arguments
371    /// * `key` - The hash key
372    /// * `unix_time_milliseconds` - The aboslute unix timestamp in milliseconds, the fields will expire at.
373    /// * `option` - The [`ExpireOption`](crate::commands::ExpireOption) option.
374    /// * `fields` - The fields to expire.
375    ///
376    /// # Return
377    /// For each field:
378    /// * `-2` - if no such field exists in the provided hash key, or the provided key does not exist.
379    /// * `0` - if the specified NX | XX | GT | LT condition has not been met.
380    /// * `1` - if the expiration time was set/updated.
381    /// * `2` - when the command is called with a past Unix time in milliseconds.
382    ///
383    /// # See Also
384    /// [<https://redis.io/commands/hpexpireat/>](https://redis.io/commands/hpexpireat/)
385    #[must_use]
386    fn hpexpireat<R: Response>(
387        self,
388        key: impl Serialize,
389        unix_time_milliseconds: u64,
390        option: impl Into<Option<ExpireOption>>,
391        fields: impl Serialize,
392    ) -> PreparedCommand<'a, Self, R> {
393        prepare_command(
394            self,
395            cmd("HPEXPIREAT")
396                .key(key)
397                .arg(unix_time_milliseconds)
398                .arg(option.into())
399                .arg("FIELDS")
400                .arg_with_count(fields),
401        )
402    }
403
404    /// This command has the same semantics as [`hexpiretime`](HashCommands::hexpiretime),
405    /// but returns the absolute Unix expiration timestamp
406    /// in milliseconds since Unix epoch instead of seconds.
407    ///
408    /// # Arguments
409    /// * `key` - The hash key
410    /// * `fields` - The fields to get the expiration time from.
411    ///
412    /// # Return
413    /// For each field, the expiration (Unix timestamp) in milliseconds.
414    /// - The command returns -2 if no such field exists in the provided hash key, or the provided key does not exist.
415    /// - The command returns -1 if the field exists but has no associated expiration set.
416    ///
417    /// # See Also
418    /// [<https://redis.io/commands/hpexpiretime/>](https://redis.io/commands/hpexpiretime/)
419    #[must_use]
420    fn hpexpiretime<R: Response>(
421        self,
422        key: impl Serialize,
423        fields: impl Serialize,
424    ) -> PreparedCommand<'a, Self, R> {
425        prepare_command(
426            self,
427            cmd("HPEXPIRETIME")
428                .key(key)
429                .arg("FIELDS")
430                .arg_with_count(fields),
431        )
432    }
433
434    /// Like [`httl`](HashCommands::httl), this command returns the remaining TTL (time to live)
435    /// of a field that has an expiration set, but in milliseconds instead of seconds.
436    ///
437    /// # Arguments
438    /// * `key` - The hash key
439    /// * `fields` - The fields to get the TTL from.
440    ///
441    /// # Return
442    /// the TTL in milliseconds.
443    /// - The command returns -2 if no such field exists in the provided hash key, or the provided key does not exist.
444    /// - The command returns -1 if the field exists but has no associated expiration set.
445    ///
446    /// # See Also
447    /// [<https://redis.io/commands/hpttl/>](https://redis.io/commands/hpttl/)
448    #[must_use]
449    fn hpttl<R: Response>(
450        self,
451        key: impl Serialize,
452        fields: impl Serialize,
453    ) -> PreparedCommand<'a, Self, R> {
454        prepare_command(
455            self,
456            cmd("HPTTL").key(key).arg("FIELDS").arg_with_count(fields),
457        )
458    }
459
460    /// return random fields from the hash value stored at key.
461    ///
462    /// # Return
463    /// * When called with just the key argument, return a random field from the hash value stored at key.
464    ///
465    /// # See Also
466    /// [<https://redis.io/commands/hrandfield/>](https://redis.io/commands/hrandfield/)
467    #[must_use]
468    fn hrandfield<R: Response>(self, key: impl Serialize) -> PreparedCommand<'a, Self, R> {
469        prepare_command(self, cmd("HRANDFIELD").key(key))
470    }
471
472    /// return random fields from the hash value stored at key.
473    ///
474    /// # Return
475    /// * If the provided count argument is positive, return an array of distinct fields.
476    ///   The array's length is either count or the hash's number of fields (HLEN), whichever is lower.
477    /// * If called with a negative count, the behavior changes and the command is allowed to return the same field multiple times.
478    ///   In this case, the number of returned fields is the absolute value of the specified count.
479    ///
480    /// # See Also
481    /// [<https://redis.io/commands/hrandfield/>](https://redis.io/commands/hrandfield/)
482    #[must_use]
483    fn hrandfields<R: Response>(
484        self,
485        key: impl Serialize,
486        count: isize,
487    ) -> PreparedCommand<'a, Self, R> {
488        prepare_command(self, cmd("HRANDFIELD").key(key).arg(count))
489    }
490
491    /// return random fields from the hash value stored at key.
492    ///
493    /// # Return
494    /// * If the provided count argument is positive, return an array of distinct fields.
495    ///   The array's length is either count or the hash's number of fields (HLEN), whichever is lower.
496    /// * If called with a negative count, the behavior changes and the command is allowed to return the same field multiple times.
497    ///   In this case, the number of returned fields is the absolute value of the specified count.
498    ///   The optional WITHVALUES modifier changes the reply so it includes the respective values of the randomly selected hash fields.
499    ///
500    /// # See Also
501    /// [<https://redis.io/commands/hrandfield/>](https://redis.io/commands/hrandfield/)
502    #[must_use]
503    fn hrandfields_with_values<R: Response>(
504        self,
505        key: impl Serialize,
506        count: isize,
507    ) -> PreparedCommand<'a, Self, R> {
508        prepare_command(
509            self,
510            cmd("HRANDFIELD").key(key).arg(count).arg("WITHVALUES"),
511        )
512    }
513
514    /// Iterates fields of Hash types and their associated values.
515    ///
516    /// # Return
517    /// array of elements contain two elements, a field and a value,
518    /// for every returned element of the Hash.
519    ///
520    /// # See Also
521    /// [<https://redis.io/commands/hlen/>](https://redis.io/commands/hscan/)
522    #[must_use]
523    fn hscan<F: Response + DeserializeOwned, V: Response + DeserializeOwned>(
524        self,
525        key: impl Serialize,
526        cursor: u64,
527        options: HScanOptions,
528    ) -> PreparedCommand<'a, Self, HScanResult<F, V>> {
529        prepare_command(self, cmd("HSCAN").key(key).arg(cursor).arg(options))
530    }
531
532    /// Sets field in the hash stored at key to value.
533    ///
534    /// # Return
535    /// The number of fields that were added.
536    ///
537    /// # See Also
538    /// [<https://redis.io/commands/hset/>](https://redis.io/commands/hset/)
539    #[must_use]
540    fn hset(self, key: impl Serialize, items: impl Serialize) -> PreparedCommand<'a, Self, usize> {
541        prepare_command(self, cmd("HSET").key(key).arg(items))
542    }
543
544    /// Set the value of one or more fields of a given hash key,
545    /// and optionally set their expiration time or time-to-live (TTL).
546    ///
547    /// # Return
548    /// * `true` if all the fields wereset.
549    /// * `false` if no fields were set.
550    ///
551    /// # See Also
552    /// [<https://redis.io/commands/hsetex/>](https://redis.io/commands/hsetex/)
553    #[must_use]
554    fn hsetex(
555        self,
556        key: impl Serialize,
557        condition: impl Into<Option<HSetExCondition>>,
558        expiration: impl Into<Option<SetExpiration>>,
559        items: impl Serialize,
560    ) -> PreparedCommand<'a, Self, bool> {
561        let mut counter = ArgCounter::default();
562        items.serialize(&mut counter).expect("Arg counting failed");
563
564        prepare_command(
565            self,
566            cmd("HSETEX")
567                .key(key)
568                .arg(condition.into())
569                .arg(expiration.into())
570                .arg("FIELDS")
571                .arg(counter.count / 2)
572                .arg(items),
573        )
574    }
575
576    /// Sets field in the hash stored at key to value, only if field does not yet exist.
577    ///
578    /// # Return
579    /// * `true` - if field is a new field in the hash and value was set.
580    /// * `false` - if field already exists in the hash and no operation was performed.
581    ///
582    /// # See Also
583    /// [<https://redis.io/commands/hsetnx/>](https://redis.io/commands/hsetnx/)
584    #[must_use]
585    fn hsetnx(
586        self,
587        key: impl Serialize,
588        field: impl Serialize,
589        value: impl Serialize,
590    ) -> PreparedCommand<'a, Self, bool> {
591        prepare_command(self, cmd("HSETNX").key(key).arg(field).arg(value))
592    }
593
594    /// Returns the string length of the value associated with field in the hash stored at key.
595    ///
596    /// # Return
597    /// the string length of the value associated with field,
598    /// or zero when field is not present in the hash or key does not exist at all.
599    ///
600    /// # See Also
601    /// [<https://redis.io/commands/hstrlen/>](https://redis.io/commands/hstrlen/)
602    #[must_use]
603    fn hstrlen(
604        self,
605        key: impl Serialize,
606        field: impl Serialize,
607    ) -> PreparedCommand<'a, Self, usize> {
608        prepare_command(self, cmd("HSTRLEN").key(key).arg(field))
609    }
610
611    /// Returns the remaining TTL (time to live) of a hash key's field(s) that have a set expiration.
612    /// This introspection capability allows you to check how many seconds
613    /// a given hash field will continue to be part of the hash key.
614    ///
615    /// # Arguments
616    /// * `key` - The hash key
617    /// * `fields` - The fields to get the TTL from.
618    ///
619    /// # Return
620    /// The TTL in seconds.
621    /// - The command returns -2 if no such field exists in the provided hash key, or the provided key does not exist.
622    /// - The command returns -1 if the field exists but has no associated expiration set.
623    ///
624    /// # See Also
625    /// [<https://redis.io/commands/httl/>](https://redis.io/commands/httl/)
626    #[must_use]
627    fn httl<R: Response>(
628        self,
629        key: impl Serialize,
630        fields: impl Serialize,
631    ) -> PreparedCommand<'a, Self, R> {
632        prepare_command(
633            self,
634            cmd("HTTL").key(key).arg("FIELDS").arg_with_count(fields),
635        )
636    }
637
638    /// list of values in the hash, or an empty list when key does not exist.
639    ///
640    /// # Return
641    /// The list of values in the hash, or an empty list when key does not exist.
642    ///
643    /// # See Also
644    /// [<https://redis.io/commands/hvals/>](https://redis.io/commands/hvals/)
645    #[must_use]
646    fn hvals<R: Response>(self, key: impl Serialize) -> PreparedCommand<'a, Self, R> {
647        prepare_command(self, cmd("HVALS").key(key))
648    }
649}
650
651/// Options for the [`hscan`](HashCommands::hscan) command
652#[derive(Default, Serialize)]
653#[serde(rename_all = "UPPERCASE")]
654pub struct HScanOptions<'a> {
655    #[serde(skip_serializing_if = "Option::is_none")]
656    r#match: Option<&'a str>,
657    #[serde(skip_serializing_if = "Option::is_none")]
658    count: Option<u32>,
659    #[serde(
660        skip_serializing_if = "std::ops::Not::not",
661        serialize_with = "serialize_flag"
662    )]
663    novalues: bool,
664}
665
666impl<'a> HScanOptions<'a> {
667    #[must_use]
668    pub fn match_pattern(mut self, match_pattern: &'a str) -> Self {
669        self.r#match = Some(match_pattern);
670        self
671    }
672
673    #[must_use]
674    pub fn count(mut self, count: u32) -> Self {
675        self.count = Some(count);
676        self
677    }
678
679    #[must_use]
680    pub fn no_values(mut self) -> Self {
681        self.novalues = true;
682        self
683    }
684}
685
686/// Result for the [`hscan`](HashCommands::hscan) command.
687#[derive(Debug, Deserialize)]
688pub struct HScanResult<F: Response + DeserializeOwned, V: Response + DeserializeOwned> {
689    pub cursor: u64,
690    #[serde(deserialize_with = "deserialize_vec_of_pairs")]
691    pub elements: Vec<(F, V)>,
692}
693
694/// Condition option for the [`hsetex`](HashCommands::hsetex) command
695#[derive(Serialize)]
696#[serde(rename_all = "UPPERCASE")]
697pub enum HSetExCondition {
698    /// Only set the fields if none of them already exist.
699    FNX,
700    /// Only set the fields if all of them already exist.
701    FXX,
702}