redis/
types.rs

1#[cfg(feature = "ahash")]
2pub(crate) use ahash::{AHashMap as HashMap, AHashSet as HashSet};
3use num_bigint::BigInt;
4use std::borrow::Cow;
5#[cfg(not(feature = "ahash"))]
6pub(crate) use std::collections::{HashMap, HashSet};
7use std::default::Default;
8use std::error;
9use std::ffi::{CString, NulError};
10use std::fmt;
11use std::hash::{BuildHasher, Hash};
12use std::io;
13use std::ops::Deref;
14use std::str::{from_utf8, Utf8Error};
15use std::string::FromUtf8Error;
16
17macro_rules! invalid_type_error {
18    ($v:expr, $det:expr) => {{
19        fail!(invalid_type_error_inner!($v, $det))
20    }};
21}
22
23macro_rules! invalid_type_error_inner {
24    ($v:expr, $det:expr) => {
25        RedisError::from((
26            ErrorKind::TypeError,
27            "Response was of incompatible type",
28            format!("{:?} (response was {:?})", $det, $v),
29        ))
30    };
31}
32
33/// Helper enum that is used to define expiry time
34pub enum Expiry {
35    /// EX seconds -- Set the specified expire time, in seconds.
36    EX(u64),
37    /// PX milliseconds -- Set the specified expire time, in milliseconds.
38    PX(u64),
39    /// EXAT timestamp-seconds -- Set the specified Unix time at which the key will expire, in seconds.
40    EXAT(u64),
41    /// PXAT timestamp-milliseconds -- Set the specified Unix time at which the key will expire, in milliseconds.
42    PXAT(u64),
43    /// PERSIST -- Remove the time to live associated with the key.
44    PERSIST,
45}
46
47/// Helper enum that is used to define expiry time for SET command
48#[derive(Clone, Copy)]
49pub enum SetExpiry {
50    /// EX seconds -- Set the specified expire time, in seconds.
51    EX(u64),
52    /// PX milliseconds -- Set the specified expire time, in milliseconds.
53    PX(u64),
54    /// EXAT timestamp-seconds -- Set the specified Unix time at which the key will expire, in seconds.
55    EXAT(u64),
56    /// PXAT timestamp-milliseconds -- Set the specified Unix time at which the key will expire, in milliseconds.
57    PXAT(u64),
58    /// KEEPTTL -- Retain the time to live associated with the key.
59    KEEPTTL,
60}
61
62/// Helper enum that is used to define existence checks
63#[derive(Clone, Copy)]
64pub enum ExistenceCheck {
65    /// NX -- Only set the key if it does not already exist.
66    NX,
67    /// XX -- Only set the key if it already exists.
68    XX,
69}
70
71/// Helper enum that is used to define field existence checks
72#[derive(Clone, Copy)]
73pub enum FieldExistenceCheck {
74    /// FNX -- Only set the fields if all do not already exist.
75    FNX,
76    /// FXX -- Only set the fields if all already exist.
77    FXX,
78}
79
80/// Helper enum that is used in some situations to describe
81/// the behavior of arguments in a numeric context.
82#[derive(PartialEq, Eq, Clone, Debug, Copy)]
83pub enum NumericBehavior {
84    /// This argument is not numeric.
85    NonNumeric,
86    /// This argument is an integer.
87    NumberIsInteger,
88    /// This argument is a floating point value.
89    NumberIsFloat,
90}
91
92/// An enum of all error kinds.
93#[derive(PartialEq, Eq, Copy, Clone, Debug)]
94#[non_exhaustive]
95pub enum ErrorKind {
96    /// The server generated an invalid response.
97    ResponseError,
98    /// The parser failed to parse the server response.
99    ParseError,
100    /// The authentication with the server failed.
101    AuthenticationFailed,
102    /// Operation failed because of a type mismatch.
103    TypeError,
104    /// A script execution was aborted.
105    ExecAbortError,
106    /// The server cannot response because it's loading a dump.
107    BusyLoadingError,
108    /// A script that was requested does not actually exist.
109    NoScriptError,
110    /// An error that was caused because the parameter to the
111    /// client were wrong.
112    InvalidClientConfig,
113    /// Raised if a key moved to a different node.
114    Moved,
115    /// Raised if a key moved to a different node but we need to ask.
116    Ask,
117    /// Raised if a request needs to be retried.
118    TryAgain,
119    /// Raised if a redis cluster is down.
120    ClusterDown,
121    /// A request spans multiple slots
122    CrossSlot,
123    /// A cluster master is unavailable.
124    MasterDown,
125    /// This kind is returned if the redis error is one that is
126    /// not native to the system.  This is usually the case if
127    /// the cause is another error.
128    IoError,
129    /// An error raised that was identified on the client before execution.
130    ClientError,
131    /// An extension error.  This is an error created by the server
132    /// that is not directly understood by the library.
133    ExtensionError,
134    /// Attempt to write to a read-only server
135    ReadOnly,
136    /// Requested name not found among masters returned by the sentinels
137    MasterNameNotFoundBySentinel,
138    /// No valid replicas found in the sentinels, for a given master name
139    NoValidReplicasFoundBySentinel,
140    /// At least one sentinel connection info is required
141    EmptySentinelList,
142    /// Attempted to kill a script/function while they werent' executing
143    NotBusy,
144    /// Used when a cluster connection cannot find a connection to a valid node.
145    ClusterConnectionNotFound,
146    /// Attempted to unsubscribe on a connection that is not in subscribed mode.
147    NoSub,
148
149    #[cfg(feature = "json")]
150    /// Error Serializing a struct to JSON form
151    Serialize,
152
153    /// Redis Servers prior to v6.0.0 doesn't support RESP3.
154    /// Try disabling resp3 option
155    RESP3NotSupported,
156}
157
158#[derive(PartialEq, Debug, Clone, Copy)]
159pub enum ServerErrorKind {
160    ResponseError,
161    ExecAbortError,
162    BusyLoadingError,
163    NoScriptError,
164    Moved,
165    Ask,
166    TryAgain,
167    ClusterDown,
168    CrossSlot,
169    MasterDown,
170    ReadOnly,
171    NotBusy,
172    NoSub,
173}
174
175#[derive(PartialEq, Debug, Clone)]
176pub enum ServerError {
177    ExtensionError {
178        code: String,
179        detail: Option<String>,
180    },
181    KnownError {
182        kind: ServerErrorKind,
183        detail: Option<String>,
184    },
185}
186
187impl ServerError {
188    pub fn kind(&self) -> Option<ServerErrorKind> {
189        match self {
190            ServerError::ExtensionError { .. } => None,
191            ServerError::KnownError { kind, .. } => Some(*kind),
192        }
193    }
194
195    pub fn code(&self) -> &str {
196        match self {
197            ServerError::ExtensionError { code, .. } => code,
198            ServerError::KnownError { kind, .. } => match kind {
199                ServerErrorKind::ResponseError => "ERR",
200                ServerErrorKind::ExecAbortError => "EXECABORT",
201                ServerErrorKind::BusyLoadingError => "LOADING",
202                ServerErrorKind::NoScriptError => "NOSCRIPT",
203                ServerErrorKind::Moved => "MOVED",
204                ServerErrorKind::Ask => "ASK",
205                ServerErrorKind::TryAgain => "TRYAGAIN",
206                ServerErrorKind::ClusterDown => "CLUSTERDOWN",
207                ServerErrorKind::CrossSlot => "CROSSSLOT",
208                ServerErrorKind::MasterDown => "MASTERDOWN",
209                ServerErrorKind::ReadOnly => "READONLY",
210                ServerErrorKind::NotBusy => "NOTBUSY",
211                ServerErrorKind::NoSub => "NOSUB",
212            },
213        }
214    }
215
216    pub fn details(&self) -> Option<&str> {
217        match self {
218            ServerError::ExtensionError { detail, .. } => detail.as_ref().map(|str| str.as_str()),
219            ServerError::KnownError { detail, .. } => detail.as_ref().map(|str| str.as_str()),
220        }
221    }
222}
223
224impl From<ServerError> for RedisError {
225    fn from(value: ServerError) -> Self {
226        // TODO - Consider changing RedisError to explicitly represent whether an error came from the server or not. Today it is only implied.
227        match value {
228            ServerError::ExtensionError { code, detail } => make_extension_error(code, detail),
229            ServerError::KnownError { kind, detail } => {
230                let desc = "An error was signalled by the server";
231                let kind = match kind {
232                    ServerErrorKind::ResponseError => ErrorKind::ResponseError,
233                    ServerErrorKind::ExecAbortError => ErrorKind::ExecAbortError,
234                    ServerErrorKind::BusyLoadingError => ErrorKind::BusyLoadingError,
235                    ServerErrorKind::NoScriptError => ErrorKind::NoScriptError,
236                    ServerErrorKind::Moved => ErrorKind::Moved,
237                    ServerErrorKind::Ask => ErrorKind::Ask,
238                    ServerErrorKind::TryAgain => ErrorKind::TryAgain,
239                    ServerErrorKind::ClusterDown => ErrorKind::ClusterDown,
240                    ServerErrorKind::CrossSlot => ErrorKind::CrossSlot,
241                    ServerErrorKind::MasterDown => ErrorKind::MasterDown,
242                    ServerErrorKind::ReadOnly => ErrorKind::ReadOnly,
243                    ServerErrorKind::NotBusy => ErrorKind::NotBusy,
244                    ServerErrorKind::NoSub => ErrorKind::NoSub,
245                };
246                match detail {
247                    Some(detail) => RedisError::from((kind, desc, detail)),
248                    None => RedisError::from((kind, desc)),
249                }
250            }
251        }
252    }
253}
254
255/// Internal low-level redis value enum.
256#[derive(PartialEq, Clone)]
257pub enum Value {
258    /// A nil response from the server.
259    Nil,
260    /// An integer response.  Note that there are a few situations
261    /// in which redis actually returns a string for an integer which
262    /// is why this library generally treats integers and strings
263    /// the same for all numeric responses.
264    Int(i64),
265    /// An arbitrary binary data, usually represents a binary-safe string.
266    BulkString(Vec<u8>),
267    /// A response containing an array with more data. This is generally used by redis
268    /// to express nested structures.
269    Array(Vec<Value>),
270    /// A simple string response, without line breaks and not binary safe.
271    SimpleString(String),
272    /// A status response which represents the string "OK".
273    Okay,
274    /// Unordered key,value list from the server. Use `as_map_iter` function.
275    Map(Vec<(Value, Value)>),
276    /// Attribute value from the server. Client will give data instead of whole Attribute type.
277    Attribute {
278        /// Data that attributes belong to.
279        data: Box<Value>,
280        /// Key,Value list of attributes.
281        attributes: Vec<(Value, Value)>,
282    },
283    /// Unordered set value from the server.
284    Set(Vec<Value>),
285    /// A floating number response from the server.
286    Double(f64),
287    /// A boolean response from the server.
288    Boolean(bool),
289    /// First String is format and other is the string
290    VerbatimString {
291        /// Text's format type
292        format: VerbatimFormat,
293        /// Remaining string check format before using!
294        text: String,
295    },
296    /// Very large number that out of the range of the signed 64 bit numbers
297    BigNumber(BigInt),
298    /// Push data from the server.
299    Push {
300        /// Push Kind
301        kind: PushKind,
302        /// Remaining data from push message
303        data: Vec<Value>,
304    },
305    /// Represents an error message from the server
306    ServerError(ServerError),
307}
308
309/// `VerbatimString`'s format types defined by spec
310#[derive(PartialEq, Clone, Debug)]
311pub enum VerbatimFormat {
312    /// Unknown type to catch future formats.
313    Unknown(String),
314    /// `mkd` format
315    Markdown,
316    /// `txt` format
317    Text,
318}
319
320/// `Push` type's currently known kinds.
321#[derive(PartialEq, Clone, Debug)]
322pub enum PushKind {
323    /// `Disconnection` is sent from the **library** when connection is closed.
324    Disconnection,
325    /// Other kind to catch future kinds.
326    Other(String),
327    /// `invalidate` is received when a key is changed/deleted.
328    Invalidate,
329    /// `message` is received when pubsub message published by another client.
330    Message,
331    /// `pmessage` is received when pubsub message published by another client and client subscribed to topic via pattern.
332    PMessage,
333    /// `smessage` is received when pubsub message published by another client and client subscribed to it with sharding.
334    SMessage,
335    /// `unsubscribe` is received when client unsubscribed from a channel.
336    Unsubscribe,
337    /// `punsubscribe` is received when client unsubscribed from a pattern.
338    PUnsubscribe,
339    /// `sunsubscribe` is received when client unsubscribed from a shard channel.
340    SUnsubscribe,
341    /// `subscribe` is received when client subscribed to a channel.
342    Subscribe,
343    /// `psubscribe` is received when client subscribed to a pattern.
344    PSubscribe,
345    /// `ssubscribe` is received when client subscribed to a shard channel.
346    SSubscribe,
347}
348
349impl PushKind {
350    #[cfg(feature = "aio")]
351    pub(crate) fn has_reply(&self) -> bool {
352        matches!(
353            self,
354            &PushKind::Unsubscribe
355                | &PushKind::PUnsubscribe
356                | &PushKind::SUnsubscribe
357                | &PushKind::Subscribe
358                | &PushKind::PSubscribe
359                | &PushKind::SSubscribe
360        )
361    }
362}
363
364impl fmt::Display for VerbatimFormat {
365    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366        match self {
367            VerbatimFormat::Markdown => write!(f, "mkd"),
368            VerbatimFormat::Unknown(val) => write!(f, "{val}"),
369            VerbatimFormat::Text => write!(f, "txt"),
370        }
371    }
372}
373
374impl fmt::Display for PushKind {
375    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376        match self {
377            PushKind::Other(kind) => write!(f, "{kind}"),
378            PushKind::Invalidate => write!(f, "invalidate"),
379            PushKind::Message => write!(f, "message"),
380            PushKind::PMessage => write!(f, "pmessage"),
381            PushKind::SMessage => write!(f, "smessage"),
382            PushKind::Unsubscribe => write!(f, "unsubscribe"),
383            PushKind::PUnsubscribe => write!(f, "punsubscribe"),
384            PushKind::SUnsubscribe => write!(f, "sunsubscribe"),
385            PushKind::Subscribe => write!(f, "subscribe"),
386            PushKind::PSubscribe => write!(f, "psubscribe"),
387            PushKind::SSubscribe => write!(f, "ssubscribe"),
388            PushKind::Disconnection => write!(f, "disconnection"),
389        }
390    }
391}
392
393pub enum MapIter<'a> {
394    Array(std::slice::Iter<'a, Value>),
395    Map(std::slice::Iter<'a, (Value, Value)>),
396}
397
398impl<'a> Iterator for MapIter<'a> {
399    type Item = (&'a Value, &'a Value);
400
401    fn next(&mut self) -> Option<Self::Item> {
402        match self {
403            MapIter::Array(iter) => Some((iter.next()?, iter.next()?)),
404            MapIter::Map(iter) => {
405                let (k, v) = iter.next()?;
406                Some((k, v))
407            }
408        }
409    }
410
411    fn size_hint(&self) -> (usize, Option<usize>) {
412        match self {
413            MapIter::Array(iter) => iter.size_hint(),
414            MapIter::Map(iter) => iter.size_hint(),
415        }
416    }
417}
418
419pub enum OwnedMapIter {
420    Array(std::vec::IntoIter<Value>),
421    Map(std::vec::IntoIter<(Value, Value)>),
422}
423
424impl Iterator for OwnedMapIter {
425    type Item = (Value, Value);
426
427    fn next(&mut self) -> Option<Self::Item> {
428        match self {
429            OwnedMapIter::Array(iter) => Some((iter.next()?, iter.next()?)),
430            OwnedMapIter::Map(iter) => iter.next(),
431        }
432    }
433
434    fn size_hint(&self) -> (usize, Option<usize>) {
435        match self {
436            OwnedMapIter::Array(iter) => {
437                let (low, high) = iter.size_hint();
438                (low / 2, high.map(|h| h / 2))
439            }
440            OwnedMapIter::Map(iter) => iter.size_hint(),
441        }
442    }
443}
444
445/// Values are generally not used directly unless you are using the
446/// more low level functionality in the library.  For the most part
447/// this is hidden with the help of the `FromRedisValue` trait.
448///
449/// While on the redis protocol there is an error type this is already
450/// separated at an early point so the value only holds the remaining
451/// types.
452impl Value {
453    /// Checks if the return value looks like it fulfils the cursor
454    /// protocol.  That means the result is an array item of length
455    /// two with the first one being a cursor and the second an
456    /// array response.
457    pub fn looks_like_cursor(&self) -> bool {
458        match *self {
459            Value::Array(ref items) => {
460                if items.len() != 2 {
461                    return false;
462                }
463                matches!(items[0], Value::BulkString(_)) && matches!(items[1], Value::Array(_))
464            }
465            _ => false,
466        }
467    }
468
469    /// Returns an `&[Value]` if `self` is compatible with a sequence type
470    pub fn as_sequence(&self) -> Option<&[Value]> {
471        match self {
472            Value::Array(items) => Some(&items[..]),
473            Value::Set(items) => Some(&items[..]),
474            Value::Nil => Some(&[]),
475            _ => None,
476        }
477    }
478
479    /// Returns a `Vec<Value>` if `self` is compatible with a sequence type,
480    /// otherwise returns `Err(self)`.
481    pub fn into_sequence(self) -> Result<Vec<Value>, Value> {
482        match self {
483            Value::Array(items) => Ok(items),
484            Value::Set(items) => Ok(items),
485            Value::Nil => Ok(vec![]),
486            _ => Err(self),
487        }
488    }
489
490    /// Returns an iterator of `(&Value, &Value)` if `self` is compatible with a map type
491    pub fn as_map_iter(&self) -> Option<MapIter<'_>> {
492        match self {
493            Value::Array(items) => {
494                if items.len() % 2 == 0 {
495                    Some(MapIter::Array(items.iter()))
496                } else {
497                    None
498                }
499            }
500            Value::Map(items) => Some(MapIter::Map(items.iter())),
501            _ => None,
502        }
503    }
504
505    /// Returns an iterator of `(Value, Value)` if `self` is compatible with a map type.
506    /// If not, returns `Err(self)`.
507    pub fn into_map_iter(self) -> Result<OwnedMapIter, Value> {
508        match self {
509            Value::Array(items) => {
510                if items.len() % 2 == 0 {
511                    Ok(OwnedMapIter::Array(items.into_iter()))
512                } else {
513                    Err(Value::Array(items))
514                }
515            }
516            Value::Map(items) => Ok(OwnedMapIter::Map(items.into_iter())),
517            _ => Err(self),
518        }
519    }
520
521    /// If value contains a server error, return it as an Err. Otherwise wrap the value in Ok.
522    pub fn extract_error(self) -> RedisResult<Self> {
523        match self {
524            Self::Array(val) => Ok(Self::Array(Self::extract_error_vec(val)?)),
525            Self::Map(map) => Ok(Self::Map(Self::extract_error_map(map)?)),
526            Self::Attribute { data, attributes } => {
527                let data = Box::new((*data).extract_error()?);
528                let attributes = Self::extract_error_map(attributes)?;
529                Ok(Value::Attribute { data, attributes })
530            }
531            Self::Set(set) => Ok(Self::Set(Self::extract_error_vec(set)?)),
532            Self::Push { kind, data } => Ok(Self::Push {
533                kind,
534                data: Self::extract_error_vec(data)?,
535            }),
536            Value::ServerError(err) => Err(err.into()),
537            _ => Ok(self),
538        }
539    }
540
541    pub(crate) fn extract_error_vec(vec: Vec<Self>) -> RedisResult<Vec<Self>> {
542        vec.into_iter()
543            .map(Self::extract_error)
544            .collect::<RedisResult<Vec<_>>>()
545    }
546
547    pub(crate) fn extract_error_map(map: Vec<(Self, Self)>) -> RedisResult<Vec<(Self, Self)>> {
548        let mut vec = Vec::with_capacity(map.len());
549        for (key, value) in map.into_iter() {
550            vec.push((key.extract_error()?, value.extract_error()?));
551        }
552        Ok(vec)
553    }
554
555    fn is_collection_of_len(&self, len: usize) -> bool {
556        match self {
557            Value::Array(values) => values.len() == len,
558            Value::Map(items) => items.len() * 2 == len,
559            Value::Set(values) => values.len() == len,
560            _ => false,
561        }
562    }
563}
564
565impl fmt::Debug for Value {
566    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
567        match *self {
568            Value::Nil => write!(fmt, "nil"),
569            Value::Int(val) => write!(fmt, "int({val:?})"),
570            Value::BulkString(ref val) => match from_utf8(val) {
571                Ok(x) => write!(fmt, "bulk-string('{x:?}')"),
572                Err(_) => write!(fmt, "binary-data({val:?})"),
573            },
574            Value::Array(ref values) => write!(fmt, "array({values:?})"),
575            Value::Push { ref kind, ref data } => write!(fmt, "push({kind:?}, {data:?})"),
576            Value::Okay => write!(fmt, "ok"),
577            Value::SimpleString(ref s) => write!(fmt, "simple-string({s:?})"),
578            Value::Map(ref values) => write!(fmt, "map({values:?})"),
579            Value::Attribute {
580                ref data,
581                attributes: _,
582            } => write!(fmt, "attribute({data:?})"),
583            Value::Set(ref values) => write!(fmt, "set({values:?})"),
584            Value::Double(ref d) => write!(fmt, "double({d:?})"),
585            Value::Boolean(ref b) => write!(fmt, "boolean({b:?})"),
586            Value::VerbatimString {
587                ref format,
588                ref text,
589            } => {
590                write!(fmt, "verbatim-string({format:?},{text:?})")
591            }
592            Value::BigNumber(ref m) => write!(fmt, "big-number({m:?})"),
593            Value::ServerError(ref err) => match err.details() {
594                Some(details) => write!(fmt, "Server error: `{}: {details}`", err.code()),
595                None => write!(fmt, "Server error: `{}`", err.code()),
596            },
597        }
598    }
599}
600
601/// Represents a redis error.
602///
603/// For the most part you should be using the Error trait to interact with this
604/// rather than the actual struct.
605pub struct RedisError {
606    repr: ErrorRepr,
607}
608
609#[cfg(feature = "json")]
610impl From<serde_json::Error> for RedisError {
611    fn from(serde_err: serde_json::Error) -> RedisError {
612        RedisError::from((
613            ErrorKind::Serialize,
614            "Serialization Error",
615            format!("{serde_err}"),
616        ))
617    }
618}
619
620#[derive(Debug)]
621enum ErrorRepr {
622    WithDescription(ErrorKind, &'static str),
623    WithDescriptionAndDetail(ErrorKind, &'static str, String),
624    ExtensionError(String, String),
625    IoError(io::Error),
626}
627
628impl PartialEq for RedisError {
629    fn eq(&self, other: &RedisError) -> bool {
630        match (&self.repr, &other.repr) {
631            (&ErrorRepr::WithDescription(kind_a, _), &ErrorRepr::WithDescription(kind_b, _)) => {
632                kind_a == kind_b
633            }
634            (
635                &ErrorRepr::WithDescriptionAndDetail(kind_a, _, _),
636                &ErrorRepr::WithDescriptionAndDetail(kind_b, _, _),
637            ) => kind_a == kind_b,
638            (ErrorRepr::ExtensionError(a, _), ErrorRepr::ExtensionError(b, _)) => *a == *b,
639            _ => false,
640        }
641    }
642}
643
644impl From<io::Error> for RedisError {
645    fn from(err: io::Error) -> RedisError {
646        RedisError {
647            repr: ErrorRepr::IoError(err),
648        }
649    }
650}
651
652impl From<Utf8Error> for RedisError {
653    fn from(_: Utf8Error) -> RedisError {
654        RedisError {
655            repr: ErrorRepr::WithDescription(ErrorKind::TypeError, "Invalid UTF-8"),
656        }
657    }
658}
659
660impl From<NulError> for RedisError {
661    fn from(err: NulError) -> RedisError {
662        RedisError {
663            repr: ErrorRepr::WithDescriptionAndDetail(
664                ErrorKind::TypeError,
665                "Value contains interior nul terminator",
666                err.to_string(),
667            ),
668        }
669    }
670}
671
672#[cfg(feature = "tls-native-tls")]
673impl From<native_tls::Error> for RedisError {
674    fn from(err: native_tls::Error) -> RedisError {
675        RedisError {
676            repr: ErrorRepr::WithDescriptionAndDetail(
677                ErrorKind::IoError,
678                "TLS error",
679                err.to_string(),
680            ),
681        }
682    }
683}
684
685#[cfg(feature = "tls-rustls")]
686impl From<rustls::Error> for RedisError {
687    fn from(err: rustls::Error) -> RedisError {
688        RedisError {
689            repr: ErrorRepr::WithDescriptionAndDetail(
690                ErrorKind::IoError,
691                "TLS error",
692                err.to_string(),
693            ),
694        }
695    }
696}
697
698#[cfg(feature = "tls-rustls")]
699impl From<rustls::pki_types::InvalidDnsNameError> for RedisError {
700    fn from(err: rustls::pki_types::InvalidDnsNameError) -> RedisError {
701        RedisError {
702            repr: ErrorRepr::WithDescriptionAndDetail(
703                ErrorKind::IoError,
704                "TLS Error",
705                err.to_string(),
706            ),
707        }
708    }
709}
710
711#[cfg(feature = "tls-rustls")]
712impl From<rustls_native_certs::Error> for RedisError {
713    fn from(err: rustls_native_certs::Error) -> RedisError {
714        RedisError {
715            repr: ErrorRepr::WithDescriptionAndDetail(
716                ErrorKind::IoError,
717                "Fetch certs Error",
718                err.to_string(),
719            ),
720        }
721    }
722}
723
724#[cfg(feature = "uuid")]
725impl From<uuid::Error> for RedisError {
726    fn from(err: uuid::Error) -> RedisError {
727        RedisError {
728            repr: ErrorRepr::WithDescriptionAndDetail(
729                ErrorKind::TypeError,
730                "Value is not a valid UUID",
731                err.to_string(),
732            ),
733        }
734    }
735}
736
737impl From<FromUtf8Error> for RedisError {
738    fn from(_: FromUtf8Error) -> RedisError {
739        RedisError {
740            repr: ErrorRepr::WithDescription(ErrorKind::TypeError, "Cannot convert from UTF-8"),
741        }
742    }
743}
744
745impl From<(ErrorKind, &'static str)> for RedisError {
746    fn from((kind, desc): (ErrorKind, &'static str)) -> RedisError {
747        RedisError {
748            repr: ErrorRepr::WithDescription(kind, desc),
749        }
750    }
751}
752
753impl From<(ErrorKind, &'static str, String)> for RedisError {
754    fn from((kind, desc, detail): (ErrorKind, &'static str, String)) -> RedisError {
755        RedisError {
756            repr: ErrorRepr::WithDescriptionAndDetail(kind, desc, detail),
757        }
758    }
759}
760
761impl error::Error for RedisError {
762    #[allow(deprecated)]
763    fn description(&self) -> &str {
764        match self.repr {
765            ErrorRepr::WithDescription(_, desc) => desc,
766            ErrorRepr::WithDescriptionAndDetail(_, desc, _) => desc,
767            ErrorRepr::ExtensionError(_, _) => "extension error",
768            ErrorRepr::IoError(ref err) => err.description(),
769        }
770    }
771
772    fn cause(&self) -> Option<&dyn error::Error> {
773        match self.repr {
774            ErrorRepr::IoError(ref err) => Some(err as &dyn error::Error),
775            _ => None,
776        }
777    }
778
779    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
780        match self.repr {
781            ErrorRepr::IoError(ref err) => Some(err),
782            _ => None,
783        }
784    }
785}
786
787impl fmt::Display for RedisError {
788    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
789        match self.repr {
790            ErrorRepr::WithDescription(kind, desc) => {
791                desc.fmt(f)?;
792                f.write_str("- ")?;
793                fmt::Debug::fmt(&kind, f)
794            }
795            ErrorRepr::WithDescriptionAndDetail(kind, desc, ref detail) => {
796                desc.fmt(f)?;
797                f.write_str(" - ")?;
798                fmt::Debug::fmt(&kind, f)?;
799                f.write_str(": ")?;
800                detail.fmt(f)
801            }
802            ErrorRepr::ExtensionError(ref code, ref detail) => {
803                code.fmt(f)?;
804                f.write_str(": ")?;
805                detail.fmt(f)
806            }
807            ErrorRepr::IoError(ref err) => err.fmt(f),
808        }
809    }
810}
811
812impl fmt::Debug for RedisError {
813    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
814        fmt::Display::fmt(self, f)
815    }
816}
817
818/// What method should be used if retrying this request.
819#[non_exhaustive]
820pub enum RetryMethod {
821    /// Create a fresh connection, since the current connection is no longer usable.
822    Reconnect,
823    /// Don't retry, this is a permanent error.
824    NoRetry,
825    /// Retry immediately, this doesn't require a wait.
826    RetryImmediately,
827    /// Retry after sleeping to avoid overloading the external service.
828    WaitAndRetry,
829    /// The key has moved to a different node but we have to ask which node, this is only relevant for clusters.
830    AskRedirect,
831    /// The key has moved to a different node, this is only relevant for clusters.
832    MovedRedirect,
833    /// Reconnect the initial connection to the master cluster, this is only relevant for clusters.
834    ReconnectFromInitialConnections,
835}
836
837/// Indicates a general failure in the library.
838impl RedisError {
839    /// Returns the kind of the error.
840    pub fn kind(&self) -> ErrorKind {
841        match self.repr {
842            ErrorRepr::WithDescription(kind, _)
843            | ErrorRepr::WithDescriptionAndDetail(kind, _, _) => kind,
844            ErrorRepr::ExtensionError(_, _) => ErrorKind::ExtensionError,
845            ErrorRepr::IoError(_) => ErrorKind::IoError,
846        }
847    }
848
849    /// Returns the error detail.
850    pub fn detail(&self) -> Option<&str> {
851        match self.repr {
852            ErrorRepr::WithDescriptionAndDetail(_, _, ref detail)
853            | ErrorRepr::ExtensionError(_, ref detail) => Some(detail.as_str()),
854            _ => None,
855        }
856    }
857
858    /// Returns the raw error code if available.
859    pub fn code(&self) -> Option<&str> {
860        match self.kind() {
861            ErrorKind::ResponseError => Some("ERR"),
862            ErrorKind::ExecAbortError => Some("EXECABORT"),
863            ErrorKind::BusyLoadingError => Some("LOADING"),
864            ErrorKind::NoScriptError => Some("NOSCRIPT"),
865            ErrorKind::Moved => Some("MOVED"),
866            ErrorKind::Ask => Some("ASK"),
867            ErrorKind::TryAgain => Some("TRYAGAIN"),
868            ErrorKind::ClusterDown => Some("CLUSTERDOWN"),
869            ErrorKind::CrossSlot => Some("CROSSSLOT"),
870            ErrorKind::MasterDown => Some("MASTERDOWN"),
871            ErrorKind::ReadOnly => Some("READONLY"),
872            ErrorKind::NotBusy => Some("NOTBUSY"),
873            _ => match self.repr {
874                ErrorRepr::ExtensionError(ref code, _) => Some(code),
875                _ => None,
876            },
877        }
878    }
879
880    /// Returns the name of the error category for display purposes.
881    pub fn category(&self) -> &str {
882        match self.kind() {
883            ErrorKind::ResponseError => "response error",
884            ErrorKind::AuthenticationFailed => "authentication failed",
885            ErrorKind::TypeError => "type error",
886            ErrorKind::ExecAbortError => "script execution aborted",
887            ErrorKind::BusyLoadingError => "busy loading",
888            ErrorKind::NoScriptError => "no script",
889            ErrorKind::InvalidClientConfig => "invalid client config",
890            ErrorKind::Moved => "key moved",
891            ErrorKind::Ask => "key moved (ask)",
892            ErrorKind::TryAgain => "try again",
893            ErrorKind::ClusterDown => "cluster down",
894            ErrorKind::CrossSlot => "cross-slot",
895            ErrorKind::MasterDown => "master down",
896            ErrorKind::IoError => "I/O error",
897            ErrorKind::ExtensionError => "extension error",
898            ErrorKind::ClientError => "client error",
899            ErrorKind::ReadOnly => "read-only",
900            ErrorKind::MasterNameNotFoundBySentinel => "master name not found by sentinel",
901            ErrorKind::NoValidReplicasFoundBySentinel => "no valid replicas found by sentinel",
902            ErrorKind::EmptySentinelList => "empty sentinel list",
903            ErrorKind::NotBusy => "not busy",
904            ErrorKind::ClusterConnectionNotFound => "connection to node in cluster not found",
905            #[cfg(feature = "json")]
906            ErrorKind::Serialize => "serializing",
907            ErrorKind::RESP3NotSupported => "resp3 is not supported by server",
908            ErrorKind::ParseError => "parse error",
909            ErrorKind::NoSub => {
910                "Server declined unsubscribe related command in non-subscribed mode"
911            }
912        }
913    }
914
915    /// Indicates that this failure is an IO failure.
916    pub fn is_io_error(&self) -> bool {
917        self.kind() == ErrorKind::IoError
918    }
919
920    pub(crate) fn as_io_error(&self) -> Option<&io::Error> {
921        match &self.repr {
922            ErrorRepr::IoError(e) => Some(e),
923            _ => None,
924        }
925    }
926
927    /// Indicates that this is a cluster error.
928    pub fn is_cluster_error(&self) -> bool {
929        matches!(
930            self.kind(),
931            ErrorKind::Moved | ErrorKind::Ask | ErrorKind::TryAgain | ErrorKind::ClusterDown
932        )
933    }
934
935    /// Returns true if this error indicates that the connection was
936    /// refused.  You should generally not rely much on this function
937    /// unless you are writing unit tests that want to detect if a
938    /// local server is available.
939    pub fn is_connection_refusal(&self) -> bool {
940        match self.repr {
941            ErrorRepr::IoError(ref err) => {
942                #[allow(clippy::match_like_matches_macro)]
943                match err.kind() {
944                    io::ErrorKind::ConnectionRefused => true,
945                    // if we connect to a unix socket and the file does not
946                    // exist yet, then we want to treat this as if it was a
947                    // connection refusal.
948                    io::ErrorKind::NotFound => cfg!(unix),
949                    _ => false,
950                }
951            }
952            _ => false,
953        }
954    }
955
956    /// Returns true if error was caused by I/O time out.
957    /// Note that this may not be accurate depending on platform.
958    pub fn is_timeout(&self) -> bool {
959        match self.repr {
960            ErrorRepr::IoError(ref err) => matches!(
961                err.kind(),
962                io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock
963            ),
964            _ => false,
965        }
966    }
967
968    /// Returns true if error was caused by a dropped connection.
969    pub fn is_connection_dropped(&self) -> bool {
970        match self.repr {
971            ErrorRepr::IoError(ref err) => matches!(
972                err.kind(),
973                io::ErrorKind::BrokenPipe
974                    | io::ErrorKind::ConnectionReset
975                    | io::ErrorKind::UnexpectedEof
976            ),
977            _ => false,
978        }
979    }
980
981    /// Returns true if the error is likely to not be recoverable, and the connection must be replaced.
982    pub fn is_unrecoverable_error(&self) -> bool {
983        match self.retry_method() {
984            RetryMethod::Reconnect => true,
985            RetryMethod::ReconnectFromInitialConnections => true,
986
987            RetryMethod::NoRetry => false,
988            RetryMethod::RetryImmediately => false,
989            RetryMethod::WaitAndRetry => false,
990            RetryMethod::AskRedirect => false,
991            RetryMethod::MovedRedirect => false,
992        }
993    }
994
995    /// Returns the node the error refers to.
996    ///
997    /// This returns `(addr, slot_id)`.
998    pub fn redirect_node(&self) -> Option<(&str, u16)> {
999        match self.kind() {
1000            ErrorKind::Ask | ErrorKind::Moved => (),
1001            _ => return None,
1002        }
1003        let mut iter = self.detail()?.split_ascii_whitespace();
1004        let slot_id: u16 = iter.next()?.parse().ok()?;
1005        let addr = iter.next()?;
1006        Some((addr, slot_id))
1007    }
1008
1009    /// Returns the extension error code.
1010    ///
1011    /// This method should not be used because every time the redis library
1012    /// adds support for a new error code it would disappear form this method.
1013    /// `code()` always returns the code.
1014    #[deprecated(note = "use code() instead")]
1015    pub fn extension_error_code(&self) -> Option<&str> {
1016        match self.repr {
1017            ErrorRepr::ExtensionError(ref code, _) => Some(code),
1018            _ => None,
1019        }
1020    }
1021
1022    /// Clone the `RedisError`, throwing away non-cloneable parts of an `IoError`.
1023    ///
1024    /// Deriving `Clone` is not possible because the wrapped `io::Error` is not
1025    /// cloneable.
1026    ///
1027    /// The `ioerror_description` parameter will be prepended to the message in
1028    /// case an `IoError` is found.
1029    #[cfg(feature = "connection-manager")] // Used to avoid "unused method" warning
1030    pub(crate) fn clone_mostly(&self, ioerror_description: &'static str) -> Self {
1031        let repr = match self.repr {
1032            ErrorRepr::WithDescription(kind, desc) => ErrorRepr::WithDescription(kind, desc),
1033            ErrorRepr::WithDescriptionAndDetail(kind, desc, ref detail) => {
1034                ErrorRepr::WithDescriptionAndDetail(kind, desc, detail.clone())
1035            }
1036            ErrorRepr::ExtensionError(ref code, ref detail) => {
1037                ErrorRepr::ExtensionError(code.clone(), detail.clone())
1038            }
1039            ErrorRepr::IoError(ref e) => ErrorRepr::IoError(io::Error::new(
1040                e.kind(),
1041                format!("{ioerror_description}: {e}"),
1042            )),
1043        };
1044        Self { repr }
1045    }
1046
1047    /// Specifies what method (if any) should be used to retry this request.
1048    ///
1049    /// If you are using the cluster api retrying of requests is already handled by the library.
1050    ///
1051    /// This isn't precise, and internally the library uses multiple other considerations rather
1052    /// than just the error kind on when to retry.
1053    pub fn retry_method(&self) -> RetryMethod {
1054        match self.kind() {
1055            ErrorKind::Moved => RetryMethod::MovedRedirect,
1056            ErrorKind::Ask => RetryMethod::AskRedirect,
1057
1058            ErrorKind::TryAgain => RetryMethod::WaitAndRetry,
1059            ErrorKind::MasterDown => RetryMethod::WaitAndRetry,
1060            ErrorKind::ClusterDown => RetryMethod::WaitAndRetry,
1061            ErrorKind::BusyLoadingError => RetryMethod::WaitAndRetry,
1062            ErrorKind::MasterNameNotFoundBySentinel => RetryMethod::WaitAndRetry,
1063            ErrorKind::NoValidReplicasFoundBySentinel => RetryMethod::WaitAndRetry,
1064
1065            ErrorKind::ResponseError => RetryMethod::NoRetry,
1066            ErrorKind::ReadOnly => RetryMethod::NoRetry,
1067            ErrorKind::ExtensionError => RetryMethod::NoRetry,
1068            ErrorKind::ExecAbortError => RetryMethod::NoRetry,
1069            ErrorKind::TypeError => RetryMethod::NoRetry,
1070            ErrorKind::NoScriptError => RetryMethod::NoRetry,
1071            ErrorKind::InvalidClientConfig => RetryMethod::NoRetry,
1072            ErrorKind::CrossSlot => RetryMethod::NoRetry,
1073            ErrorKind::ClientError => RetryMethod::NoRetry,
1074            ErrorKind::EmptySentinelList => RetryMethod::NoRetry,
1075            ErrorKind::NotBusy => RetryMethod::NoRetry,
1076            #[cfg(feature = "json")]
1077            ErrorKind::Serialize => RetryMethod::NoRetry,
1078            ErrorKind::RESP3NotSupported => RetryMethod::NoRetry,
1079            ErrorKind::NoSub => RetryMethod::NoRetry,
1080
1081            ErrorKind::ParseError => RetryMethod::Reconnect,
1082            ErrorKind::AuthenticationFailed => RetryMethod::Reconnect,
1083            ErrorKind::ClusterConnectionNotFound => RetryMethod::ReconnectFromInitialConnections,
1084
1085            ErrorKind::IoError => match &self.repr {
1086                ErrorRepr::IoError(err) => match err.kind() {
1087                    io::ErrorKind::ConnectionRefused => RetryMethod::Reconnect,
1088                    io::ErrorKind::NotFound => RetryMethod::Reconnect,
1089                    io::ErrorKind::ConnectionReset => RetryMethod::Reconnect,
1090                    io::ErrorKind::ConnectionAborted => RetryMethod::Reconnect,
1091                    io::ErrorKind::NotConnected => RetryMethod::Reconnect,
1092                    io::ErrorKind::BrokenPipe => RetryMethod::Reconnect,
1093                    io::ErrorKind::UnexpectedEof => RetryMethod::Reconnect,
1094
1095                    io::ErrorKind::PermissionDenied => RetryMethod::NoRetry,
1096                    io::ErrorKind::Unsupported => RetryMethod::NoRetry,
1097
1098                    _ => RetryMethod::RetryImmediately,
1099                },
1100                _ => RetryMethod::RetryImmediately,
1101            },
1102        }
1103    }
1104}
1105
1106/// Creates a new Redis error with the `ExtensionError` kind.
1107///
1108/// This function is used to create Redis errors for extension error codes
1109/// that are not directly understood by the library.
1110///
1111/// # Arguments
1112///
1113/// * `code` - The error code string returned by the Redis server
1114/// * `detail` - Optional detailed error message. If None, a default message is used.
1115///
1116/// # Returns
1117///
1118/// A `RedisError` with the `ExtensionError` kind.
1119pub fn make_extension_error(code: String, detail: Option<String>) -> RedisError {
1120    RedisError {
1121        repr: ErrorRepr::ExtensionError(
1122            code,
1123            match detail {
1124                Some(x) => x,
1125                None => "Unknown extension error encountered".to_string(),
1126            },
1127        ),
1128    }
1129}
1130
1131/// Library generic result type.
1132pub type RedisResult<T> = Result<T, RedisError>;
1133
1134/// Library generic future type.
1135#[cfg(feature = "aio")]
1136pub type RedisFuture<'a, T> = futures_util::future::BoxFuture<'a, RedisResult<T>>;
1137
1138/// An info dictionary type.
1139#[derive(Debug, Clone)]
1140pub struct InfoDict {
1141    map: HashMap<String, Value>,
1142}
1143
1144/// This type provides convenient access to key/value data returned by
1145/// the "INFO" command.  It acts like a regular mapping but also has
1146/// a convenience method `get` which can return data in the appropriate
1147/// type.
1148///
1149/// For instance this can be used to query the server for the role it's
1150/// in (master, slave) etc:
1151///
1152/// ```rust,no_run
1153/// # fn do_something() -> redis::RedisResult<()> {
1154/// # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
1155/// # let mut con = client.get_connection().unwrap();
1156/// let info : redis::InfoDict = redis::cmd("INFO").query(&mut con)?;
1157/// let role : Option<String> = info.get("role");
1158/// # Ok(()) }
1159/// ```
1160impl InfoDict {
1161    /// Creates a new info dictionary from a string in the response of
1162    /// the INFO command.  Each line is a key, value pair with the
1163    /// key and value separated by a colon (`:`).  Lines starting with a
1164    /// hash (`#`) are ignored.
1165    pub fn new(kvpairs: &str) -> InfoDict {
1166        let mut map = HashMap::new();
1167        for line in kvpairs.lines() {
1168            if line.is_empty() || line.starts_with('#') {
1169                continue;
1170            }
1171            let mut p = line.splitn(2, ':');
1172            let (k, v) = match (p.next(), p.next()) {
1173                (Some(k), Some(v)) => (k.to_string(), v.to_string()),
1174                _ => continue,
1175            };
1176            map.insert(k, Value::SimpleString(v));
1177        }
1178        InfoDict { map }
1179    }
1180
1181    /// Fetches a value by key and converts it into the given type.
1182    /// Typical types are `String`, `bool` and integer types.
1183    pub fn get<T: FromRedisValue>(&self, key: &str) -> Option<T> {
1184        match self.find(&key) {
1185            Some(x) => from_redis_value(x).ok(),
1186            None => None,
1187        }
1188    }
1189
1190    /// Looks up a key in the info dict.
1191    pub fn find(&self, key: &&str) -> Option<&Value> {
1192        self.map.get(*key)
1193    }
1194
1195    /// Checks if a key is contained in the info dicf.
1196    pub fn contains_key(&self, key: &&str) -> bool {
1197        self.find(key).is_some()
1198    }
1199
1200    /// Returns the size of the info dict.
1201    pub fn len(&self) -> usize {
1202        self.map.len()
1203    }
1204
1205    /// Checks if the dict is empty.
1206    pub fn is_empty(&self) -> bool {
1207        self.map.is_empty()
1208    }
1209}
1210
1211impl Deref for InfoDict {
1212    type Target = HashMap<String, Value>;
1213
1214    fn deref(&self) -> &Self::Target {
1215        &self.map
1216    }
1217}
1218
1219/// High level representation of response to the [`ROLE`][1] command.
1220///
1221/// [1]: https://redis.io/docs/latest/commands/role/
1222#[derive(Debug, Clone, Eq, PartialEq)]
1223pub enum Role {
1224    /// Represents a primary role, which is `master` in legacy Redis terminology.
1225    Primary {
1226        /// The current primary replication offset
1227        replication_offset: u64,
1228        /// List of replica, each represented by a tuple of IP, port and the last acknowledged replication offset.
1229        replicas: Vec<ReplicaInfo>,
1230    },
1231    /// Represents a replica role, which is `slave` in legacy Redis terminology.
1232    Replica {
1233        /// The IP of the primary.
1234        primary_ip: String,
1235        /// The port of the primary.
1236        primary_port: u16,
1237        /// The state of the replication from the point of view of the primary.
1238        replication_state: String,
1239        /// The amount of data received from the replica so far in terms of primary replication offset.
1240        data_received: u64,
1241    },
1242    /// Represents a sentinel role.
1243    Sentinel {
1244        /// List of primary names monitored by this Sentinel instance.
1245        primary_names: Vec<String>,
1246    },
1247}
1248
1249/// Replication information for a replica, as returned by the [`ROLE`][1] command.
1250///
1251/// [1]: https://redis.io/docs/latest/commands/role/
1252#[derive(Debug, Clone, Eq, PartialEq)]
1253pub struct ReplicaInfo {
1254    /// The IP of the replica.
1255    pub ip: String,
1256    /// The port of the replica.
1257    pub port: u16,
1258    /// The last acknowledged replication offset.
1259    pub replication_offset: i64,
1260}
1261
1262impl FromRedisValue for ReplicaInfo {
1263    fn from_redis_value(v: &Value) -> RedisResult<Self> {
1264        Self::from_owned_redis_value(v.clone())
1265    }
1266
1267    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
1268        let v = match get_owned_inner_value(v).into_sequence() {
1269            Ok(v) => v,
1270            Err(v) => invalid_type_error!(v, "Replica response should be an array"),
1271        };
1272        if v.len() < 3 {
1273            invalid_type_error!(v, "Replica array is too short, expected 3 elements")
1274        }
1275        let mut v = v.into_iter();
1276        let ip = from_owned_redis_value(v.next().expect("len was checked"))?;
1277        let port = from_owned_redis_value(v.next().expect("len was checked"))?;
1278        let offset = from_owned_redis_value(v.next().expect("len was checked"))?;
1279        Ok(ReplicaInfo {
1280            ip,
1281            port,
1282            replication_offset: offset,
1283        })
1284    }
1285}
1286
1287impl FromRedisValue for Role {
1288    fn from_redis_value(v: &Value) -> RedisResult<Self> {
1289        Self::from_owned_redis_value(v.clone())
1290    }
1291
1292    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
1293        let v = match get_owned_inner_value(v).into_sequence() {
1294            Ok(v) => v,
1295            Err(v) => invalid_type_error!(v, "Role response should be an array"),
1296        };
1297        if v.len() < 2 {
1298            invalid_type_error!(v, "Role array is too short, expected at least 2 elements")
1299        }
1300        match &v[0] {
1301            Value::BulkString(role) => match role.as_slice() {
1302                b"master" => Role::new_primary(v),
1303                b"slave" => Role::new_replica(v),
1304                b"sentinel" => Role::new_sentinel(v),
1305                _ => invalid_type_error!(v, "Role type is not master, slave or sentinel"),
1306            },
1307            _ => invalid_type_error!(v, "Role type is not a bulk string"),
1308        }
1309    }
1310}
1311
1312impl Role {
1313    fn new_primary(values: Vec<Value>) -> RedisResult<Self> {
1314        if values.len() < 3 {
1315            invalid_type_error!(
1316                values,
1317                "Role primary response too short, expected 3 elements"
1318            )
1319        }
1320
1321        let mut values = values.into_iter();
1322        _ = values.next();
1323
1324        let replication_offset = from_owned_redis_value(values.next().expect("len was checked"))?;
1325        let replicas = from_owned_redis_value(values.next().expect("len was checked"))?;
1326
1327        Ok(Role::Primary {
1328            replication_offset,
1329            replicas,
1330        })
1331    }
1332
1333    fn new_replica(values: Vec<Value>) -> RedisResult<Self> {
1334        if values.len() < 5 {
1335            invalid_type_error!(
1336                values,
1337                "Role replica response too short, expected 5 elements"
1338            )
1339        }
1340
1341        let mut values = values.into_iter();
1342        _ = values.next();
1343
1344        let primary_ip = from_owned_redis_value(values.next().expect("len was checked"))?;
1345        let primary_port = from_owned_redis_value(values.next().expect("len was checked"))?;
1346        let replication_state = from_owned_redis_value(values.next().expect("len was checked"))?;
1347        let data_received = from_owned_redis_value(values.next().expect("len was checked"))?;
1348
1349        Ok(Role::Replica {
1350            primary_ip,
1351            primary_port,
1352            replication_state,
1353            data_received,
1354        })
1355    }
1356
1357    fn new_sentinel(values: Vec<Value>) -> RedisResult<Self> {
1358        if values.len() < 2 {
1359            invalid_type_error!(
1360                values,
1361                "Role sentinel response too short, expected at least 2 elements"
1362            )
1363        }
1364        let second_val = values.into_iter().nth(1).expect("len was checked");
1365        let primary_names = from_owned_redis_value(second_val)?;
1366        Ok(Role::Sentinel { primary_names })
1367    }
1368}
1369
1370/// Abstraction trait for redis command abstractions.
1371pub trait RedisWrite {
1372    /// Accepts a serialized redis command.
1373    fn write_arg(&mut self, arg: &[u8]);
1374
1375    /// Accepts a serialized redis command.
1376    fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
1377        self.write_arg(arg.to_string().as_bytes())
1378    }
1379
1380    /// Appends an empty argument to the command, and returns a
1381    /// [`std::io::Write`] instance that can write to it.
1382    ///
1383    /// Writing multiple arguments into this buffer is unsupported. The resulting
1384    /// data will be interpreted as one argument by Redis.
1385    ///
1386    /// Writing no data is supported and is similar to having an empty bytestring
1387    /// as an argument.
1388    fn writer_for_next_arg(&mut self) -> impl std::io::Write + '_;
1389
1390    /// Reserve space for `additional` arguments in the command
1391    ///
1392    /// `additional` is a list of the byte sizes of the arguments.
1393    ///
1394    /// # Examples
1395    /// Sending some Protobufs with `prost` to Redis.
1396    /// ```rust,ignore
1397    /// use prost::Message;
1398    ///
1399    /// let to_send: Vec<SomeType> = todo!();
1400    /// let mut cmd = Cmd::new();
1401    ///
1402    /// // Calculate and reserve the space for the args
1403    /// cmd.reserve_space_for_args(to_send.iter().map(Message::encoded_len));
1404    ///
1405    /// // Write the args to the buffer
1406    /// for arg in to_send {
1407    ///     // Encode the type directly into the Cmd buffer
1408    ///     // Supplying the required capacity again is not needed for Cmd,
1409    ///     // but can be useful for other implementers like Vec<Vec<u8>>.
1410    ///     arg.encode(cmd.bufmut_for_next_arg(arg.encoded_len()));
1411    /// }
1412    ///
1413    /// ```
1414    ///
1415    /// # Implementation note
1416    /// The default implementation provided by this trait is a no-op. It's therefore strongly
1417    /// recommended to implement this function. Depending on the internal buffer it might only
1418    /// be possible to use the numbers of arguments (`additional.len()`) or the total expected
1419    /// capacity (`additional.iter().sum()`). Implementors should assume that the caller will
1420    /// be wrong and might over or under specify the amount of arguments and space required.
1421    fn reserve_space_for_args(&mut self, additional: impl IntoIterator<Item = usize>) {
1422        // _additional would show up in the documentation, so we assign it
1423        // to make it used.
1424        let _do_nothing = additional;
1425    }
1426
1427    #[cfg(feature = "bytes")]
1428    /// Appends an empty argument to the command, and returns a
1429    /// [`bytes::BufMut`] instance that can write to it.
1430    ///
1431    /// `capacity` should be equal or greater to the amount of bytes
1432    /// expected, as some implementations might not be able to resize
1433    /// the returned buffer.
1434    ///
1435    /// Writing multiple arguments into this buffer is unsupported. The resulting
1436    /// data will be interpreted as one argument by Redis.
1437    ///
1438    /// Writing no data is supported and is similar to having an empty bytestring
1439    /// as an argument.
1440    fn bufmut_for_next_arg(&mut self, capacity: usize) -> impl bytes::BufMut + '_ {
1441        // This default implementation is not the most efficient, but does
1442        // allow for implementers to skip this function. This means that
1443        // upstream libraries that implement this trait don't suddenly
1444        // stop working because someone enabled one of the async features.
1445
1446        /// Has a temporary buffer that is written to [`writer_for_next_arg`]
1447        /// on drop.
1448        struct Wrapper<'a> {
1449            /// The buffer, implements [`bytes::BufMut`] allowing passthrough
1450            buf: Vec<u8>,
1451            /// The writer to the command, used on drop
1452            writer: Box<dyn std::io::Write + 'a>,
1453        }
1454        unsafe impl bytes::BufMut for Wrapper<'_> {
1455            fn remaining_mut(&self) -> usize {
1456                self.buf.remaining_mut()
1457            }
1458
1459            unsafe fn advance_mut(&mut self, cnt: usize) {
1460                self.buf.advance_mut(cnt);
1461            }
1462
1463            fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
1464                self.buf.chunk_mut()
1465            }
1466
1467            // Vec specializes these methods, so we do too
1468            fn put<T: bytes::buf::Buf>(&mut self, src: T)
1469            where
1470                Self: Sized,
1471            {
1472                self.buf.put(src);
1473            }
1474
1475            fn put_slice(&mut self, src: &[u8]) {
1476                self.buf.put_slice(src);
1477            }
1478
1479            fn put_bytes(&mut self, val: u8, cnt: usize) {
1480                self.buf.put_bytes(val, cnt);
1481            }
1482        }
1483        impl Drop for Wrapper<'_> {
1484            fn drop(&mut self) {
1485                self.writer.write_all(&self.buf).unwrap()
1486            }
1487        }
1488
1489        Wrapper {
1490            buf: Vec::with_capacity(capacity),
1491            writer: Box::new(self.writer_for_next_arg()),
1492        }
1493    }
1494}
1495
1496impl RedisWrite for Vec<Vec<u8>> {
1497    fn write_arg(&mut self, arg: &[u8]) {
1498        self.push(arg.to_owned());
1499    }
1500
1501    fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
1502        self.push(arg.to_string().into_bytes())
1503    }
1504
1505    fn writer_for_next_arg(&mut self) -> impl std::io::Write + '_ {
1506        self.push(Vec::new());
1507        self.last_mut().unwrap()
1508    }
1509
1510    fn reserve_space_for_args(&mut self, additional: impl IntoIterator<Item = usize>) {
1511        // It would be nice to do this, but there's no way to store where we currently are.
1512        // Checking for the first empty Vec is not possible, as it's valid to write empty args.
1513        // self.extend(additional.iter().copied().map(Vec::with_capacity));
1514        // So we just reserve space for the extra args and have to forgo the extra optimisation
1515        self.reserve(additional.into_iter().count());
1516    }
1517
1518    #[cfg(feature = "bytes")]
1519    fn bufmut_for_next_arg(&mut self, capacity: usize) -> impl bytes::BufMut + '_ {
1520        self.push(Vec::with_capacity(capacity));
1521        self.last_mut().unwrap()
1522    }
1523}
1524
1525/// Used to convert a value into one or multiple redis argument
1526/// strings.  Most values will produce exactly one item but in
1527/// some cases it might make sense to produce more than one.
1528pub trait ToRedisArgs: Sized {
1529    /// This converts the value into a vector of bytes.  Each item
1530    /// is a single argument.  Most items generate a vector of a
1531    /// single item.
1532    ///
1533    /// The exception to this rule currently are vectors of items.
1534    fn to_redis_args(&self) -> Vec<Vec<u8>> {
1535        let mut out = Vec::new();
1536        self.write_redis_args(&mut out);
1537        out
1538    }
1539
1540    /// This writes the value into a vector of bytes.  Each item
1541    /// is a single argument.  Most items generate a single item.
1542    ///
1543    /// The exception to this rule currently are vectors of items.
1544    fn write_redis_args<W>(&self, out: &mut W)
1545    where
1546        W: ?Sized + RedisWrite;
1547
1548    /// Returns an information about the contained value with regards
1549    /// to it's numeric behavior in a redis context.  This is used in
1550    /// some high level concepts to switch between different implementations
1551    /// of redis functions (for instance `INCR` vs `INCRBYFLOAT`).
1552    fn describe_numeric_behavior(&self) -> NumericBehavior {
1553        NumericBehavior::NonNumeric
1554    }
1555
1556    /// Returns the number of arguments this value will generate.
1557    ///
1558    /// This is used in some high level functions to intelligently switch
1559    /// between `GET` and `MGET` variants. Also, for some commands like HEXPIREDAT
1560    /// which require a specific number of arguments, this method can be used to
1561    /// know the number of arguments.
1562    fn num_of_args(&self) -> usize {
1563        1
1564    }
1565
1566    /// This only exists internally as a workaround for the lack of
1567    /// specialization.
1568    #[doc(hidden)]
1569    fn write_args_from_slice<W>(items: &[Self], out: &mut W)
1570    where
1571        W: ?Sized + RedisWrite,
1572    {
1573        Self::make_arg_iter_ref(items.iter(), out)
1574    }
1575
1576    /// This only exists internally as a workaround for the lack of
1577    /// specialization.
1578    #[doc(hidden)]
1579    fn make_arg_iter_ref<'a, I, W>(items: I, out: &mut W)
1580    where
1581        W: ?Sized + RedisWrite,
1582        I: Iterator<Item = &'a Self>,
1583        Self: 'a,
1584    {
1585        for item in items {
1586            item.write_redis_args(out);
1587        }
1588    }
1589
1590    #[doc(hidden)]
1591    fn is_single_vec_arg(items: &[Self]) -> bool {
1592        items.len() == 1 && items[0].num_of_args() <= 1
1593    }
1594}
1595
1596macro_rules! itoa_based_to_redis_impl {
1597    ($t:ty, $numeric:expr) => {
1598        impl ToRedisArgs for $t {
1599            fn write_redis_args<W>(&self, out: &mut W)
1600            where
1601                W: ?Sized + RedisWrite,
1602            {
1603                let mut buf = ::itoa::Buffer::new();
1604                let s = buf.format(*self);
1605                out.write_arg(s.as_bytes())
1606            }
1607
1608            fn describe_numeric_behavior(&self) -> NumericBehavior {
1609                $numeric
1610            }
1611        }
1612    };
1613}
1614
1615macro_rules! non_zero_itoa_based_to_redis_impl {
1616    ($t:ty, $numeric:expr) => {
1617        impl ToRedisArgs for $t {
1618            fn write_redis_args<W>(&self, out: &mut W)
1619            where
1620                W: ?Sized + RedisWrite,
1621            {
1622                let mut buf = ::itoa::Buffer::new();
1623                let s = buf.format(self.get());
1624                out.write_arg(s.as_bytes())
1625            }
1626
1627            fn describe_numeric_behavior(&self) -> NumericBehavior {
1628                $numeric
1629            }
1630        }
1631    };
1632}
1633
1634macro_rules! ryu_based_to_redis_impl {
1635    ($t:ty, $numeric:expr) => {
1636        impl ToRedisArgs for $t {
1637            fn write_redis_args<W>(&self, out: &mut W)
1638            where
1639                W: ?Sized + RedisWrite,
1640            {
1641                let mut buf = ::ryu::Buffer::new();
1642                let s = buf.format(*self);
1643                out.write_arg(s.as_bytes())
1644            }
1645
1646            fn describe_numeric_behavior(&self) -> NumericBehavior {
1647                $numeric
1648            }
1649        }
1650    };
1651}
1652
1653impl ToRedisArgs for u8 {
1654    fn write_redis_args<W>(&self, out: &mut W)
1655    where
1656        W: ?Sized + RedisWrite,
1657    {
1658        let mut buf = ::itoa::Buffer::new();
1659        let s = buf.format(*self);
1660        out.write_arg(s.as_bytes())
1661    }
1662
1663    fn write_args_from_slice<W>(items: &[u8], out: &mut W)
1664    where
1665        W: ?Sized + RedisWrite,
1666    {
1667        out.write_arg(items);
1668    }
1669
1670    fn is_single_vec_arg(_items: &[u8]) -> bool {
1671        true
1672    }
1673}
1674
1675itoa_based_to_redis_impl!(i8, NumericBehavior::NumberIsInteger);
1676itoa_based_to_redis_impl!(i16, NumericBehavior::NumberIsInteger);
1677itoa_based_to_redis_impl!(u16, NumericBehavior::NumberIsInteger);
1678itoa_based_to_redis_impl!(i32, NumericBehavior::NumberIsInteger);
1679itoa_based_to_redis_impl!(u32, NumericBehavior::NumberIsInteger);
1680itoa_based_to_redis_impl!(i64, NumericBehavior::NumberIsInteger);
1681itoa_based_to_redis_impl!(u64, NumericBehavior::NumberIsInteger);
1682itoa_based_to_redis_impl!(i128, NumericBehavior::NumberIsInteger);
1683itoa_based_to_redis_impl!(u128, NumericBehavior::NumberIsInteger);
1684itoa_based_to_redis_impl!(isize, NumericBehavior::NumberIsInteger);
1685itoa_based_to_redis_impl!(usize, NumericBehavior::NumberIsInteger);
1686
1687non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU8, NumericBehavior::NumberIsInteger);
1688non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI8, NumericBehavior::NumberIsInteger);
1689non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU16, NumericBehavior::NumberIsInteger);
1690non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI16, NumericBehavior::NumberIsInteger);
1691non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU32, NumericBehavior::NumberIsInteger);
1692non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI32, NumericBehavior::NumberIsInteger);
1693non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU64, NumericBehavior::NumberIsInteger);
1694non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI64, NumericBehavior::NumberIsInteger);
1695non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU128, NumericBehavior::NumberIsInteger);
1696non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI128, NumericBehavior::NumberIsInteger);
1697non_zero_itoa_based_to_redis_impl!(core::num::NonZeroUsize, NumericBehavior::NumberIsInteger);
1698non_zero_itoa_based_to_redis_impl!(core::num::NonZeroIsize, NumericBehavior::NumberIsInteger);
1699
1700ryu_based_to_redis_impl!(f32, NumericBehavior::NumberIsFloat);
1701ryu_based_to_redis_impl!(f64, NumericBehavior::NumberIsFloat);
1702
1703#[cfg(any(
1704    feature = "rust_decimal",
1705    feature = "bigdecimal",
1706    feature = "num-bigint"
1707))]
1708macro_rules! bignum_to_redis_impl {
1709    ($t:ty) => {
1710        impl ToRedisArgs for $t {
1711            fn write_redis_args<W>(&self, out: &mut W)
1712            where
1713                W: ?Sized + RedisWrite,
1714            {
1715                out.write_arg(&self.to_string().into_bytes())
1716            }
1717        }
1718    };
1719}
1720
1721#[cfg(feature = "rust_decimal")]
1722bignum_to_redis_impl!(rust_decimal::Decimal);
1723#[cfg(feature = "bigdecimal")]
1724bignum_to_redis_impl!(bigdecimal::BigDecimal);
1725#[cfg(feature = "num-bigint")]
1726bignum_to_redis_impl!(num_bigint::BigInt);
1727#[cfg(feature = "num-bigint")]
1728bignum_to_redis_impl!(num_bigint::BigUint);
1729
1730impl ToRedisArgs for bool {
1731    fn write_redis_args<W>(&self, out: &mut W)
1732    where
1733        W: ?Sized + RedisWrite,
1734    {
1735        out.write_arg(if *self { b"1" } else { b"0" })
1736    }
1737}
1738
1739impl ToRedisArgs for String {
1740    fn write_redis_args<W>(&self, out: &mut W)
1741    where
1742        W: ?Sized + RedisWrite,
1743    {
1744        out.write_arg(self.as_bytes())
1745    }
1746}
1747
1748impl ToRedisArgs for &str {
1749    fn write_redis_args<W>(&self, out: &mut W)
1750    where
1751        W: ?Sized + RedisWrite,
1752    {
1753        out.write_arg(self.as_bytes())
1754    }
1755}
1756
1757impl<'a, T> ToRedisArgs for Cow<'a, T>
1758where
1759    T: ToOwned + ?Sized,
1760    &'a T: ToRedisArgs,
1761    for<'b> &'b T::Owned: ToRedisArgs,
1762{
1763    fn write_redis_args<W>(&self, out: &mut W)
1764    where
1765        W: ?Sized + RedisWrite,
1766    {
1767        match self {
1768            Cow::Borrowed(inner) => inner.write_redis_args(out),
1769            Cow::Owned(inner) => inner.write_redis_args(out),
1770        }
1771    }
1772}
1773
1774impl<T: ToRedisArgs> ToRedisArgs for Vec<T> {
1775    fn write_redis_args<W>(&self, out: &mut W)
1776    where
1777        W: ?Sized + RedisWrite,
1778    {
1779        ToRedisArgs::write_args_from_slice(self, out)
1780    }
1781
1782    fn num_of_args(&self) -> usize {
1783        if ToRedisArgs::is_single_vec_arg(&self[..]) {
1784            return 1;
1785        }
1786        if self.len() == 1 {
1787            self[0].num_of_args()
1788        } else {
1789            self.len()
1790        }
1791    }
1792}
1793
1794impl<T: ToRedisArgs> ToRedisArgs for &[T] {
1795    fn write_redis_args<W>(&self, out: &mut W)
1796    where
1797        W: ?Sized + RedisWrite,
1798    {
1799        ToRedisArgs::write_args_from_slice(self, out)
1800    }
1801
1802    fn num_of_args(&self) -> usize {
1803        if ToRedisArgs::is_single_vec_arg(&self[..]) {
1804            return 1;
1805        }
1806        if self.len() == 1 {
1807            self[0].num_of_args()
1808        } else {
1809            self.len()
1810        }
1811    }
1812}
1813
1814impl<T: ToRedisArgs> ToRedisArgs for Option<T> {
1815    fn write_redis_args<W>(&self, out: &mut W)
1816    where
1817        W: ?Sized + RedisWrite,
1818    {
1819        if let Some(ref x) = *self {
1820            x.write_redis_args(out);
1821        }
1822    }
1823
1824    fn describe_numeric_behavior(&self) -> NumericBehavior {
1825        match *self {
1826            Some(ref x) => x.describe_numeric_behavior(),
1827            None => NumericBehavior::NonNumeric,
1828        }
1829    }
1830
1831    fn num_of_args(&self) -> usize {
1832        match *self {
1833            Some(ref x) => x.num_of_args(),
1834            None => 0,
1835        }
1836    }
1837}
1838
1839macro_rules! deref_to_write_redis_args_impl {
1840    (
1841        $(#[$attr:meta])*
1842        <$($desc:tt)+
1843    ) => {
1844        $(#[$attr])*
1845        impl <$($desc)+ {
1846            #[inline]
1847            fn write_redis_args<W>(&self, out: &mut W)
1848                where
1849                W: ?Sized + RedisWrite,
1850            {
1851                (**self).write_redis_args(out)
1852            }
1853
1854            fn num_of_args(&self) -> usize {
1855                (**self).num_of_args()
1856            }
1857
1858            fn describe_numeric_behavior(&self) -> NumericBehavior {
1859                (**self).describe_numeric_behavior()
1860            }
1861        }
1862    };
1863}
1864
1865deref_to_write_redis_args_impl! {
1866    <'a, T> ToRedisArgs for &'a T where T: ToRedisArgs
1867}
1868
1869deref_to_write_redis_args_impl! {
1870    <'a, T> ToRedisArgs for &'a mut T where T: ToRedisArgs
1871}
1872
1873deref_to_write_redis_args_impl! {
1874    <T> ToRedisArgs for Box<T> where T: ToRedisArgs
1875}
1876
1877deref_to_write_redis_args_impl! {
1878    <T> ToRedisArgs for std::sync::Arc<T> where T: ToRedisArgs
1879}
1880
1881deref_to_write_redis_args_impl! {
1882    <T> ToRedisArgs for std::rc::Rc<T> where T: ToRedisArgs
1883}
1884
1885/// @note: Redis cannot store empty sets so the application has to
1886/// check whether the set is empty and if so, not attempt to use that
1887/// result
1888macro_rules! impl_to_redis_args_for_set {
1889    (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+) ) => {
1890        impl< $($TypeParam),+ > ToRedisArgs for $SetType
1891        where
1892            $($WhereClause)+
1893        {
1894            fn write_redis_args<W>(&self, out: &mut W)
1895            where
1896                W: ?Sized + RedisWrite,
1897            {
1898                ToRedisArgs::make_arg_iter_ref(self.iter(), out)
1899            }
1900
1901            fn num_of_args(&self) -> usize {
1902                self.len()
1903            }
1904        }
1905    };
1906}
1907
1908impl_to_redis_args_for_set!(
1909    for <T, S> std::collections::HashSet<T, S>,
1910    where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1911);
1912
1913impl_to_redis_args_for_set!(
1914    for <T> std::collections::BTreeSet<T>,
1915    where (T: ToRedisArgs + Hash + Eq + Ord)
1916);
1917
1918#[cfg(feature = "hashbrown")]
1919impl_to_redis_args_for_set!(
1920    for <T, S> hashbrown::HashSet<T, S>,
1921    where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1922);
1923
1924#[cfg(feature = "ahash")]
1925impl_to_redis_args_for_set!(
1926    for <T, S> ahash::AHashSet<T, S>,
1927    where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1928);
1929
1930/// @note: Redis cannot store empty maps so the application has to
1931/// check whether the set is empty and if so, not attempt to use that
1932/// result
1933macro_rules! impl_to_redis_args_for_map {
1934    (
1935        $(#[$meta:meta])*
1936        for <$($TypeParam:ident),+> $MapType:ty,
1937        where ($($WhereClause:tt)+)
1938    ) => {
1939        $(#[$meta])*
1940        impl< $($TypeParam),+ > ToRedisArgs for $MapType
1941        where
1942            $($WhereClause)+
1943        {
1944            fn write_redis_args<W>(&self, out: &mut W)
1945            where
1946                W: ?Sized + RedisWrite,
1947            {
1948                for (key, value) in self {
1949                    // Ensure key and value produce a single argument each
1950                    assert!(key.num_of_args() <= 1 && value.num_of_args() <= 1);
1951                    key.write_redis_args(out);
1952                    value.write_redis_args(out);
1953                }
1954            }
1955
1956            fn num_of_args(&self) -> usize {
1957                self.len()
1958            }
1959        }
1960    };
1961}
1962impl_to_redis_args_for_map!(
1963    for <K, V> std::collections::HashMap<K, V>,
1964    where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1965);
1966
1967impl_to_redis_args_for_map!(
1968    /// this flattens BTreeMap into something that goes well with HMSET
1969    for <K, V> std::collections::BTreeMap<K, V>,
1970    where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1971);
1972
1973#[cfg(feature = "hashbrown")]
1974impl_to_redis_args_for_map!(
1975    for <K, V> hashbrown::HashMap<K, V>,
1976    where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1977);
1978
1979macro_rules! to_redis_args_for_tuple {
1980    () => ();
1981    ($(#[$meta:meta],)*$($name:ident,)+) => (
1982        $(#[$meta])*
1983        impl<$($name: ToRedisArgs),*> ToRedisArgs for ($($name,)*) {
1984            // we have local variables named T1 as dummies and those
1985            // variables are unused.
1986            #[allow(non_snake_case, unused_variables)]
1987            fn write_redis_args<W>(&self, out: &mut W) where W: ?Sized + RedisWrite {
1988                let ($(ref $name,)*) = *self;
1989                $($name.write_redis_args(out);)*
1990            }
1991
1992            #[allow(non_snake_case, unused_variables)]
1993            fn num_of_args(&self) -> usize {
1994                let mut n: usize = 0;
1995                $(let $name = (); n += 1;)*
1996                n
1997            }
1998        }
1999    )
2000}
2001
2002to_redis_args_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
2003to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, }
2004to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, }
2005to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
2006to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
2007to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
2008to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
2009to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
2010to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
2011to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
2012to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2013to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2014
2015impl<T: ToRedisArgs, const N: usize> ToRedisArgs for &[T; N] {
2016    fn write_redis_args<W>(&self, out: &mut W)
2017    where
2018        W: ?Sized + RedisWrite,
2019    {
2020        ToRedisArgs::write_args_from_slice(self.as_slice(), out)
2021    }
2022
2023    fn num_of_args(&self) -> usize {
2024        if ToRedisArgs::is_single_vec_arg(&self[..]) {
2025            return 1;
2026        }
2027        if self.len() == 1 {
2028            self[0].num_of_args()
2029        } else {
2030            self.len()
2031        }
2032    }
2033}
2034
2035fn vec_to_array<T, const N: usize>(items: Vec<T>, original_value: &Value) -> RedisResult<[T; N]> {
2036    match items.try_into() {
2037        Ok(array) => Ok(array),
2038        Err(items) => {
2039            let msg = format!(
2040                "Response has wrong dimension, expected {N}, got {}",
2041                items.len()
2042            );
2043            invalid_type_error!(original_value, msg)
2044        }
2045    }
2046}
2047
2048impl<T: FromRedisValue, const N: usize> FromRedisValue for [T; N] {
2049    fn from_redis_value(value: &Value) -> RedisResult<[T; N]> {
2050        match *value {
2051            Value::BulkString(ref bytes) => match FromRedisValue::from_byte_vec(bytes) {
2052                Some(items) => vec_to_array(items, value),
2053                None => {
2054                    let msg = format!(
2055                        "Conversion to Array[{}; {N}] failed",
2056                        std::any::type_name::<T>()
2057                    );
2058                    invalid_type_error!(value, msg)
2059                }
2060            },
2061            Value::Array(ref items) => {
2062                let items = FromRedisValue::from_redis_values(items)?;
2063                vec_to_array(items, value)
2064            }
2065            Value::Nil => vec_to_array(vec![], value),
2066            _ => invalid_type_error!(value, "Response type not array compatible"),
2067        }
2068    }
2069}
2070
2071/// This trait is used to convert a redis value into a more appropriate
2072/// type.
2073///
2074/// While a redis `Value` can represent any response that comes
2075/// back from the redis server, usually you want to map this into something
2076/// that works better in rust.  For instance you might want to convert the
2077/// return value into a `String` or an integer.
2078///
2079/// This trait is well supported throughout the library and you can
2080/// implement it for your own types if you want.
2081///
2082/// In addition to what you can see from the docs, this is also implemented
2083/// for tuples up to size 12 and for `Vec<u8>`.
2084pub trait FromRedisValue: Sized {
2085    /// Given a redis `Value` this attempts to convert it into the given
2086    /// destination type.  If that fails because it's not compatible an
2087    /// appropriate error is generated.
2088    fn from_redis_value(v: &Value) -> RedisResult<Self>;
2089
2090    /// Given a redis `Value` this attempts to convert it into the given
2091    /// destination type.  If that fails because it's not compatible an
2092    /// appropriate error is generated.
2093    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2094        // By default, fall back to `from_redis_value`.
2095        // This function only needs to be implemented if it can benefit
2096        // from taking `v` by value.
2097        Self::from_redis_value(&v)
2098    }
2099
2100    /// Similar to `from_redis_value` but constructs a vector of objects
2101    /// from another vector of values.  This primarily exists internally
2102    /// to customize the behavior for vectors of tuples.
2103    fn from_redis_values(items: &[Value]) -> RedisResult<Vec<Self>> {
2104        items.iter().map(FromRedisValue::from_redis_value).collect()
2105    }
2106
2107    /// The same as `from_redis_values`, but takes a `Vec<Value>` instead
2108    /// of a `&[Value]`.
2109    fn from_owned_redis_values(items: Vec<Value>) -> RedisResult<Vec<Self>> {
2110        items
2111            .into_iter()
2112            .map(FromRedisValue::from_owned_redis_value)
2113            .collect()
2114    }
2115
2116    /// The same as `from_owned_redis_values`, but returns a result for each
2117    /// conversion to make handling them case-by-case possible.
2118    fn from_each_owned_redis_values(items: Vec<Value>) -> Vec<RedisResult<Self>> {
2119        items
2120            .into_iter()
2121            .map(FromRedisValue::from_owned_redis_value)
2122            .collect()
2123    }
2124
2125    /// Convert bytes to a single element vector.
2126    fn from_byte_vec(_vec: &[u8]) -> Option<Vec<Self>> {
2127        Self::from_owned_redis_value(Value::BulkString(_vec.into()))
2128            .map(|rv| vec![rv])
2129            .ok()
2130    }
2131
2132    /// Convert bytes to a single element vector.
2133    fn from_owned_byte_vec(_vec: Vec<u8>) -> RedisResult<Vec<Self>> {
2134        Self::from_owned_redis_value(Value::BulkString(_vec)).map(|rv| vec![rv])
2135    }
2136}
2137
2138fn get_inner_value(v: &Value) -> &Value {
2139    if let Value::Attribute {
2140        data,
2141        attributes: _,
2142    } = v
2143    {
2144        data.as_ref()
2145    } else {
2146        v
2147    }
2148}
2149
2150fn get_owned_inner_value(v: Value) -> Value {
2151    if let Value::Attribute {
2152        data,
2153        attributes: _,
2154    } = v
2155    {
2156        *data
2157    } else {
2158        v
2159    }
2160}
2161
2162macro_rules! from_redis_value_for_num_internal {
2163    ($t:ty, $v:expr) => {{
2164        let v = if let Value::Attribute {
2165            data,
2166            attributes: _,
2167        } = $v
2168        {
2169            data
2170        } else {
2171            $v
2172        };
2173        match *v {
2174            Value::Int(val) => Ok(val as $t),
2175            Value::SimpleString(ref s) => match s.parse::<$t>() {
2176                Ok(rv) => Ok(rv),
2177                Err(_) => invalid_type_error!(v, "Could not convert from string."),
2178            },
2179            Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
2180                Ok(rv) => Ok(rv),
2181                Err(_) => invalid_type_error!(v, "Could not convert from string."),
2182            },
2183            Value::Double(val) => Ok(val as $t),
2184            _ => invalid_type_error!(v, "Response type not convertible to numeric."),
2185        }
2186    }};
2187}
2188
2189macro_rules! from_redis_value_for_num {
2190    ($t:ty) => {
2191        impl FromRedisValue for $t {
2192            fn from_redis_value(v: &Value) -> RedisResult<$t> {
2193                from_redis_value_for_num_internal!($t, v)
2194            }
2195        }
2196    };
2197}
2198
2199impl FromRedisValue for u8 {
2200    fn from_redis_value(v: &Value) -> RedisResult<u8> {
2201        from_redis_value_for_num_internal!(u8, v)
2202    }
2203
2204    // this hack allows us to specialize Vec<u8> to work with binary data.
2205    fn from_byte_vec(vec: &[u8]) -> Option<Vec<u8>> {
2206        Some(vec.to_vec())
2207    }
2208    fn from_owned_byte_vec(vec: Vec<u8>) -> RedisResult<Vec<u8>> {
2209        Ok(vec)
2210    }
2211}
2212
2213from_redis_value_for_num!(i8);
2214from_redis_value_for_num!(i16);
2215from_redis_value_for_num!(u16);
2216from_redis_value_for_num!(i32);
2217from_redis_value_for_num!(u32);
2218from_redis_value_for_num!(i64);
2219from_redis_value_for_num!(u64);
2220from_redis_value_for_num!(i128);
2221from_redis_value_for_num!(u128);
2222from_redis_value_for_num!(f32);
2223from_redis_value_for_num!(f64);
2224from_redis_value_for_num!(isize);
2225from_redis_value_for_num!(usize);
2226
2227#[cfg(any(
2228    feature = "rust_decimal",
2229    feature = "bigdecimal",
2230    feature = "num-bigint"
2231))]
2232macro_rules! from_redis_value_for_bignum_internal {
2233    ($t:ty, $v:expr) => {{
2234        let v = $v;
2235        match *v {
2236            Value::Int(val) => <$t>::try_from(val)
2237                .map_err(|_| invalid_type_error_inner!(v, "Could not convert from integer.")),
2238            Value::SimpleString(ref s) => match s.parse::<$t>() {
2239                Ok(rv) => Ok(rv),
2240                Err(_) => invalid_type_error!(v, "Could not convert from string."),
2241            },
2242            Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
2243                Ok(rv) => Ok(rv),
2244                Err(_) => invalid_type_error!(v, "Could not convert from string."),
2245            },
2246            _ => invalid_type_error!(v, "Response type not convertible to numeric."),
2247        }
2248    }};
2249}
2250
2251#[cfg(any(
2252    feature = "rust_decimal",
2253    feature = "bigdecimal",
2254    feature = "num-bigint"
2255))]
2256macro_rules! from_redis_value_for_bignum {
2257    ($t:ty) => {
2258        impl FromRedisValue for $t {
2259            fn from_redis_value(v: &Value) -> RedisResult<$t> {
2260                from_redis_value_for_bignum_internal!($t, v)
2261            }
2262        }
2263    };
2264}
2265
2266#[cfg(feature = "rust_decimal")]
2267from_redis_value_for_bignum!(rust_decimal::Decimal);
2268#[cfg(feature = "bigdecimal")]
2269from_redis_value_for_bignum!(bigdecimal::BigDecimal);
2270#[cfg(feature = "num-bigint")]
2271from_redis_value_for_bignum!(num_bigint::BigInt);
2272#[cfg(feature = "num-bigint")]
2273from_redis_value_for_bignum!(num_bigint::BigUint);
2274
2275impl FromRedisValue for bool {
2276    fn from_redis_value(v: &Value) -> RedisResult<bool> {
2277        let v = get_inner_value(v);
2278        match *v {
2279            Value::Nil => Ok(false),
2280            Value::Int(val) => Ok(val != 0),
2281            Value::SimpleString(ref s) => {
2282                if &s[..] == "1" {
2283                    Ok(true)
2284                } else if &s[..] == "0" {
2285                    Ok(false)
2286                } else {
2287                    invalid_type_error!(v, "Response status not valid boolean");
2288                }
2289            }
2290            Value::BulkString(ref bytes) => {
2291                if bytes == b"1" {
2292                    Ok(true)
2293                } else if bytes == b"0" {
2294                    Ok(false)
2295                } else {
2296                    invalid_type_error!(v, "Response type not bool compatible.");
2297                }
2298            }
2299            Value::Boolean(b) => Ok(b),
2300            Value::Okay => Ok(true),
2301            _ => invalid_type_error!(v, "Response type not bool compatible."),
2302        }
2303    }
2304}
2305
2306impl FromRedisValue for CString {
2307    fn from_redis_value(v: &Value) -> RedisResult<CString> {
2308        let v = get_inner_value(v);
2309        match *v {
2310            Value::BulkString(ref bytes) => Ok(CString::new(bytes.as_slice())?),
2311            Value::Okay => Ok(CString::new("OK")?),
2312            Value::SimpleString(ref val) => Ok(CString::new(val.as_bytes())?),
2313            _ => invalid_type_error!(v, "Response type not CString compatible."),
2314        }
2315    }
2316    fn from_owned_redis_value(v: Value) -> RedisResult<CString> {
2317        let v = get_owned_inner_value(v);
2318        match v {
2319            Value::BulkString(bytes) => Ok(CString::new(bytes)?),
2320            Value::Okay => Ok(CString::new("OK")?),
2321            Value::SimpleString(val) => Ok(CString::new(val)?),
2322            _ => invalid_type_error!(v, "Response type not CString compatible."),
2323        }
2324    }
2325}
2326
2327impl FromRedisValue for String {
2328    fn from_redis_value(v: &Value) -> RedisResult<Self> {
2329        let v = get_inner_value(v);
2330        match *v {
2331            Value::BulkString(ref bytes) => Ok(from_utf8(bytes)?.to_string()),
2332            Value::Okay => Ok("OK".to_string()),
2333            Value::SimpleString(ref val) => Ok(val.to_string()),
2334            Value::VerbatimString {
2335                format: _,
2336                ref text,
2337            } => Ok(text.to_string()),
2338            Value::Double(ref val) => Ok(val.to_string()),
2339            Value::Int(val) => Ok(val.to_string()),
2340            _ => invalid_type_error!(v, "Response type not string compatible."),
2341        }
2342    }
2343
2344    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2345        let v = get_owned_inner_value(v);
2346        match v {
2347            Value::BulkString(bytes) => Ok(Self::from_utf8(bytes)?),
2348            Value::Okay => Ok("OK".to_string()),
2349            Value::SimpleString(val) => Ok(val),
2350            Value::VerbatimString { format: _, text } => Ok(text),
2351            Value::Double(val) => Ok(val.to_string()),
2352            Value::Int(val) => Ok(val.to_string()),
2353            _ => invalid_type_error!(v, "Response type not string compatible."),
2354        }
2355    }
2356}
2357
2358macro_rules! pointer_from_redis_value_impl {
2359    (
2360        $(#[$attr:meta])*
2361        $id:ident, $ty:ty, $func:expr
2362    ) => {
2363        $(#[$attr])*
2364        impl<$id:  FromRedisValue> FromRedisValue for $ty {
2365            fn from_redis_value(v: &Value) -> RedisResult<Self>
2366            {
2367                FromRedisValue::from_redis_value(v).map($func)
2368            }
2369
2370            fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2371                FromRedisValue::from_owned_redis_value(v).map($func)
2372            }
2373        }
2374    }
2375}
2376
2377pointer_from_redis_value_impl!(T, Box<T>, Box::new);
2378pointer_from_redis_value_impl!(T, std::sync::Arc<T>, std::sync::Arc::new);
2379pointer_from_redis_value_impl!(T, std::rc::Rc<T>, std::rc::Rc::new);
2380
2381/// Implement `FromRedisValue` for `$Type` (which should use the generic parameter `$T`).
2382///
2383/// The implementation parses the value into a vec, and then passes the value through `$convert`.
2384/// If `$convert` is omitted, it defaults to `Into::into`.
2385macro_rules! from_vec_from_redis_value {
2386    (<$T:ident> $Type:ty) => {
2387        from_vec_from_redis_value!(<$T> $Type; Into::into);
2388    };
2389
2390    (<$T:ident> $Type:ty; $convert:expr) => {
2391        impl<$T: FromRedisValue> FromRedisValue for $Type {
2392            fn from_redis_value(v: &Value) -> RedisResult<$Type> {
2393                match v {
2394                    // All binary data except u8 will try to parse into a single element vector.
2395                    // u8 has its own implementation of from_byte_vec.
2396                    Value::BulkString(bytes) => match FromRedisValue::from_byte_vec(bytes) {
2397                        Some(x) => Ok($convert(x)),
2398                        None => invalid_type_error!(
2399                            v,
2400                            format!("Conversion to {} failed.", std::any::type_name::<$Type>())
2401                        ),
2402                    },
2403                    Value::Array(items) => FromRedisValue::from_redis_values(items).map($convert),
2404                    Value::Set(ref items) => FromRedisValue::from_redis_values(items).map($convert),
2405                    Value::Map(ref items) => {
2406                        let mut n: Vec<T> = vec![];
2407                        for item in items {
2408                            match FromRedisValue::from_redis_value(&Value::Map(vec![item.clone()])) {
2409                                Ok(v) => {
2410                                    n.push(v);
2411                                }
2412                                Err(e) => {
2413                                    return Err(e);
2414                                }
2415                            }
2416                        }
2417                        Ok($convert(n))
2418                    }
2419                    Value::Nil => Ok($convert(Vec::new())),
2420                    _ => invalid_type_error!(v, "Response type not vector compatible."),
2421                }
2422            }
2423            fn from_owned_redis_value(v: Value) -> RedisResult<$Type> {
2424                match v {
2425                    // Binary data is parsed into a single-element vector, except
2426                    // for the element type `u8`, which directly consumes the entire
2427                    // array of bytes.
2428                    Value::BulkString(bytes) => FromRedisValue::from_owned_byte_vec(bytes).map($convert),
2429                    Value::Array(items) => FromRedisValue::from_owned_redis_values(items).map($convert),
2430                    Value::Set(items) => FromRedisValue::from_owned_redis_values(items).map($convert),
2431                    Value::Map(items) => {
2432                        let mut n: Vec<T> = vec![];
2433                        for item in items {
2434                            match FromRedisValue::from_owned_redis_value(Value::Map(vec![item])) {
2435                                Ok(v) => {
2436                                    n.push(v);
2437                                }
2438                                Err(e) => {
2439                                    return Err(e);
2440                                }
2441                            }
2442                        }
2443                        Ok($convert(n))
2444                    }
2445                    Value::Nil => Ok($convert(Vec::new())),
2446                    _ => invalid_type_error!(v, "Response type not vector compatible."),
2447                }
2448            }
2449        }
2450    };
2451}
2452
2453from_vec_from_redis_value!(<T> Vec<T>);
2454from_vec_from_redis_value!(<T> std::sync::Arc<[T]>);
2455from_vec_from_redis_value!(<T> Box<[T]>; Vec::into_boxed_slice);
2456
2457macro_rules! impl_from_redis_value_for_map {
2458    (for <$($TypeParam:ident),+> $MapType:ty, where ($($WhereClause:tt)+)) => {
2459        impl< $($TypeParam),+ > FromRedisValue for $MapType
2460        where
2461            $($WhereClause)+
2462        {
2463            fn from_redis_value(v: &Value) -> RedisResult<$MapType> {
2464                let v = get_inner_value(v);
2465                match *v {
2466                    Value::Nil => Ok(Default::default()),
2467                    _ => v
2468                        .as_map_iter()
2469                        .ok_or_else(|| invalid_type_error_inner!(v, "Response type not map compatible"))?
2470                        .map(|(k, v)| {
2471                            Ok((from_redis_value(k)?, from_redis_value(v)?))
2472                        })
2473                        .collect(),
2474                }
2475            }
2476
2477            fn from_owned_redis_value(v: Value) -> RedisResult<$MapType> {
2478                let v = get_owned_inner_value(v);
2479                match v {
2480                    Value::Nil => Ok(Default::default()),
2481                    _ => v
2482                        .into_map_iter()
2483                        .map_err(|v| invalid_type_error_inner!(v, "Response type not map compatible"))?
2484                        .map(|(k, v)| {
2485                            Ok((from_owned_redis_value(k)?, from_owned_redis_value(v)?))
2486                        })
2487                        .collect(),
2488                }
2489            }
2490        }
2491    };
2492}
2493
2494impl_from_redis_value_for_map!(
2495    for <K, V, S> std::collections::HashMap<K, V, S>,
2496    where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2497);
2498
2499#[cfg(feature = "hashbrown")]
2500impl_from_redis_value_for_map!(
2501    for <K, V, S> hashbrown::HashMap<K, V, S>,
2502    where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2503);
2504
2505#[cfg(feature = "ahash")]
2506impl_from_redis_value_for_map!(
2507    for <K, V> ahash::AHashMap<K, V>,
2508    where (K: FromRedisValue + Eq + Hash, V: FromRedisValue)
2509);
2510
2511impl_from_redis_value_for_map!(
2512    for <K, V> std::collections::BTreeMap<K, V>,
2513    where (K: FromRedisValue + Eq + Hash + Ord, V: FromRedisValue)
2514);
2515
2516macro_rules! impl_from_redis_value_for_set {
2517    (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+)) => {
2518        impl< $($TypeParam),+ > FromRedisValue for $SetType
2519        where
2520            $($WhereClause)+
2521        {
2522            fn from_redis_value(v: &Value) -> RedisResult<$SetType> {
2523                let v = get_inner_value(v);
2524                let items = v
2525                    .as_sequence()
2526                    .ok_or_else(|| invalid_type_error_inner!(v, "Response type not map compatible"))?;
2527                items.iter().map(|item| from_redis_value(item)).collect()
2528            }
2529
2530            fn from_owned_redis_value(v: Value) -> RedisResult<$SetType> {
2531                let v = get_owned_inner_value(v);
2532                let items = v
2533                    .into_sequence()
2534                    .map_err(|v| invalid_type_error_inner!(v, "Response type not map compatible"))?;
2535                items
2536                    .into_iter()
2537                    .map(|item| from_owned_redis_value(item))
2538                    .collect()
2539            }
2540        }
2541    };
2542}
2543
2544impl_from_redis_value_for_set!(
2545    for <T, S> std::collections::HashSet<T, S>,
2546    where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2547);
2548
2549impl_from_redis_value_for_set!(
2550    for <T> std::collections::BTreeSet<T>,
2551    where (T: FromRedisValue + Eq + Ord)
2552);
2553
2554#[cfg(feature = "hashbrown")]
2555impl_from_redis_value_for_set!(
2556    for <T, S> hashbrown::HashSet<T, S>,
2557    where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2558);
2559
2560#[cfg(feature = "ahash")]
2561impl_from_redis_value_for_set!(
2562    for <T> ahash::AHashSet<T>,
2563    where (T: FromRedisValue + Eq + Hash)
2564);
2565
2566impl FromRedisValue for Value {
2567    fn from_redis_value(v: &Value) -> RedisResult<Value> {
2568        Ok(v.clone())
2569    }
2570    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2571        Ok(v)
2572    }
2573}
2574
2575impl FromRedisValue for () {
2576    fn from_redis_value(_v: &Value) -> RedisResult<()> {
2577        Ok(())
2578    }
2579}
2580
2581macro_rules! from_redis_value_for_tuple {
2582    () => ();
2583    ($(#[$meta:meta],)*$($name:ident,)+) => (
2584        $(#[$meta])*
2585        impl<$($name: FromRedisValue),*> FromRedisValue for ($($name,)*) {
2586            // we have local variables named T1 as dummies and those
2587            // variables are unused.
2588            #[allow(non_snake_case, unused_variables)]
2589            fn from_redis_value(v: &Value) -> RedisResult<($($name,)*)> {
2590                let v = get_inner_value(v);
2591                // hacky way to count the tuple size
2592                let mut n = 0;
2593                $(let $name = (); n += 1;)*
2594
2595                match *v {
2596                    Value::Array(ref items) => {
2597                        if items.len() != n {
2598                            invalid_type_error!(v, "Array response of wrong dimension")
2599                        }
2600
2601                        // The { i += 1; i - 1} is rust's postfix increment :)
2602                        let mut i = 0;
2603                        Ok(($({let $name = (); from_redis_value(
2604                             &items[{ i += 1; i - 1 }])?},)*))
2605                    }
2606
2607                    Value::Set(ref items) => {
2608                        if items.len() != n {
2609                            invalid_type_error!(v, "Set response of wrong dimension")
2610                        }
2611
2612                        // The { i += 1; i - 1} is rust's postfix increment :)
2613                        let mut i = 0;
2614                        Ok(($({let $name = (); from_redis_value(
2615                             &items[{ i += 1; i - 1 }])?},)*))
2616                    }
2617
2618                    Value::Map(ref items) => {
2619                        if n != items.len() * 2 {
2620                            invalid_type_error!(v, "Map response of wrong dimension")
2621                        }
2622
2623                        let mut flatten_items = items.iter().map(|(a,b)|[a,b]).flatten();
2624
2625                        Ok(($({let $name = (); from_redis_value(
2626                             &flatten_items.next().unwrap())?},)*))
2627                    }
2628
2629                    _ => invalid_type_error!(v, "Not a Array response")
2630                }
2631            }
2632
2633            // we have local variables named T1 as dummies and those
2634            // variables are unused.
2635            #[allow(non_snake_case, unused_variables)]
2636            fn from_owned_redis_value(v: Value) -> RedisResult<($($name,)*)> {
2637                let v = get_owned_inner_value(v);
2638                // hacky way to count the tuple size
2639                let mut n = 0;
2640                $(let $name = (); n += 1;)*
2641                match v {
2642                    Value::Array(mut items) => {
2643                        if items.len() != n {
2644                            invalid_type_error!(Value::Array(items), "Array response of wrong dimension")
2645                        }
2646
2647                        // The { i += 1; i - 1} is rust's postfix increment :)
2648                        let mut i = 0;
2649                        Ok(($({let $name = (); from_owned_redis_value(
2650                            ::std::mem::replace(&mut items[{ i += 1; i - 1 }], Value::Nil)
2651                        )?},)*))
2652                    }
2653
2654                    Value::Set(mut items) => {
2655                        if items.len() != n {
2656                            invalid_type_error!(Value::Array(items), "Set response of wrong dimension")
2657                        }
2658
2659                        // The { i += 1; i - 1} is rust's postfix increment :)
2660                        let mut i = 0;
2661                        Ok(($({let $name = (); from_owned_redis_value(
2662                            ::std::mem::replace(&mut items[{ i += 1; i - 1 }], Value::Nil)
2663                        )?},)*))
2664                    }
2665
2666                    Value::Map(items) => {
2667                        if n != items.len() * 2 {
2668                            invalid_type_error!(Value::Map(items), "Map response of wrong dimension")
2669                        }
2670
2671                        let mut flatten_items = items.into_iter().map(|(a,b)|[a,b]).flatten();
2672
2673                        Ok(($({let $name = (); from_owned_redis_value(
2674                            ::std::mem::replace(&mut flatten_items.next().unwrap(), Value::Nil)
2675                        )?},)*))
2676                    }
2677
2678                    _ => invalid_type_error!(v, "Not a Array response")
2679                }
2680            }
2681
2682            #[allow(non_snake_case, unused_variables)]
2683            fn from_redis_values(items: &[Value]) -> RedisResult<Vec<($($name,)*)>> {
2684                // hacky way to count the tuple size
2685                let mut n = 0;
2686                $(let $name = (); n += 1;)*
2687                if items.len() == 0 {
2688                    return Ok(vec![]);
2689                }
2690
2691                if items.iter().all(|item|item.is_collection_of_len(n)) {
2692                    return items.iter().map(|item|from_redis_value(item)).collect();
2693                }
2694
2695                let mut rv = Vec::with_capacity(items.len() / n);
2696                if let [$($name),*] = items{
2697                    rv.push(($(from_redis_value($name)?),*),);
2698                    return Ok(rv);
2699                }
2700                for chunk in items.chunks_exact(n) {
2701                    match chunk {
2702                        [$($name),*] => rv.push(($(from_redis_value($name)?),*),),
2703                         _ => {},
2704                    }
2705                }
2706                Ok(rv)
2707            }
2708
2709            #[allow(non_snake_case, unused_variables)]
2710            fn from_each_owned_redis_values(mut items: Vec<Value>) -> Vec<RedisResult<($($name,)*)>> {
2711
2712                #[allow(unused_parens)]
2713                let extract = |val: ($(RedisResult<$name>),*)| -> RedisResult<($($name,)*)> {
2714                    let ($($name),*) = val;
2715                    Ok(($($name?),*,))
2716                };
2717
2718                // hacky way to count the tuple size
2719                let mut n = 0;
2720                $(let $name = (); n += 1;)*
2721
2722                // let mut rv = vec![];
2723                if items.len() == 0 {
2724                    return vec![];
2725                }
2726                if items.iter().all(|item|item.is_collection_of_len(n)) {
2727                    return items.into_iter().map(|item|from_owned_redis_value(item)).collect();
2728                }
2729
2730                let mut rv = Vec::with_capacity(items.len() / n);
2731
2732                for chunk in items.chunks_mut(n) {
2733                    match chunk {
2734                        // Take each element out of the chunk with `std::mem::replace`, leaving a `Value::Nil`
2735                        // in its place. This allows each `Value` to be parsed without being copied.
2736                        // Since `items` is consumed by this function and not used later, this replacement
2737                        // is not observable to the rest of the code.
2738                        [$($name),*] => rv.push(extract(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))),*))),
2739                         _ => unreachable!(),
2740                    }
2741                }
2742                rv
2743            }
2744
2745            #[allow(non_snake_case, unused_variables)]
2746            fn from_owned_redis_values(mut items: Vec<Value>) -> RedisResult<Vec<($($name,)*)>> {
2747                // hacky way to count the tuple size
2748                let mut n = 0;
2749                $(let $name = (); n += 1;)*
2750
2751                // let mut rv = vec![];
2752                if items.len() == 0 {
2753                    return Ok(vec![])
2754                }
2755                if items.iter().all(|item|item.is_collection_of_len(n)) {
2756                    return items.into_iter().map(|item|from_owned_redis_value(item)).collect();
2757                }
2758
2759                let mut rv = Vec::with_capacity(items.len() / n);
2760                for chunk in items.chunks_mut(n) {
2761                    match chunk {
2762                        // Take each element out of the chunk with `std::mem::replace`, leaving a `Value::Nil`
2763                        // in its place. This allows each `Value` to be parsed without being copied.
2764                        // Since `items` is consume by this function and not used later, this replacement
2765                        // is not observable to the rest of the code.
2766                        [$($name),*] => rv.push(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))?),*),),
2767                         _ => unreachable!(),
2768                    }
2769                }
2770                Ok(rv)
2771            }
2772        }
2773    )
2774}
2775
2776from_redis_value_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
2777from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, }
2778from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, }
2779from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
2780from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
2781from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
2782from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
2783from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
2784from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
2785from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
2786from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2787from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2788
2789impl FromRedisValue for InfoDict {
2790    fn from_redis_value(v: &Value) -> RedisResult<InfoDict> {
2791        let v = get_inner_value(v);
2792        let s: String = from_redis_value(v)?;
2793        Ok(InfoDict::new(&s))
2794    }
2795    fn from_owned_redis_value(v: Value) -> RedisResult<InfoDict> {
2796        let v = get_owned_inner_value(v);
2797        let s: String = from_owned_redis_value(v)?;
2798        Ok(InfoDict::new(&s))
2799    }
2800}
2801
2802impl<T: FromRedisValue> FromRedisValue for Option<T> {
2803    fn from_redis_value(v: &Value) -> RedisResult<Option<T>> {
2804        let v = get_inner_value(v);
2805        if *v == Value::Nil {
2806            return Ok(None);
2807        }
2808        Ok(Some(from_redis_value(v)?))
2809    }
2810    fn from_owned_redis_value(v: Value) -> RedisResult<Option<T>> {
2811        let v = get_owned_inner_value(v);
2812        if v == Value::Nil {
2813            return Ok(None);
2814        }
2815        Ok(Some(from_owned_redis_value(v)?))
2816    }
2817}
2818
2819#[cfg(feature = "bytes")]
2820impl FromRedisValue for bytes::Bytes {
2821    fn from_redis_value(v: &Value) -> RedisResult<Self> {
2822        let v = get_inner_value(v);
2823        match v {
2824            Value::BulkString(bytes_vec) => Ok(bytes::Bytes::copy_from_slice(bytes_vec.as_ref())),
2825            _ => invalid_type_error!(v, "Not a bulk string"),
2826        }
2827    }
2828    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2829        let v = get_owned_inner_value(v);
2830        match v {
2831            Value::BulkString(bytes_vec) => Ok(bytes_vec.into()),
2832            _ => invalid_type_error!(v, "Not a bulk string"),
2833        }
2834    }
2835}
2836
2837#[cfg(feature = "uuid")]
2838impl FromRedisValue for uuid::Uuid {
2839    fn from_redis_value(v: &Value) -> RedisResult<Self> {
2840        match *v {
2841            Value::BulkString(ref bytes) => Ok(uuid::Uuid::from_slice(bytes)?),
2842            _ => invalid_type_error!(v, "Response type not uuid compatible."),
2843        }
2844    }
2845}
2846
2847#[cfg(feature = "uuid")]
2848impl ToRedisArgs for uuid::Uuid {
2849    fn write_redis_args<W>(&self, out: &mut W)
2850    where
2851        W: ?Sized + RedisWrite,
2852    {
2853        out.write_arg(self.as_bytes());
2854    }
2855}
2856
2857/// A shortcut function to invoke `FromRedisValue::from_redis_value`
2858/// to make the API slightly nicer.
2859pub fn from_redis_value<T: FromRedisValue>(v: &Value) -> RedisResult<T> {
2860    FromRedisValue::from_redis_value(v)
2861}
2862
2863/// A shortcut function to invoke `FromRedisValue::from_owned_redis_value`
2864/// to make the API slightly nicer.
2865pub fn from_owned_redis_value<T: FromRedisValue>(v: Value) -> RedisResult<T> {
2866    FromRedisValue::from_owned_redis_value(v)
2867}
2868
2869/// Enum representing the communication protocol with the server.
2870///
2871/// This enum represents the types of data that the server can send to the client,
2872/// and the capabilities that the client can use.
2873#[derive(Clone, Eq, PartialEq, Default, Debug, Copy)]
2874pub enum ProtocolVersion {
2875    /// <https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md>
2876    #[default]
2877    RESP2,
2878    /// <https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md>
2879    RESP3,
2880}
2881
2882/// Helper enum that is used to define option for the hash expire commands
2883#[derive(Clone, Copy)]
2884pub enum ExpireOption {
2885    /// NONE -- Set expiration regardless of the field's current expiration.
2886    NONE,
2887    /// NX -- Only set expiration only when the field has no expiration.
2888    NX,
2889    /// XX -- Only set expiration only when the field has an existing expiration.
2890    XX,
2891    /// GT -- Only set expiration only when the new expiration is greater than current one.
2892    GT,
2893    /// LT -- Only set expiration only when the new expiration is less than current one.
2894    LT,
2895}
2896
2897impl ToRedisArgs for ExpireOption {
2898    fn write_redis_args<W>(&self, out: &mut W)
2899    where
2900        W: ?Sized + RedisWrite,
2901    {
2902        match self {
2903            ExpireOption::NX => out.write_arg(b"NX"),
2904            ExpireOption::XX => out.write_arg(b"XX"),
2905            ExpireOption::GT => out.write_arg(b"GT"),
2906            ExpireOption::LT => out.write_arg(b"LT"),
2907            _ => {}
2908        }
2909    }
2910}
2911
2912#[derive(Debug, Clone, PartialEq)]
2913/// A push message from the server.
2914pub struct PushInfo {
2915    /// Push Kind
2916    pub kind: PushKind,
2917    /// Data from push message
2918    pub data: Vec<Value>,
2919}
2920
2921impl PushInfo {
2922    pub(crate) fn disconnect() -> Self {
2923        PushInfo {
2924            kind: crate::PushKind::Disconnection,
2925            data: vec![],
2926        }
2927    }
2928}
2929
2930pub(crate) type SyncPushSender = std::sync::mpsc::Sender<PushInfo>;
2931
2932// A consistent error value for connections closed without a reason.
2933#[cfg(any(feature = "aio", feature = "r2d2"))]
2934pub(crate) fn closed_connection_error() -> RedisError {
2935    RedisError::from(io::Error::from(io::ErrorKind::BrokenPipe))
2936}
2937
2938/// Possible types of value held in Redis: [Redis Docs](https://redis.io/docs/latest/commands/type/)
2939#[derive(Debug, Clone, PartialEq)]
2940pub enum ValueType {
2941    /// Generally returned by anything that returns a single element. [Redis Docs](https://redis.io/docs/latest/develop/data-types/strings/)
2942    String,
2943    /// A list of String values. [Redis Docs](https://redis.io/docs/latest/develop/data-types/lists/)
2944    List,
2945    /// A set of unique String values. [Redis Docs](https://redis.io/docs/latest/develop/data-types/sets/)
2946    Set,
2947    /// A sorted set of String values. [Redis Docs](https://redis.io/docs/latest/develop/data-types/sorted-sets/)
2948    ZSet,
2949    /// A collection of field-value pairs. [Redis Docs](https://redis.io/docs/latest/develop/data-types/hashes/)
2950    Hash,
2951    /// A Redis Stream. [Redis Docs](https://redis.io/docs/latest/develop/data-types/stream)
2952    Stream,
2953    /// Any other value type not explicitly defined in [Redis Docs](https://redis.io/docs/latest/commands/type/)
2954    Unknown(String),
2955}
2956
2957impl<T: AsRef<str>> From<T> for ValueType {
2958    fn from(s: T) -> Self {
2959        match s.as_ref() {
2960            "string" => ValueType::String,
2961            "list" => ValueType::List,
2962            "set" => ValueType::Set,
2963            "zset" => ValueType::ZSet,
2964            "hash" => ValueType::Hash,
2965            "stream" => ValueType::Stream,
2966            s => ValueType::Unknown(s.to_string()),
2967        }
2968    }
2969}
2970
2971impl From<ValueType> for String {
2972    fn from(v: ValueType) -> Self {
2973        match v {
2974            ValueType::String => "string".to_string(),
2975            ValueType::List => "list".to_string(),
2976            ValueType::Set => "set".to_string(),
2977            ValueType::ZSet => "zset".to_string(),
2978            ValueType::Hash => "hash".to_string(),
2979            ValueType::Stream => "stream".to_string(),
2980            ValueType::Unknown(s) => s,
2981        }
2982    }
2983}
2984
2985impl FromRedisValue for ValueType {
2986    fn from_redis_value(v: &Value) -> RedisResult<Self> {
2987        match v {
2988            Value::SimpleString(s) => Ok(s.into()),
2989            _ => invalid_type_error!(v, "Value type should be a simple string"),
2990        }
2991    }
2992
2993    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2994        match v {
2995            Value::SimpleString(s) => Ok(s.into()),
2996            _ => invalid_type_error!(v, "Value type should be a simple string"),
2997        }
2998    }
2999}
3000
3001/// Returned by typed commands which either return a positive integer or some negative integer indicating some kind of no-op.
3002#[derive(Debug, PartialEq, Clone)]
3003pub enum IntegerReplyOrNoOp {
3004    /// A positive integer reply indicating success of some kind.
3005    IntegerReply(usize),
3006    /// The field/key you are trying to operate on does not exist.
3007    NotExists,
3008    /// The field/key you are trying to operate on exists but is not of the correct type or does not have some property you are trying to affect.
3009    ExistsButNotRelevant,
3010}
3011
3012impl IntegerReplyOrNoOp {
3013    /// Returns the integer value of the reply.
3014    pub fn raw(&self) -> isize {
3015        match self {
3016            IntegerReplyOrNoOp::IntegerReply(s) => *s as isize,
3017            IntegerReplyOrNoOp::NotExists => -2,
3018            IntegerReplyOrNoOp::ExistsButNotRelevant => -1,
3019        }
3020    }
3021}
3022
3023impl FromRedisValue for IntegerReplyOrNoOp {
3024    fn from_redis_value(v: &Value) -> RedisResult<Self> {
3025        match v {
3026            Value::Int(s) => match s {
3027                -2 => Ok(IntegerReplyOrNoOp::NotExists),
3028                -1 => Ok(IntegerReplyOrNoOp::ExistsButNotRelevant),
3029                _ => Ok(IntegerReplyOrNoOp::IntegerReply(*s as usize)),
3030            },
3031            _ => invalid_type_error!(v, "Value should be an integer"),
3032        }
3033    }
3034
3035    fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
3036        match v {
3037            Value::Int(s) => match s {
3038                -2 => Ok(IntegerReplyOrNoOp::NotExists),
3039                -1 => Ok(IntegerReplyOrNoOp::ExistsButNotRelevant),
3040                _ => Ok(IntegerReplyOrNoOp::IntegerReply(s as usize)),
3041            },
3042            _ => invalid_type_error!(v, "Value should be an integer"),
3043        }
3044    }
3045}
3046
3047impl PartialEq<isize> for IntegerReplyOrNoOp {
3048    fn eq(&self, other: &isize) -> bool {
3049        match self {
3050            IntegerReplyOrNoOp::IntegerReply(s) => *s as isize == *other,
3051            IntegerReplyOrNoOp::NotExists => *other == -2,
3052            IntegerReplyOrNoOp::ExistsButNotRelevant => *other == -1,
3053        }
3054    }
3055}
3056
3057impl PartialEq<usize> for IntegerReplyOrNoOp {
3058    fn eq(&self, other: &usize) -> bool {
3059        match self {
3060            IntegerReplyOrNoOp::IntegerReply(s) => *s == *other,
3061            _ => false,
3062        }
3063    }
3064}
3065
3066impl PartialEq<i32> for IntegerReplyOrNoOp {
3067    fn eq(&self, other: &i32) -> bool {
3068        match self {
3069            IntegerReplyOrNoOp::IntegerReply(s) => *s as i32 == *other,
3070            IntegerReplyOrNoOp::NotExists => *other == -2,
3071            IntegerReplyOrNoOp::ExistsButNotRelevant => *other == -1,
3072        }
3073    }
3074}
3075
3076impl PartialEq<u32> for IntegerReplyOrNoOp {
3077    fn eq(&self, other: &u32) -> bool {
3078        match self {
3079            IntegerReplyOrNoOp::IntegerReply(s) => *s as u32 == *other,
3080            _ => false,
3081        }
3082    }
3083}