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