rustis/commands/
hash_commands.rs

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