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
33pub enum Expiry {
35 EX(u64),
37 PX(u64),
39 EXAT(u64),
41 PXAT(u64),
43 PERSIST,
45}
46
47#[derive(Clone, Copy)]
49pub enum SetExpiry {
50 EX(u64),
52 PX(u64),
54 EXAT(u64),
56 PXAT(u64),
58 KEEPTTL,
60}
61
62#[derive(Clone, Copy)]
64pub enum ExistenceCheck {
65 NX,
67 XX,
69}
70
71#[derive(Clone, Copy)]
73pub enum FieldExistenceCheck {
74 FNX,
76 FXX,
78}
79
80#[derive(PartialEq, Eq, Clone, Debug, Copy)]
83pub enum NumericBehavior {
84 NonNumeric,
86 NumberIsInteger,
88 NumberIsFloat,
90}
91
92#[derive(PartialEq, Eq, Copy, Clone, Debug)]
94#[non_exhaustive]
95pub enum ErrorKind {
96 ResponseError,
98 ParseError,
100 AuthenticationFailed,
102 TypeError,
104 ExecAbortError,
106 BusyLoadingError,
108 NoScriptError,
110 InvalidClientConfig,
113 Moved,
115 Ask,
117 TryAgain,
119 ClusterDown,
121 CrossSlot,
123 MasterDown,
125 IoError,
129 ClientError,
131 ExtensionError,
134 ReadOnly,
136 MasterNameNotFoundBySentinel,
138 NoValidReplicasFoundBySentinel,
140 EmptySentinelList,
142 NotBusy,
144 ClusterConnectionNotFound,
146 NoSub,
148
149 #[cfg(feature = "json")]
150 Serialize,
152
153 RESP3NotSupported,
156}
157
158#[derive(PartialEq, Debug, Clone, Copy)]
159pub enum ServerErrorKind {
160 ResponseError,
161 ExecAbortError,
162 BusyLoadingError,
163 NoScriptError,
164 Moved,
165 Ask,
166 TryAgain,
167 ClusterDown,
168 CrossSlot,
169 MasterDown,
170 ReadOnly,
171 NotBusy,
172 NoSub,
173}
174
175#[derive(PartialEq, Debug, Clone)]
176pub enum ServerError {
177 ExtensionError {
178 code: String,
179 detail: Option<String>,
180 },
181 KnownError {
182 kind: ServerErrorKind,
183 detail: Option<String>,
184 },
185}
186
187impl ServerError {
188 pub fn kind(&self) -> Option<ServerErrorKind> {
189 match self {
190 ServerError::ExtensionError { .. } => None,
191 ServerError::KnownError { kind, .. } => Some(*kind),
192 }
193 }
194
195 pub fn code(&self) -> &str {
196 match self {
197 ServerError::ExtensionError { code, .. } => code,
198 ServerError::KnownError { kind, .. } => match kind {
199 ServerErrorKind::ResponseError => "ERR",
200 ServerErrorKind::ExecAbortError => "EXECABORT",
201 ServerErrorKind::BusyLoadingError => "LOADING",
202 ServerErrorKind::NoScriptError => "NOSCRIPT",
203 ServerErrorKind::Moved => "MOVED",
204 ServerErrorKind::Ask => "ASK",
205 ServerErrorKind::TryAgain => "TRYAGAIN",
206 ServerErrorKind::ClusterDown => "CLUSTERDOWN",
207 ServerErrorKind::CrossSlot => "CROSSSLOT",
208 ServerErrorKind::MasterDown => "MASTERDOWN",
209 ServerErrorKind::ReadOnly => "READONLY",
210 ServerErrorKind::NotBusy => "NOTBUSY",
211 ServerErrorKind::NoSub => "NOSUB",
212 },
213 }
214 }
215
216 pub fn details(&self) -> Option<&str> {
217 match self {
218 ServerError::ExtensionError { detail, .. } => detail.as_ref().map(|str| str.as_str()),
219 ServerError::KnownError { detail, .. } => detail.as_ref().map(|str| str.as_str()),
220 }
221 }
222}
223
224impl From<ServerError> for RedisError {
225 fn from(value: ServerError) -> Self {
226 match value {
228 ServerError::ExtensionError { code, detail } => make_extension_error(code, detail),
229 ServerError::KnownError { kind, detail } => {
230 let desc = "An error was signalled by the server";
231 let kind = match kind {
232 ServerErrorKind::ResponseError => ErrorKind::ResponseError,
233 ServerErrorKind::ExecAbortError => ErrorKind::ExecAbortError,
234 ServerErrorKind::BusyLoadingError => ErrorKind::BusyLoadingError,
235 ServerErrorKind::NoScriptError => ErrorKind::NoScriptError,
236 ServerErrorKind::Moved => ErrorKind::Moved,
237 ServerErrorKind::Ask => ErrorKind::Ask,
238 ServerErrorKind::TryAgain => ErrorKind::TryAgain,
239 ServerErrorKind::ClusterDown => ErrorKind::ClusterDown,
240 ServerErrorKind::CrossSlot => ErrorKind::CrossSlot,
241 ServerErrorKind::MasterDown => ErrorKind::MasterDown,
242 ServerErrorKind::ReadOnly => ErrorKind::ReadOnly,
243 ServerErrorKind::NotBusy => ErrorKind::NotBusy,
244 ServerErrorKind::NoSub => ErrorKind::NoSub,
245 };
246 match detail {
247 Some(detail) => RedisError::from((kind, desc, detail)),
248 None => RedisError::from((kind, desc)),
249 }
250 }
251 }
252 }
253}
254
255#[derive(PartialEq, Clone)]
257pub enum Value {
258 Nil,
260 Int(i64),
265 BulkString(Vec<u8>),
267 Array(Vec<Value>),
270 SimpleString(String),
272 Okay,
274 Map(Vec<(Value, Value)>),
276 Attribute {
278 data: Box<Value>,
280 attributes: Vec<(Value, Value)>,
282 },
283 Set(Vec<Value>),
285 Double(f64),
287 Boolean(bool),
289 VerbatimString {
291 format: VerbatimFormat,
293 text: String,
295 },
296 BigNumber(BigInt),
298 Push {
300 kind: PushKind,
302 data: Vec<Value>,
304 },
305 ServerError(ServerError),
307}
308
309#[derive(PartialEq, Clone, Debug)]
311pub enum VerbatimFormat {
312 Unknown(String),
314 Markdown,
316 Text,
318}
319
320#[derive(PartialEq, Clone, Debug)]
322pub enum PushKind {
323 Disconnection,
325 Other(String),
327 Invalidate,
329 Message,
331 PMessage,
333 SMessage,
335 Unsubscribe,
337 PUnsubscribe,
339 SUnsubscribe,
341 Subscribe,
343 PSubscribe,
345 SSubscribe,
347}
348
349impl PushKind {
350 #[cfg(feature = "aio")]
351 pub(crate) fn has_reply(&self) -> bool {
352 matches!(
353 self,
354 &PushKind::Unsubscribe
355 | &PushKind::PUnsubscribe
356 | &PushKind::SUnsubscribe
357 | &PushKind::Subscribe
358 | &PushKind::PSubscribe
359 | &PushKind::SSubscribe
360 )
361 }
362}
363
364impl fmt::Display for VerbatimFormat {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 match self {
367 VerbatimFormat::Markdown => write!(f, "mkd"),
368 VerbatimFormat::Unknown(val) => write!(f, "{val}"),
369 VerbatimFormat::Text => write!(f, "txt"),
370 }
371 }
372}
373
374impl fmt::Display for PushKind {
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 match self {
377 PushKind::Other(kind) => write!(f, "{}", kind),
378 PushKind::Invalidate => write!(f, "invalidate"),
379 PushKind::Message => write!(f, "message"),
380 PushKind::PMessage => write!(f, "pmessage"),
381 PushKind::SMessage => write!(f, "smessage"),
382 PushKind::Unsubscribe => write!(f, "unsubscribe"),
383 PushKind::PUnsubscribe => write!(f, "punsubscribe"),
384 PushKind::SUnsubscribe => write!(f, "sunsubscribe"),
385 PushKind::Subscribe => write!(f, "subscribe"),
386 PushKind::PSubscribe => write!(f, "psubscribe"),
387 PushKind::SSubscribe => write!(f, "ssubscribe"),
388 PushKind::Disconnection => write!(f, "disconnection"),
389 }
390 }
391}
392
393pub enum MapIter<'a> {
394 Array(std::slice::Iter<'a, Value>),
395 Map(std::slice::Iter<'a, (Value, Value)>),
396}
397
398impl<'a> Iterator for MapIter<'a> {
399 type Item = (&'a Value, &'a Value);
400
401 fn next(&mut self) -> Option<Self::Item> {
402 match self {
403 MapIter::Array(iter) => Some((iter.next()?, iter.next()?)),
404 MapIter::Map(iter) => {
405 let (k, v) = iter.next()?;
406 Some((k, v))
407 }
408 }
409 }
410
411 fn size_hint(&self) -> (usize, Option<usize>) {
412 match self {
413 MapIter::Array(iter) => iter.size_hint(),
414 MapIter::Map(iter) => iter.size_hint(),
415 }
416 }
417}
418
419pub enum OwnedMapIter {
420 Array(std::vec::IntoIter<Value>),
421 Map(std::vec::IntoIter<(Value, Value)>),
422}
423
424impl Iterator for OwnedMapIter {
425 type Item = (Value, Value);
426
427 fn next(&mut self) -> Option<Self::Item> {
428 match self {
429 OwnedMapIter::Array(iter) => Some((iter.next()?, iter.next()?)),
430 OwnedMapIter::Map(iter) => iter.next(),
431 }
432 }
433
434 fn size_hint(&self) -> (usize, Option<usize>) {
435 match self {
436 OwnedMapIter::Array(iter) => {
437 let (low, high) = iter.size_hint();
438 (low / 2, high.map(|h| h / 2))
439 }
440 OwnedMapIter::Map(iter) => iter.size_hint(),
441 }
442 }
443}
444
445impl Value {
453 pub fn looks_like_cursor(&self) -> bool {
458 match *self {
459 Value::Array(ref items) => {
460 if items.len() != 2 {
461 return false;
462 }
463 matches!(items[0], Value::BulkString(_)) && matches!(items[1], Value::Array(_))
464 }
465 _ => false,
466 }
467 }
468
469 pub fn as_sequence(&self) -> Option<&[Value]> {
471 match self {
472 Value::Array(items) => Some(&items[..]),
473 Value::Set(items) => Some(&items[..]),
474 Value::Nil => Some(&[]),
475 _ => None,
476 }
477 }
478
479 pub fn into_sequence(self) -> Result<Vec<Value>, Value> {
482 match self {
483 Value::Array(items) => Ok(items),
484 Value::Set(items) => Ok(items),
485 Value::Nil => Ok(vec![]),
486 _ => Err(self),
487 }
488 }
489
490 pub fn as_map_iter(&self) -> Option<MapIter<'_>> {
492 match self {
493 Value::Array(items) => {
494 if items.len() % 2 == 0 {
495 Some(MapIter::Array(items.iter()))
496 } else {
497 None
498 }
499 }
500 Value::Map(items) => Some(MapIter::Map(items.iter())),
501 _ => None,
502 }
503 }
504
505 pub fn into_map_iter(self) -> Result<OwnedMapIter, Value> {
508 match self {
509 Value::Array(items) => {
510 if items.len() % 2 == 0 {
511 Ok(OwnedMapIter::Array(items.into_iter()))
512 } else {
513 Err(Value::Array(items))
514 }
515 }
516 Value::Map(items) => Ok(OwnedMapIter::Map(items.into_iter())),
517 _ => Err(self),
518 }
519 }
520
521 pub fn extract_error(self) -> RedisResult<Self> {
523 match self {
524 Self::Array(val) => Ok(Self::Array(Self::extract_error_vec(val)?)),
525 Self::Map(map) => Ok(Self::Map(Self::extract_error_map(map)?)),
526 Self::Attribute { data, attributes } => {
527 let data = Box::new((*data).extract_error()?);
528 let attributes = Self::extract_error_map(attributes)?;
529 Ok(Value::Attribute { data, attributes })
530 }
531 Self::Set(set) => Ok(Self::Set(Self::extract_error_vec(set)?)),
532 Self::Push { kind, data } => Ok(Self::Push {
533 kind,
534 data: Self::extract_error_vec(data)?,
535 }),
536 Value::ServerError(err) => Err(err.into()),
537 _ => Ok(self),
538 }
539 }
540
541 pub(crate) fn extract_error_vec(vec: Vec<Self>) -> RedisResult<Vec<Self>> {
542 vec.into_iter()
543 .map(Self::extract_error)
544 .collect::<RedisResult<Vec<_>>>()
545 }
546
547 pub(crate) fn extract_error_map(map: Vec<(Self, Self)>) -> RedisResult<Vec<(Self, Self)>> {
548 let mut vec = Vec::with_capacity(map.len());
549 for (key, value) in map.into_iter() {
550 vec.push((key.extract_error()?, value.extract_error()?));
551 }
552 Ok(vec)
553 }
554}
555
556impl fmt::Debug for Value {
557 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
558 match *self {
559 Value::Nil => write!(fmt, "nil"),
560 Value::Int(val) => write!(fmt, "int({val:?})"),
561 Value::BulkString(ref val) => match from_utf8(val) {
562 Ok(x) => write!(fmt, "bulk-string('{x:?}')"),
563 Err(_) => write!(fmt, "binary-data({val:?})"),
564 },
565 Value::Array(ref values) => write!(fmt, "array({values:?})"),
566 Value::Push { ref kind, ref data } => write!(fmt, "push({kind:?}, {data:?})"),
567 Value::Okay => write!(fmt, "ok"),
568 Value::SimpleString(ref s) => write!(fmt, "simple-string({s:?})"),
569 Value::Map(ref values) => write!(fmt, "map({values:?})"),
570 Value::Attribute {
571 ref data,
572 attributes: _,
573 } => write!(fmt, "attribute({data:?})"),
574 Value::Set(ref values) => write!(fmt, "set({values:?})"),
575 Value::Double(ref d) => write!(fmt, "double({d:?})"),
576 Value::Boolean(ref b) => write!(fmt, "boolean({b:?})"),
577 Value::VerbatimString {
578 ref format,
579 ref text,
580 } => {
581 write!(fmt, "verbatim-string({:?},{:?})", format, text)
582 }
583 Value::BigNumber(ref m) => write!(fmt, "big-number({:?})", m),
584 Value::ServerError(ref err) => match err.details() {
585 Some(details) => write!(fmt, "Server error: `{}: {details}`", err.code()),
586 None => write!(fmt, "Server error: `{}`", err.code()),
587 },
588 }
589 }
590}
591
592pub struct RedisError {
597 repr: ErrorRepr,
598}
599
600#[cfg(feature = "json")]
601impl From<serde_json::Error> for RedisError {
602 fn from(serde_err: serde_json::Error) -> RedisError {
603 RedisError::from((
604 ErrorKind::Serialize,
605 "Serialization Error",
606 format!("{serde_err}"),
607 ))
608 }
609}
610
611#[derive(Debug)]
612enum ErrorRepr {
613 WithDescription(ErrorKind, &'static str),
614 WithDescriptionAndDetail(ErrorKind, &'static str, String),
615 ExtensionError(String, String),
616 IoError(io::Error),
617}
618
619impl PartialEq for RedisError {
620 fn eq(&self, other: &RedisError) -> bool {
621 match (&self.repr, &other.repr) {
622 (&ErrorRepr::WithDescription(kind_a, _), &ErrorRepr::WithDescription(kind_b, _)) => {
623 kind_a == kind_b
624 }
625 (
626 &ErrorRepr::WithDescriptionAndDetail(kind_a, _, _),
627 &ErrorRepr::WithDescriptionAndDetail(kind_b, _, _),
628 ) => kind_a == kind_b,
629 (ErrorRepr::ExtensionError(a, _), ErrorRepr::ExtensionError(b, _)) => *a == *b,
630 _ => false,
631 }
632 }
633}
634
635impl From<io::Error> for RedisError {
636 fn from(err: io::Error) -> RedisError {
637 RedisError {
638 repr: ErrorRepr::IoError(err),
639 }
640 }
641}
642
643impl From<Utf8Error> for RedisError {
644 fn from(_: Utf8Error) -> RedisError {
645 RedisError {
646 repr: ErrorRepr::WithDescription(ErrorKind::TypeError, "Invalid UTF-8"),
647 }
648 }
649}
650
651impl From<NulError> for RedisError {
652 fn from(err: NulError) -> RedisError {
653 RedisError {
654 repr: ErrorRepr::WithDescriptionAndDetail(
655 ErrorKind::TypeError,
656 "Value contains interior nul terminator",
657 err.to_string(),
658 ),
659 }
660 }
661}
662
663#[cfg(feature = "tls-native-tls")]
664impl From<native_tls::Error> for RedisError {
665 fn from(err: native_tls::Error) -> RedisError {
666 RedisError {
667 repr: ErrorRepr::WithDescriptionAndDetail(
668 ErrorKind::IoError,
669 "TLS error",
670 err.to_string(),
671 ),
672 }
673 }
674}
675
676#[cfg(feature = "tls-rustls")]
677impl From<rustls::Error> for RedisError {
678 fn from(err: rustls::Error) -> RedisError {
679 RedisError {
680 repr: ErrorRepr::WithDescriptionAndDetail(
681 ErrorKind::IoError,
682 "TLS error",
683 err.to_string(),
684 ),
685 }
686 }
687}
688
689#[cfg(feature = "tls-rustls")]
690impl From<rustls::pki_types::InvalidDnsNameError> for RedisError {
691 fn from(err: rustls::pki_types::InvalidDnsNameError) -> RedisError {
692 RedisError {
693 repr: ErrorRepr::WithDescriptionAndDetail(
694 ErrorKind::IoError,
695 "TLS Error",
696 err.to_string(),
697 ),
698 }
699 }
700}
701
702#[cfg(feature = "tls-rustls")]
703impl From<rustls_native_certs::Error> for RedisError {
704 fn from(err: rustls_native_certs::Error) -> RedisError {
705 RedisError {
706 repr: ErrorRepr::WithDescriptionAndDetail(
707 ErrorKind::IoError,
708 "Fetch certs Error",
709 err.to_string(),
710 ),
711 }
712 }
713}
714
715#[cfg(feature = "uuid")]
716impl From<uuid::Error> for RedisError {
717 fn from(err: uuid::Error) -> RedisError {
718 RedisError {
719 repr: ErrorRepr::WithDescriptionAndDetail(
720 ErrorKind::TypeError,
721 "Value is not a valid UUID",
722 err.to_string(),
723 ),
724 }
725 }
726}
727
728impl From<FromUtf8Error> for RedisError {
729 fn from(_: FromUtf8Error) -> RedisError {
730 RedisError {
731 repr: ErrorRepr::WithDescription(ErrorKind::TypeError, "Cannot convert from UTF-8"),
732 }
733 }
734}
735
736impl From<(ErrorKind, &'static str)> for RedisError {
737 fn from((kind, desc): (ErrorKind, &'static str)) -> RedisError {
738 RedisError {
739 repr: ErrorRepr::WithDescription(kind, desc),
740 }
741 }
742}
743
744impl From<(ErrorKind, &'static str, String)> for RedisError {
745 fn from((kind, desc, detail): (ErrorKind, &'static str, String)) -> RedisError {
746 RedisError {
747 repr: ErrorRepr::WithDescriptionAndDetail(kind, desc, detail),
748 }
749 }
750}
751
752impl error::Error for RedisError {
753 #[allow(deprecated)]
754 fn description(&self) -> &str {
755 match self.repr {
756 ErrorRepr::WithDescription(_, desc) => desc,
757 ErrorRepr::WithDescriptionAndDetail(_, desc, _) => desc,
758 ErrorRepr::ExtensionError(_, _) => "extension error",
759 ErrorRepr::IoError(ref err) => err.description(),
760 }
761 }
762
763 fn cause(&self) -> Option<&dyn error::Error> {
764 match self.repr {
765 ErrorRepr::IoError(ref err) => Some(err as &dyn error::Error),
766 _ => None,
767 }
768 }
769
770 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
771 match self.repr {
772 ErrorRepr::IoError(ref err) => Some(err),
773 _ => None,
774 }
775 }
776}
777
778impl fmt::Display for RedisError {
779 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
780 match self.repr {
781 ErrorRepr::WithDescription(kind, desc) => {
782 desc.fmt(f)?;
783 f.write_str("- ")?;
784 fmt::Debug::fmt(&kind, f)
785 }
786 ErrorRepr::WithDescriptionAndDetail(kind, desc, ref detail) => {
787 desc.fmt(f)?;
788 f.write_str(" - ")?;
789 fmt::Debug::fmt(&kind, f)?;
790 f.write_str(": ")?;
791 detail.fmt(f)
792 }
793 ErrorRepr::ExtensionError(ref code, ref detail) => {
794 code.fmt(f)?;
795 f.write_str(": ")?;
796 detail.fmt(f)
797 }
798 ErrorRepr::IoError(ref err) => err.fmt(f),
799 }
800 }
801}
802
803impl fmt::Debug for RedisError {
804 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
805 fmt::Display::fmt(self, f)
806 }
807}
808
809#[non_exhaustive]
811pub enum RetryMethod {
812 Reconnect,
814 NoRetry,
816 RetryImmediately,
818 WaitAndRetry,
820 AskRedirect,
822 MovedRedirect,
824 ReconnectFromInitialConnections,
826}
827
828impl RedisError {
830 pub fn kind(&self) -> ErrorKind {
832 match self.repr {
833 ErrorRepr::WithDescription(kind, _)
834 | ErrorRepr::WithDescriptionAndDetail(kind, _, _) => kind,
835 ErrorRepr::ExtensionError(_, _) => ErrorKind::ExtensionError,
836 ErrorRepr::IoError(_) => ErrorKind::IoError,
837 }
838 }
839
840 pub fn detail(&self) -> Option<&str> {
842 match self.repr {
843 ErrorRepr::WithDescriptionAndDetail(_, _, ref detail)
844 | ErrorRepr::ExtensionError(_, ref detail) => Some(detail.as_str()),
845 _ => None,
846 }
847 }
848
849 pub fn code(&self) -> Option<&str> {
851 match self.kind() {
852 ErrorKind::ResponseError => Some("ERR"),
853 ErrorKind::ExecAbortError => Some("EXECABORT"),
854 ErrorKind::BusyLoadingError => Some("LOADING"),
855 ErrorKind::NoScriptError => Some("NOSCRIPT"),
856 ErrorKind::Moved => Some("MOVED"),
857 ErrorKind::Ask => Some("ASK"),
858 ErrorKind::TryAgain => Some("TRYAGAIN"),
859 ErrorKind::ClusterDown => Some("CLUSTERDOWN"),
860 ErrorKind::CrossSlot => Some("CROSSSLOT"),
861 ErrorKind::MasterDown => Some("MASTERDOWN"),
862 ErrorKind::ReadOnly => Some("READONLY"),
863 ErrorKind::NotBusy => Some("NOTBUSY"),
864 _ => match self.repr {
865 ErrorRepr::ExtensionError(ref code, _) => Some(code),
866 _ => None,
867 },
868 }
869 }
870
871 pub fn category(&self) -> &str {
873 match self.kind() {
874 ErrorKind::ResponseError => "response error",
875 ErrorKind::AuthenticationFailed => "authentication failed",
876 ErrorKind::TypeError => "type error",
877 ErrorKind::ExecAbortError => "script execution aborted",
878 ErrorKind::BusyLoadingError => "busy loading",
879 ErrorKind::NoScriptError => "no script",
880 ErrorKind::InvalidClientConfig => "invalid client config",
881 ErrorKind::Moved => "key moved",
882 ErrorKind::Ask => "key moved (ask)",
883 ErrorKind::TryAgain => "try again",
884 ErrorKind::ClusterDown => "cluster down",
885 ErrorKind::CrossSlot => "cross-slot",
886 ErrorKind::MasterDown => "master down",
887 ErrorKind::IoError => "I/O error",
888 ErrorKind::ExtensionError => "extension error",
889 ErrorKind::ClientError => "client error",
890 ErrorKind::ReadOnly => "read-only",
891 ErrorKind::MasterNameNotFoundBySentinel => "master name not found by sentinel",
892 ErrorKind::NoValidReplicasFoundBySentinel => "no valid replicas found by sentinel",
893 ErrorKind::EmptySentinelList => "empty sentinel list",
894 ErrorKind::NotBusy => "not busy",
895 ErrorKind::ClusterConnectionNotFound => "connection to node in cluster not found",
896 #[cfg(feature = "json")]
897 ErrorKind::Serialize => "serializing",
898 ErrorKind::RESP3NotSupported => "resp3 is not supported by server",
899 ErrorKind::ParseError => "parse error",
900 ErrorKind::NoSub => {
901 "Server declined unsubscribe related command in non-subscribed mode"
902 }
903 }
904 }
905
906 pub fn is_io_error(&self) -> bool {
908 self.kind() == ErrorKind::IoError
909 }
910
911 pub(crate) fn as_io_error(&self) -> Option<&io::Error> {
912 match &self.repr {
913 ErrorRepr::IoError(e) => Some(e),
914 _ => None,
915 }
916 }
917
918 pub fn is_cluster_error(&self) -> bool {
920 matches!(
921 self.kind(),
922 ErrorKind::Moved | ErrorKind::Ask | ErrorKind::TryAgain | ErrorKind::ClusterDown
923 )
924 }
925
926 pub fn is_connection_refusal(&self) -> bool {
931 match self.repr {
932 ErrorRepr::IoError(ref err) => {
933 #[allow(clippy::match_like_matches_macro)]
934 match err.kind() {
935 io::ErrorKind::ConnectionRefused => true,
936 io::ErrorKind::NotFound => cfg!(unix),
940 _ => false,
941 }
942 }
943 _ => false,
944 }
945 }
946
947 pub fn is_timeout(&self) -> bool {
950 match self.repr {
951 ErrorRepr::IoError(ref err) => matches!(
952 err.kind(),
953 io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock
954 ),
955 _ => false,
956 }
957 }
958
959 pub fn is_connection_dropped(&self) -> bool {
961 match self.repr {
962 ErrorRepr::IoError(ref err) => matches!(
963 err.kind(),
964 io::ErrorKind::BrokenPipe
965 | io::ErrorKind::ConnectionReset
966 | io::ErrorKind::UnexpectedEof
967 ),
968 _ => false,
969 }
970 }
971
972 pub fn is_unrecoverable_error(&self) -> bool {
974 match self.retry_method() {
975 RetryMethod::Reconnect => true,
976 RetryMethod::ReconnectFromInitialConnections => true,
977
978 RetryMethod::NoRetry => false,
979 RetryMethod::RetryImmediately => false,
980 RetryMethod::WaitAndRetry => false,
981 RetryMethod::AskRedirect => false,
982 RetryMethod::MovedRedirect => false,
983 }
984 }
985
986 pub fn redirect_node(&self) -> Option<(&str, u16)> {
990 match self.kind() {
991 ErrorKind::Ask | ErrorKind::Moved => (),
992 _ => return None,
993 }
994 let mut iter = self.detail()?.split_ascii_whitespace();
995 let slot_id: u16 = iter.next()?.parse().ok()?;
996 let addr = iter.next()?;
997 Some((addr, slot_id))
998 }
999
1000 #[deprecated(note = "use code() instead")]
1006 pub fn extension_error_code(&self) -> Option<&str> {
1007 match self.repr {
1008 ErrorRepr::ExtensionError(ref code, _) => Some(code),
1009 _ => None,
1010 }
1011 }
1012
1013 #[cfg(feature = "connection-manager")] pub(crate) fn clone_mostly(&self, ioerror_description: &'static str) -> Self {
1022 let repr = match self.repr {
1023 ErrorRepr::WithDescription(kind, desc) => ErrorRepr::WithDescription(kind, desc),
1024 ErrorRepr::WithDescriptionAndDetail(kind, desc, ref detail) => {
1025 ErrorRepr::WithDescriptionAndDetail(kind, desc, detail.clone())
1026 }
1027 ErrorRepr::ExtensionError(ref code, ref detail) => {
1028 ErrorRepr::ExtensionError(code.clone(), detail.clone())
1029 }
1030 ErrorRepr::IoError(ref e) => ErrorRepr::IoError(io::Error::new(
1031 e.kind(),
1032 format!("{ioerror_description}: {e}"),
1033 )),
1034 };
1035 Self { repr }
1036 }
1037
1038 pub fn retry_method(&self) -> RetryMethod {
1045 match self.kind() {
1046 ErrorKind::Moved => RetryMethod::MovedRedirect,
1047 ErrorKind::Ask => RetryMethod::AskRedirect,
1048
1049 ErrorKind::TryAgain => RetryMethod::WaitAndRetry,
1050 ErrorKind::MasterDown => RetryMethod::WaitAndRetry,
1051 ErrorKind::ClusterDown => RetryMethod::WaitAndRetry,
1052 ErrorKind::BusyLoadingError => RetryMethod::WaitAndRetry,
1053 ErrorKind::MasterNameNotFoundBySentinel => RetryMethod::WaitAndRetry,
1054 ErrorKind::NoValidReplicasFoundBySentinel => RetryMethod::WaitAndRetry,
1055
1056 ErrorKind::ResponseError => RetryMethod::NoRetry,
1057 ErrorKind::ReadOnly => RetryMethod::NoRetry,
1058 ErrorKind::ExtensionError => RetryMethod::NoRetry,
1059 ErrorKind::ExecAbortError => RetryMethod::NoRetry,
1060 ErrorKind::TypeError => RetryMethod::NoRetry,
1061 ErrorKind::NoScriptError => RetryMethod::NoRetry,
1062 ErrorKind::InvalidClientConfig => RetryMethod::NoRetry,
1063 ErrorKind::CrossSlot => RetryMethod::NoRetry,
1064 ErrorKind::ClientError => RetryMethod::NoRetry,
1065 ErrorKind::EmptySentinelList => RetryMethod::NoRetry,
1066 ErrorKind::NotBusy => RetryMethod::NoRetry,
1067 #[cfg(feature = "json")]
1068 ErrorKind::Serialize => RetryMethod::NoRetry,
1069 ErrorKind::RESP3NotSupported => RetryMethod::NoRetry,
1070 ErrorKind::NoSub => RetryMethod::NoRetry,
1071
1072 ErrorKind::ParseError => RetryMethod::Reconnect,
1073 ErrorKind::AuthenticationFailed => RetryMethod::Reconnect,
1074 ErrorKind::ClusterConnectionNotFound => RetryMethod::ReconnectFromInitialConnections,
1075
1076 ErrorKind::IoError => match &self.repr {
1077 ErrorRepr::IoError(err) => match err.kind() {
1078 io::ErrorKind::ConnectionRefused => RetryMethod::Reconnect,
1079 io::ErrorKind::NotFound => RetryMethod::Reconnect,
1080 io::ErrorKind::ConnectionReset => RetryMethod::Reconnect,
1081 io::ErrorKind::ConnectionAborted => RetryMethod::Reconnect,
1082 io::ErrorKind::NotConnected => RetryMethod::Reconnect,
1083 io::ErrorKind::BrokenPipe => RetryMethod::Reconnect,
1084 io::ErrorKind::UnexpectedEof => RetryMethod::Reconnect,
1085
1086 io::ErrorKind::PermissionDenied => RetryMethod::NoRetry,
1087 io::ErrorKind::Unsupported => RetryMethod::NoRetry,
1088
1089 _ => RetryMethod::RetryImmediately,
1090 },
1091 _ => RetryMethod::RetryImmediately,
1092 },
1093 }
1094 }
1095}
1096
1097pub fn make_extension_error(code: String, detail: Option<String>) -> RedisError {
1111 RedisError {
1112 repr: ErrorRepr::ExtensionError(
1113 code,
1114 match detail {
1115 Some(x) => x,
1116 None => "Unknown extension error encountered".to_string(),
1117 },
1118 ),
1119 }
1120}
1121
1122pub type RedisResult<T> = Result<T, RedisError>;
1124
1125#[cfg(feature = "aio")]
1127pub type RedisFuture<'a, T> = futures_util::future::BoxFuture<'a, RedisResult<T>>;
1128
1129#[derive(Debug, Clone)]
1131pub struct InfoDict {
1132 map: HashMap<String, Value>,
1133}
1134
1135impl InfoDict {
1152 pub fn new(kvpairs: &str) -> InfoDict {
1157 let mut map = HashMap::new();
1158 for line in kvpairs.lines() {
1159 if line.is_empty() || line.starts_with('#') {
1160 continue;
1161 }
1162 let mut p = line.splitn(2, ':');
1163 let (k, v) = match (p.next(), p.next()) {
1164 (Some(k), Some(v)) => (k.to_string(), v.to_string()),
1165 _ => continue,
1166 };
1167 map.insert(k, Value::SimpleString(v));
1168 }
1169 InfoDict { map }
1170 }
1171
1172 pub fn get<T: FromRedisValue>(&self, key: &str) -> Option<T> {
1175 match self.find(&key) {
1176 Some(x) => from_redis_value(x).ok(),
1177 None => None,
1178 }
1179 }
1180
1181 pub fn find(&self, key: &&str) -> Option<&Value> {
1183 self.map.get(*key)
1184 }
1185
1186 pub fn contains_key(&self, key: &&str) -> bool {
1188 self.find(key).is_some()
1189 }
1190
1191 pub fn len(&self) -> usize {
1193 self.map.len()
1194 }
1195
1196 pub fn is_empty(&self) -> bool {
1198 self.map.is_empty()
1199 }
1200}
1201
1202impl Deref for InfoDict {
1203 type Target = HashMap<String, Value>;
1204
1205 fn deref(&self) -> &Self::Target {
1206 &self.map
1207 }
1208}
1209
1210#[derive(Debug, Clone, Eq, PartialEq)]
1214pub enum Role {
1215 Primary {
1217 replication_offset: u64,
1219 replicas: Vec<ReplicaInfo>,
1221 },
1222 Replica {
1224 primary_ip: String,
1226 primary_port: u16,
1228 replication_state: String,
1230 data_received: u64,
1232 },
1233 Sentinel {
1235 primary_names: Vec<String>,
1237 },
1238}
1239
1240#[derive(Debug, Clone, Eq, PartialEq)]
1244pub struct ReplicaInfo {
1245 pub ip: String,
1247 pub port: u16,
1249 pub replication_offset: i64,
1251}
1252
1253impl FromRedisValue for ReplicaInfo {
1254 fn from_redis_value(v: &Value) -> RedisResult<Self> {
1255 Self::from_owned_redis_value(v.clone())
1256 }
1257
1258 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
1259 let v = match get_owned_inner_value(v).into_sequence() {
1260 Ok(v) => v,
1261 Err(v) => invalid_type_error!(v, "Replica response should be an array"),
1262 };
1263 if v.len() < 3 {
1264 invalid_type_error!(v, "Replica array is too short, expected 3 elements")
1265 }
1266 let mut v = v.into_iter();
1267 let ip = from_owned_redis_value(v.next().expect("len was checked"))?;
1268 let port = from_owned_redis_value(v.next().expect("len was checked"))?;
1269 let offset = from_owned_redis_value(v.next().expect("len was checked"))?;
1270 Ok(ReplicaInfo {
1271 ip,
1272 port,
1273 replication_offset: offset,
1274 })
1275 }
1276}
1277
1278impl FromRedisValue for Role {
1279 fn from_redis_value(v: &Value) -> RedisResult<Self> {
1280 Self::from_owned_redis_value(v.clone())
1281 }
1282
1283 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
1284 let v = match get_owned_inner_value(v).into_sequence() {
1285 Ok(v) => v,
1286 Err(v) => invalid_type_error!(v, "Role response should be an array"),
1287 };
1288 if v.len() < 2 {
1289 invalid_type_error!(v, "Role array is too short, expected at least 2 elements")
1290 }
1291 match &v[0] {
1292 Value::BulkString(role) => match role.as_slice() {
1293 b"master" => Role::new_primary(v),
1294 b"slave" => Role::new_replica(v),
1295 b"sentinel" => Role::new_sentinel(v),
1296 _ => invalid_type_error!(v, "Role type is not master, slave or sentinel"),
1297 },
1298 _ => invalid_type_error!(v, "Role type is not a bulk string"),
1299 }
1300 }
1301}
1302
1303impl Role {
1304 fn new_primary(values: Vec<Value>) -> RedisResult<Self> {
1305 if values.len() < 3 {
1306 invalid_type_error!(
1307 values,
1308 "Role primary response too short, expected 3 elements"
1309 )
1310 }
1311
1312 let mut values = values.into_iter();
1313 _ = values.next();
1314
1315 let replication_offset = from_owned_redis_value(values.next().expect("len was checked"))?;
1316 let replicas = from_owned_redis_value(values.next().expect("len was checked"))?;
1317
1318 Ok(Role::Primary {
1319 replication_offset,
1320 replicas,
1321 })
1322 }
1323
1324 fn new_replica(values: Vec<Value>) -> RedisResult<Self> {
1325 if values.len() < 5 {
1326 invalid_type_error!(
1327 values,
1328 "Role replica response too short, expected 5 elements"
1329 )
1330 }
1331
1332 let mut values = values.into_iter();
1333 _ = values.next();
1334
1335 let primary_ip = from_owned_redis_value(values.next().expect("len was checked"))?;
1336 let primary_port = from_owned_redis_value(values.next().expect("len was checked"))?;
1337 let replication_state = from_owned_redis_value(values.next().expect("len was checked"))?;
1338 let data_received = from_owned_redis_value(values.next().expect("len was checked"))?;
1339
1340 Ok(Role::Replica {
1341 primary_ip,
1342 primary_port,
1343 replication_state,
1344 data_received,
1345 })
1346 }
1347
1348 fn new_sentinel(values: Vec<Value>) -> RedisResult<Self> {
1349 if values.len() < 2 {
1350 invalid_type_error!(
1351 values,
1352 "Role sentinel response too short, expected at least 2 elements"
1353 )
1354 }
1355 let second_val = values.into_iter().nth(1).expect("len was checked");
1356 let primary_names = from_owned_redis_value(second_val)?;
1357 Ok(Role::Sentinel { primary_names })
1358 }
1359}
1360
1361pub trait RedisWrite {
1363 fn write_arg(&mut self, arg: &[u8]);
1365
1366 fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
1368 self.write_arg(arg.to_string().as_bytes())
1369 }
1370
1371 fn writer_for_next_arg(&mut self) -> impl std::io::Write + '_;
1380
1381 fn reserve_space_for_args(&mut self, additional: impl IntoIterator<Item = usize>) {
1413 let _do_nothing = additional;
1416 }
1417
1418 #[cfg(feature = "bytes")]
1419 fn bufmut_for_next_arg(&mut self, capacity: usize) -> impl bytes::BufMut + '_ {
1432 struct Wrapper<'a> {
1440 buf: Vec<u8>,
1442 writer: Box<dyn std::io::Write + 'a>,
1444 }
1445 unsafe impl bytes::BufMut for Wrapper<'_> {
1446 fn remaining_mut(&self) -> usize {
1447 self.buf.remaining_mut()
1448 }
1449
1450 unsafe fn advance_mut(&mut self, cnt: usize) {
1451 self.buf.advance_mut(cnt);
1452 }
1453
1454 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
1455 self.buf.chunk_mut()
1456 }
1457
1458 fn put<T: bytes::buf::Buf>(&mut self, src: T)
1460 where
1461 Self: Sized,
1462 {
1463 self.buf.put(src);
1464 }
1465
1466 fn put_slice(&mut self, src: &[u8]) {
1467 self.buf.put_slice(src);
1468 }
1469
1470 fn put_bytes(&mut self, val: u8, cnt: usize) {
1471 self.buf.put_bytes(val, cnt);
1472 }
1473 }
1474 impl Drop for Wrapper<'_> {
1475 fn drop(&mut self) {
1476 self.writer.write_all(&self.buf).unwrap()
1477 }
1478 }
1479
1480 Wrapper {
1481 buf: Vec::with_capacity(capacity),
1482 writer: Box::new(self.writer_for_next_arg()),
1483 }
1484 }
1485}
1486
1487impl RedisWrite for Vec<Vec<u8>> {
1488 fn write_arg(&mut self, arg: &[u8]) {
1489 self.push(arg.to_owned());
1490 }
1491
1492 fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
1493 self.push(arg.to_string().into_bytes())
1494 }
1495
1496 fn writer_for_next_arg(&mut self) -> impl std::io::Write + '_ {
1497 self.push(Vec::new());
1498 self.last_mut().unwrap()
1499 }
1500
1501 fn reserve_space_for_args(&mut self, additional: impl IntoIterator<Item = usize>) {
1502 self.reserve(additional.into_iter().count());
1507 }
1508
1509 #[cfg(feature = "bytes")]
1510 fn bufmut_for_next_arg(&mut self, capacity: usize) -> impl bytes::BufMut + '_ {
1511 self.push(Vec::with_capacity(capacity));
1512 self.last_mut().unwrap()
1513 }
1514}
1515
1516pub trait ToRedisArgs: Sized {
1520 fn to_redis_args(&self) -> Vec<Vec<u8>> {
1526 let mut out = Vec::new();
1527 self.write_redis_args(&mut out);
1528 out
1529 }
1530
1531 fn write_redis_args<W>(&self, out: &mut W)
1536 where
1537 W: ?Sized + RedisWrite;
1538
1539 fn describe_numeric_behavior(&self) -> NumericBehavior {
1544 NumericBehavior::NonNumeric
1545 }
1546
1547 fn num_of_args(&self) -> usize {
1554 1
1555 }
1556
1557 #[doc(hidden)]
1560 fn write_args_from_slice<W>(items: &[Self], out: &mut W)
1561 where
1562 W: ?Sized + RedisWrite,
1563 {
1564 Self::make_arg_iter_ref(items.iter(), out)
1565 }
1566
1567 #[doc(hidden)]
1570 fn make_arg_iter_ref<'a, I, W>(items: I, out: &mut W)
1571 where
1572 W: ?Sized + RedisWrite,
1573 I: Iterator<Item = &'a Self>,
1574 Self: 'a,
1575 {
1576 for item in items {
1577 item.write_redis_args(out);
1578 }
1579 }
1580
1581 #[doc(hidden)]
1582 fn is_single_vec_arg(items: &[Self]) -> bool {
1583 items.len() == 1 && items[0].num_of_args() <= 1
1584 }
1585}
1586
1587macro_rules! itoa_based_to_redis_impl {
1588 ($t:ty, $numeric:expr) => {
1589 impl ToRedisArgs for $t {
1590 fn write_redis_args<W>(&self, out: &mut W)
1591 where
1592 W: ?Sized + RedisWrite,
1593 {
1594 let mut buf = ::itoa::Buffer::new();
1595 let s = buf.format(*self);
1596 out.write_arg(s.as_bytes())
1597 }
1598
1599 fn describe_numeric_behavior(&self) -> NumericBehavior {
1600 $numeric
1601 }
1602 }
1603 };
1604}
1605
1606macro_rules! non_zero_itoa_based_to_redis_impl {
1607 ($t:ty, $numeric:expr) => {
1608 impl ToRedisArgs for $t {
1609 fn write_redis_args<W>(&self, out: &mut W)
1610 where
1611 W: ?Sized + RedisWrite,
1612 {
1613 let mut buf = ::itoa::Buffer::new();
1614 let s = buf.format(self.get());
1615 out.write_arg(s.as_bytes())
1616 }
1617
1618 fn describe_numeric_behavior(&self) -> NumericBehavior {
1619 $numeric
1620 }
1621 }
1622 };
1623}
1624
1625macro_rules! ryu_based_to_redis_impl {
1626 ($t:ty, $numeric:expr) => {
1627 impl ToRedisArgs for $t {
1628 fn write_redis_args<W>(&self, out: &mut W)
1629 where
1630 W: ?Sized + RedisWrite,
1631 {
1632 let mut buf = ::ryu::Buffer::new();
1633 let s = buf.format(*self);
1634 out.write_arg(s.as_bytes())
1635 }
1636
1637 fn describe_numeric_behavior(&self) -> NumericBehavior {
1638 $numeric
1639 }
1640 }
1641 };
1642}
1643
1644impl ToRedisArgs for u8 {
1645 fn write_redis_args<W>(&self, out: &mut W)
1646 where
1647 W: ?Sized + RedisWrite,
1648 {
1649 let mut buf = ::itoa::Buffer::new();
1650 let s = buf.format(*self);
1651 out.write_arg(s.as_bytes())
1652 }
1653
1654 fn write_args_from_slice<W>(items: &[u8], out: &mut W)
1655 where
1656 W: ?Sized + RedisWrite,
1657 {
1658 out.write_arg(items);
1659 }
1660
1661 fn is_single_vec_arg(_items: &[u8]) -> bool {
1662 true
1663 }
1664}
1665
1666itoa_based_to_redis_impl!(i8, NumericBehavior::NumberIsInteger);
1667itoa_based_to_redis_impl!(i16, NumericBehavior::NumberIsInteger);
1668itoa_based_to_redis_impl!(u16, NumericBehavior::NumberIsInteger);
1669itoa_based_to_redis_impl!(i32, NumericBehavior::NumberIsInteger);
1670itoa_based_to_redis_impl!(u32, NumericBehavior::NumberIsInteger);
1671itoa_based_to_redis_impl!(i64, NumericBehavior::NumberIsInteger);
1672itoa_based_to_redis_impl!(u64, NumericBehavior::NumberIsInteger);
1673itoa_based_to_redis_impl!(isize, NumericBehavior::NumberIsInteger);
1674itoa_based_to_redis_impl!(usize, NumericBehavior::NumberIsInteger);
1675
1676non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU8, NumericBehavior::NumberIsInteger);
1677non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI8, NumericBehavior::NumberIsInteger);
1678non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU16, NumericBehavior::NumberIsInteger);
1679non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI16, NumericBehavior::NumberIsInteger);
1680non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU32, NumericBehavior::NumberIsInteger);
1681non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI32, NumericBehavior::NumberIsInteger);
1682non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU64, NumericBehavior::NumberIsInteger);
1683non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI64, NumericBehavior::NumberIsInteger);
1684non_zero_itoa_based_to_redis_impl!(core::num::NonZeroUsize, NumericBehavior::NumberIsInteger);
1685non_zero_itoa_based_to_redis_impl!(core::num::NonZeroIsize, NumericBehavior::NumberIsInteger);
1686
1687ryu_based_to_redis_impl!(f32, NumericBehavior::NumberIsFloat);
1688ryu_based_to_redis_impl!(f64, NumericBehavior::NumberIsFloat);
1689
1690#[cfg(any(
1691 feature = "rust_decimal",
1692 feature = "bigdecimal",
1693 feature = "num-bigint"
1694))]
1695macro_rules! bignum_to_redis_impl {
1696 ($t:ty) => {
1697 impl ToRedisArgs for $t {
1698 fn write_redis_args<W>(&self, out: &mut W)
1699 where
1700 W: ?Sized + RedisWrite,
1701 {
1702 out.write_arg(&self.to_string().into_bytes())
1703 }
1704 }
1705 };
1706}
1707
1708#[cfg(feature = "rust_decimal")]
1709bignum_to_redis_impl!(rust_decimal::Decimal);
1710#[cfg(feature = "bigdecimal")]
1711bignum_to_redis_impl!(bigdecimal::BigDecimal);
1712#[cfg(feature = "num-bigint")]
1713bignum_to_redis_impl!(num_bigint::BigInt);
1714#[cfg(feature = "num-bigint")]
1715bignum_to_redis_impl!(num_bigint::BigUint);
1716
1717impl ToRedisArgs for bool {
1718 fn write_redis_args<W>(&self, out: &mut W)
1719 where
1720 W: ?Sized + RedisWrite,
1721 {
1722 out.write_arg(if *self { b"1" } else { b"0" })
1723 }
1724}
1725
1726impl ToRedisArgs for String {
1727 fn write_redis_args<W>(&self, out: &mut W)
1728 where
1729 W: ?Sized + RedisWrite,
1730 {
1731 out.write_arg(self.as_bytes())
1732 }
1733}
1734
1735impl ToRedisArgs for &str {
1736 fn write_redis_args<W>(&self, out: &mut W)
1737 where
1738 W: ?Sized + RedisWrite,
1739 {
1740 out.write_arg(self.as_bytes())
1741 }
1742}
1743
1744impl<'a, T> ToRedisArgs for Cow<'a, T>
1745where
1746 T: ToOwned + ?Sized,
1747 &'a T: ToRedisArgs,
1748 for<'b> &'b T::Owned: ToRedisArgs,
1749{
1750 fn write_redis_args<W>(&self, out: &mut W)
1751 where
1752 W: ?Sized + RedisWrite,
1753 {
1754 match self {
1755 Cow::Borrowed(inner) => inner.write_redis_args(out),
1756 Cow::Owned(inner) => inner.write_redis_args(out),
1757 }
1758 }
1759}
1760
1761impl<T: ToRedisArgs> ToRedisArgs for Vec<T> {
1762 fn write_redis_args<W>(&self, out: &mut W)
1763 where
1764 W: ?Sized + RedisWrite,
1765 {
1766 ToRedisArgs::write_args_from_slice(self, out)
1767 }
1768
1769 fn num_of_args(&self) -> usize {
1770 if ToRedisArgs::is_single_vec_arg(&self[..]) {
1771 return 1;
1772 }
1773 if self.len() == 1 {
1774 self[0].num_of_args()
1775 } else {
1776 self.len()
1777 }
1778 }
1779}
1780
1781impl<T: ToRedisArgs> ToRedisArgs for &[T] {
1782 fn write_redis_args<W>(&self, out: &mut W)
1783 where
1784 W: ?Sized + RedisWrite,
1785 {
1786 ToRedisArgs::write_args_from_slice(self, out)
1787 }
1788
1789 fn num_of_args(&self) -> usize {
1790 if ToRedisArgs::is_single_vec_arg(&self[..]) {
1791 return 1;
1792 }
1793 if self.len() == 1 {
1794 self[0].num_of_args()
1795 } else {
1796 self.len()
1797 }
1798 }
1799}
1800
1801impl<T: ToRedisArgs> ToRedisArgs for Option<T> {
1802 fn write_redis_args<W>(&self, out: &mut W)
1803 where
1804 W: ?Sized + RedisWrite,
1805 {
1806 if let Some(ref x) = *self {
1807 x.write_redis_args(out);
1808 }
1809 }
1810
1811 fn describe_numeric_behavior(&self) -> NumericBehavior {
1812 match *self {
1813 Some(ref x) => x.describe_numeric_behavior(),
1814 None => NumericBehavior::NonNumeric,
1815 }
1816 }
1817
1818 fn num_of_args(&self) -> usize {
1819 match *self {
1820 Some(ref x) => x.num_of_args(),
1821 None => 0,
1822 }
1823 }
1824}
1825
1826macro_rules! deref_to_write_redis_args_impl {
1827 (
1828 $(#[$attr:meta])*
1829 <$($desc:tt)+
1830 ) => {
1831 $(#[$attr])*
1832 impl <$($desc)+ {
1833 #[inline]
1834 fn write_redis_args<W>(&self, out: &mut W)
1835 where
1836 W: ?Sized + RedisWrite,
1837 {
1838 (**self).write_redis_args(out)
1839 }
1840
1841 fn num_of_args(&self) -> usize {
1842 (**self).num_of_args()
1843 }
1844
1845 fn describe_numeric_behavior(&self) -> NumericBehavior {
1846 (**self).describe_numeric_behavior()
1847 }
1848 }
1849 };
1850}
1851
1852deref_to_write_redis_args_impl! {
1853 <'a, T> ToRedisArgs for &'a T where T: ToRedisArgs
1854}
1855
1856deref_to_write_redis_args_impl! {
1857 <'a, T> ToRedisArgs for &'a mut T where T: ToRedisArgs
1858}
1859
1860deref_to_write_redis_args_impl! {
1861 <T> ToRedisArgs for Box<T> where T: ToRedisArgs
1862}
1863
1864deref_to_write_redis_args_impl! {
1865 <T> ToRedisArgs for std::sync::Arc<T> where T: ToRedisArgs
1866}
1867
1868deref_to_write_redis_args_impl! {
1869 <T> ToRedisArgs for std::rc::Rc<T> where T: ToRedisArgs
1870}
1871
1872macro_rules! impl_to_redis_args_for_set {
1876 (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+) ) => {
1877 impl< $($TypeParam),+ > ToRedisArgs for $SetType
1878 where
1879 $($WhereClause)+
1880 {
1881 fn write_redis_args<W>(&self, out: &mut W)
1882 where
1883 W: ?Sized + RedisWrite,
1884 {
1885 ToRedisArgs::make_arg_iter_ref(self.iter(), out)
1886 }
1887
1888 fn num_of_args(&self) -> usize {
1889 self.len()
1890 }
1891 }
1892 };
1893}
1894
1895impl_to_redis_args_for_set!(
1896 for <T, S> std::collections::HashSet<T, S>,
1897 where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1898);
1899
1900impl_to_redis_args_for_set!(
1901 for <T> std::collections::BTreeSet<T>,
1902 where (T: ToRedisArgs + Hash + Eq + Ord)
1903);
1904
1905#[cfg(feature = "hashbrown")]
1906impl_to_redis_args_for_set!(
1907 for <T, S> hashbrown::HashSet<T, S>,
1908 where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1909);
1910
1911#[cfg(feature = "ahash")]
1912impl_to_redis_args_for_set!(
1913 for <T, S> ahash::AHashSet<T, S>,
1914 where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1915);
1916
1917macro_rules! impl_to_redis_args_for_map {
1921 (
1922 $(#[$meta:meta])*
1923 for <$($TypeParam:ident),+> $MapType:ty,
1924 where ($($WhereClause:tt)+)
1925 ) => {
1926 $(#[$meta])*
1927 impl< $($TypeParam),+ > ToRedisArgs for $MapType
1928 where
1929 $($WhereClause)+
1930 {
1931 fn write_redis_args<W>(&self, out: &mut W)
1932 where
1933 W: ?Sized + RedisWrite,
1934 {
1935 for (key, value) in self {
1936 assert!(key.num_of_args() <= 1 && value.num_of_args() <= 1);
1938 key.write_redis_args(out);
1939 value.write_redis_args(out);
1940 }
1941 }
1942
1943 fn num_of_args(&self) -> usize {
1944 self.len()
1945 }
1946 }
1947 };
1948}
1949impl_to_redis_args_for_map!(
1950 for <K, V> std::collections::HashMap<K, V>,
1951 where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1952);
1953
1954impl_to_redis_args_for_map!(
1955 for <K, V> std::collections::BTreeMap<K, V>,
1957 where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1958);
1959
1960#[cfg(feature = "hashbrown")]
1961impl_to_redis_args_for_map!(
1962 for <K, V> hashbrown::HashMap<K, V>,
1963 where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1964);
1965
1966macro_rules! to_redis_args_for_tuple {
1967 () => ();
1968 ($(#[$meta:meta],)*$($name:ident,)+) => (
1969 $(#[$meta])*
1970 impl<$($name: ToRedisArgs),*> ToRedisArgs for ($($name,)*) {
1971 #[allow(non_snake_case, unused_variables)]
1974 fn write_redis_args<W>(&self, out: &mut W) where W: ?Sized + RedisWrite {
1975 let ($(ref $name,)*) = *self;
1976 $($name.write_redis_args(out);)*
1977 }
1978
1979 #[allow(non_snake_case, unused_variables)]
1980 fn num_of_args(&self) -> usize {
1981 let mut n: usize = 0;
1982 $(let $name = (); n += 1;)*
1983 n
1984 }
1985 }
1986 )
1987}
1988
1989to_redis_args_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
1990to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, }
1991to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, }
1992to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
1993to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
1994to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
1995to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
1996to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
1997to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
1998to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
1999to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2000to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2001
2002impl<T: ToRedisArgs, const N: usize> ToRedisArgs for &[T; N] {
2003 fn write_redis_args<W>(&self, out: &mut W)
2004 where
2005 W: ?Sized + RedisWrite,
2006 {
2007 ToRedisArgs::write_args_from_slice(self.as_slice(), out)
2008 }
2009
2010 fn num_of_args(&self) -> usize {
2011 if ToRedisArgs::is_single_vec_arg(&self[..]) {
2012 return 1;
2013 }
2014 if self.len() == 1 {
2015 self[0].num_of_args()
2016 } else {
2017 self.len()
2018 }
2019 }
2020}
2021
2022fn vec_to_array<T, const N: usize>(items: Vec<T>, original_value: &Value) -> RedisResult<[T; N]> {
2023 match items.try_into() {
2024 Ok(array) => Ok(array),
2025 Err(items) => {
2026 let msg = format!(
2027 "Response has wrong dimension, expected {N}, got {}",
2028 items.len()
2029 );
2030 invalid_type_error!(original_value, msg)
2031 }
2032 }
2033}
2034
2035impl<T: FromRedisValue, const N: usize> FromRedisValue for [T; N] {
2036 fn from_redis_value(value: &Value) -> RedisResult<[T; N]> {
2037 match *value {
2038 Value::BulkString(ref bytes) => match FromRedisValue::from_byte_vec(bytes) {
2039 Some(items) => vec_to_array(items, value),
2040 None => {
2041 let msg = format!(
2042 "Conversion to Array[{}; {N}] failed",
2043 std::any::type_name::<T>()
2044 );
2045 invalid_type_error!(value, msg)
2046 }
2047 },
2048 Value::Array(ref items) => {
2049 let items = FromRedisValue::from_redis_values(items)?;
2050 vec_to_array(items, value)
2051 }
2052 Value::Nil => vec_to_array(vec![], value),
2053 _ => invalid_type_error!(value, "Response type not array compatible"),
2054 }
2055 }
2056}
2057
2058pub trait FromRedisValue: Sized {
2072 fn from_redis_value(v: &Value) -> RedisResult<Self>;
2076
2077 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2081 Self::from_redis_value(&v)
2085 }
2086
2087 fn from_redis_values(items: &[Value]) -> RedisResult<Vec<Self>> {
2091 items.iter().map(FromRedisValue::from_redis_value).collect()
2092 }
2093
2094 fn from_owned_redis_values(items: Vec<Value>) -> RedisResult<Vec<Self>> {
2097 items
2098 .into_iter()
2099 .map(FromRedisValue::from_owned_redis_value)
2100 .collect()
2101 }
2102
2103 fn from_byte_vec(_vec: &[u8]) -> Option<Vec<Self>> {
2105 Self::from_owned_redis_value(Value::BulkString(_vec.into()))
2106 .map(|rv| vec![rv])
2107 .ok()
2108 }
2109
2110 fn from_owned_byte_vec(_vec: Vec<u8>) -> RedisResult<Vec<Self>> {
2112 Self::from_owned_redis_value(Value::BulkString(_vec)).map(|rv| vec![rv])
2113 }
2114}
2115
2116fn get_inner_value(v: &Value) -> &Value {
2117 if let Value::Attribute {
2118 data,
2119 attributes: _,
2120 } = v
2121 {
2122 data.as_ref()
2123 } else {
2124 v
2125 }
2126}
2127
2128fn get_owned_inner_value(v: Value) -> Value {
2129 if let Value::Attribute {
2130 data,
2131 attributes: _,
2132 } = v
2133 {
2134 *data
2135 } else {
2136 v
2137 }
2138}
2139
2140macro_rules! from_redis_value_for_num_internal {
2141 ($t:ty, $v:expr) => {{
2142 let v = if let Value::Attribute {
2143 data,
2144 attributes: _,
2145 } = $v
2146 {
2147 data
2148 } else {
2149 $v
2150 };
2151 match *v {
2152 Value::Int(val) => Ok(val as $t),
2153 Value::SimpleString(ref s) => match s.parse::<$t>() {
2154 Ok(rv) => Ok(rv),
2155 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2156 },
2157 Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
2158 Ok(rv) => Ok(rv),
2159 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2160 },
2161 Value::Double(val) => Ok(val as $t),
2162 _ => invalid_type_error!(v, "Response type not convertible to numeric."),
2163 }
2164 }};
2165}
2166
2167macro_rules! from_redis_value_for_num {
2168 ($t:ty) => {
2169 impl FromRedisValue for $t {
2170 fn from_redis_value(v: &Value) -> RedisResult<$t> {
2171 from_redis_value_for_num_internal!($t, v)
2172 }
2173 }
2174 };
2175}
2176
2177impl FromRedisValue for u8 {
2178 fn from_redis_value(v: &Value) -> RedisResult<u8> {
2179 from_redis_value_for_num_internal!(u8, v)
2180 }
2181
2182 fn from_byte_vec(vec: &[u8]) -> Option<Vec<u8>> {
2184 Some(vec.to_vec())
2185 }
2186 fn from_owned_byte_vec(vec: Vec<u8>) -> RedisResult<Vec<u8>> {
2187 Ok(vec)
2188 }
2189}
2190
2191from_redis_value_for_num!(i8);
2192from_redis_value_for_num!(i16);
2193from_redis_value_for_num!(u16);
2194from_redis_value_for_num!(i32);
2195from_redis_value_for_num!(u32);
2196from_redis_value_for_num!(i64);
2197from_redis_value_for_num!(u64);
2198from_redis_value_for_num!(i128);
2199from_redis_value_for_num!(u128);
2200from_redis_value_for_num!(f32);
2201from_redis_value_for_num!(f64);
2202from_redis_value_for_num!(isize);
2203from_redis_value_for_num!(usize);
2204
2205#[cfg(any(
2206 feature = "rust_decimal",
2207 feature = "bigdecimal",
2208 feature = "num-bigint"
2209))]
2210macro_rules! from_redis_value_for_bignum_internal {
2211 ($t:ty, $v:expr) => {{
2212 let v = $v;
2213 match *v {
2214 Value::Int(val) => <$t>::try_from(val)
2215 .map_err(|_| invalid_type_error_inner!(v, "Could not convert from integer.")),
2216 Value::SimpleString(ref s) => match s.parse::<$t>() {
2217 Ok(rv) => Ok(rv),
2218 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2219 },
2220 Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
2221 Ok(rv) => Ok(rv),
2222 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2223 },
2224 _ => invalid_type_error!(v, "Response type not convertible to numeric."),
2225 }
2226 }};
2227}
2228
2229#[cfg(any(
2230 feature = "rust_decimal",
2231 feature = "bigdecimal",
2232 feature = "num-bigint"
2233))]
2234macro_rules! from_redis_value_for_bignum {
2235 ($t:ty) => {
2236 impl FromRedisValue for $t {
2237 fn from_redis_value(v: &Value) -> RedisResult<$t> {
2238 from_redis_value_for_bignum_internal!($t, v)
2239 }
2240 }
2241 };
2242}
2243
2244#[cfg(feature = "rust_decimal")]
2245from_redis_value_for_bignum!(rust_decimal::Decimal);
2246#[cfg(feature = "bigdecimal")]
2247from_redis_value_for_bignum!(bigdecimal::BigDecimal);
2248#[cfg(feature = "num-bigint")]
2249from_redis_value_for_bignum!(num_bigint::BigInt);
2250#[cfg(feature = "num-bigint")]
2251from_redis_value_for_bignum!(num_bigint::BigUint);
2252
2253impl FromRedisValue for bool {
2254 fn from_redis_value(v: &Value) -> RedisResult<bool> {
2255 let v = get_inner_value(v);
2256 match *v {
2257 Value::Nil => Ok(false),
2258 Value::Int(val) => Ok(val != 0),
2259 Value::SimpleString(ref s) => {
2260 if &s[..] == "1" {
2261 Ok(true)
2262 } else if &s[..] == "0" {
2263 Ok(false)
2264 } else {
2265 invalid_type_error!(v, "Response status not valid boolean");
2266 }
2267 }
2268 Value::BulkString(ref bytes) => {
2269 if bytes == b"1" {
2270 Ok(true)
2271 } else if bytes == b"0" {
2272 Ok(false)
2273 } else {
2274 invalid_type_error!(v, "Response type not bool compatible.");
2275 }
2276 }
2277 Value::Boolean(b) => Ok(b),
2278 Value::Okay => Ok(true),
2279 _ => invalid_type_error!(v, "Response type not bool compatible."),
2280 }
2281 }
2282}
2283
2284impl FromRedisValue for CString {
2285 fn from_redis_value(v: &Value) -> RedisResult<CString> {
2286 let v = get_inner_value(v);
2287 match *v {
2288 Value::BulkString(ref bytes) => Ok(CString::new(bytes.as_slice())?),
2289 Value::Okay => Ok(CString::new("OK")?),
2290 Value::SimpleString(ref val) => Ok(CString::new(val.as_bytes())?),
2291 _ => invalid_type_error!(v, "Response type not CString compatible."),
2292 }
2293 }
2294 fn from_owned_redis_value(v: Value) -> RedisResult<CString> {
2295 let v = get_owned_inner_value(v);
2296 match v {
2297 Value::BulkString(bytes) => Ok(CString::new(bytes)?),
2298 Value::Okay => Ok(CString::new("OK")?),
2299 Value::SimpleString(val) => Ok(CString::new(val)?),
2300 _ => invalid_type_error!(v, "Response type not CString compatible."),
2301 }
2302 }
2303}
2304
2305impl FromRedisValue for String {
2306 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2307 let v = get_inner_value(v);
2308 match *v {
2309 Value::BulkString(ref bytes) => Ok(from_utf8(bytes)?.to_string()),
2310 Value::Okay => Ok("OK".to_string()),
2311 Value::SimpleString(ref val) => Ok(val.to_string()),
2312 Value::VerbatimString {
2313 format: _,
2314 ref text,
2315 } => Ok(text.to_string()),
2316 Value::Double(ref val) => Ok(val.to_string()),
2317 Value::Int(val) => Ok(val.to_string()),
2318 _ => invalid_type_error!(v, "Response type not string compatible."),
2319 }
2320 }
2321
2322 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2323 let v = get_owned_inner_value(v);
2324 match v {
2325 Value::BulkString(bytes) => Ok(Self::from_utf8(bytes)?),
2326 Value::Okay => Ok("OK".to_string()),
2327 Value::SimpleString(val) => Ok(val),
2328 Value::VerbatimString { format: _, text } => Ok(text),
2329 Value::Double(val) => Ok(val.to_string()),
2330 Value::Int(val) => Ok(val.to_string()),
2331 _ => invalid_type_error!(v, "Response type not string compatible."),
2332 }
2333 }
2334}
2335
2336macro_rules! pointer_from_redis_value_impl {
2337 (
2338 $(#[$attr:meta])*
2339 $id:ident, $ty:ty, $func:expr
2340 ) => {
2341 $(#[$attr])*
2342 impl<$id: FromRedisValue> FromRedisValue for $ty {
2343 fn from_redis_value(v: &Value) -> RedisResult<Self>
2344 {
2345 FromRedisValue::from_redis_value(v).map($func)
2346 }
2347
2348 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2349 FromRedisValue::from_owned_redis_value(v).map($func)
2350 }
2351 }
2352 }
2353}
2354
2355pointer_from_redis_value_impl!(T, Box<T>, Box::new);
2356pointer_from_redis_value_impl!(T, std::sync::Arc<T>, std::sync::Arc::new);
2357pointer_from_redis_value_impl!(T, std::rc::Rc<T>, std::rc::Rc::new);
2358
2359macro_rules! from_vec_from_redis_value {
2364 (<$T:ident> $Type:ty) => {
2365 from_vec_from_redis_value!(<$T> $Type; Into::into);
2366 };
2367
2368 (<$T:ident> $Type:ty; $convert:expr) => {
2369 impl<$T: FromRedisValue> FromRedisValue for $Type {
2370 fn from_redis_value(v: &Value) -> RedisResult<$Type> {
2371 match v {
2372 Value::BulkString(bytes) => match FromRedisValue::from_byte_vec(bytes) {
2375 Some(x) => Ok($convert(x)),
2376 None => invalid_type_error!(
2377 v,
2378 format!("Conversion to {} failed.", std::any::type_name::<$Type>())
2379 ),
2380 },
2381 Value::Array(items) => FromRedisValue::from_redis_values(items).map($convert),
2382 Value::Set(ref items) => FromRedisValue::from_redis_values(items).map($convert),
2383 Value::Map(ref items) => {
2384 let mut n: Vec<T> = vec![];
2385 for item in items {
2386 match FromRedisValue::from_redis_value(&Value::Map(vec![item.clone()])) {
2387 Ok(v) => {
2388 n.push(v);
2389 }
2390 Err(e) => {
2391 return Err(e);
2392 }
2393 }
2394 }
2395 Ok($convert(n))
2396 }
2397 Value::Nil => Ok($convert(Vec::new())),
2398 _ => invalid_type_error!(v, "Response type not vector compatible."),
2399 }
2400 }
2401 fn from_owned_redis_value(v: Value) -> RedisResult<$Type> {
2402 match v {
2403 Value::BulkString(bytes) => FromRedisValue::from_owned_byte_vec(bytes).map($convert),
2407 Value::Array(items) => FromRedisValue::from_owned_redis_values(items).map($convert),
2408 Value::Set(items) => FromRedisValue::from_owned_redis_values(items).map($convert),
2409 Value::Map(items) => {
2410 let mut n: Vec<T> = vec![];
2411 for item in items {
2412 match FromRedisValue::from_owned_redis_value(Value::Map(vec![item])) {
2413 Ok(v) => {
2414 n.push(v);
2415 }
2416 Err(e) => {
2417 return Err(e);
2418 }
2419 }
2420 }
2421 Ok($convert(n))
2422 }
2423 Value::Nil => Ok($convert(Vec::new())),
2424 _ => invalid_type_error!(v, "Response type not vector compatible."),
2425 }
2426 }
2427 }
2428 };
2429}
2430
2431from_vec_from_redis_value!(<T> Vec<T>);
2432from_vec_from_redis_value!(<T> std::sync::Arc<[T]>);
2433from_vec_from_redis_value!(<T> Box<[T]>; Vec::into_boxed_slice);
2434
2435macro_rules! impl_from_redis_value_for_map {
2436 (for <$($TypeParam:ident),+> $MapType:ty, where ($($WhereClause:tt)+)) => {
2437 impl< $($TypeParam),+ > FromRedisValue for $MapType
2438 where
2439 $($WhereClause)+
2440 {
2441 fn from_redis_value(v: &Value) -> RedisResult<$MapType> {
2442 let v = get_inner_value(v);
2443 match *v {
2444 Value::Nil => Ok(Default::default()),
2445 _ => v
2446 .as_map_iter()
2447 .ok_or_else(|| invalid_type_error_inner!(v, "Response type not map compatible"))?
2448 .map(|(k, v)| {
2449 Ok((from_redis_value(k)?, from_redis_value(v)?))
2450 })
2451 .collect(),
2452 }
2453 }
2454
2455 fn from_owned_redis_value(v: Value) -> RedisResult<$MapType> {
2456 let v = get_owned_inner_value(v);
2457 match v {
2458 Value::Nil => Ok(Default::default()),
2459 _ => v
2460 .into_map_iter()
2461 .map_err(|v| invalid_type_error_inner!(v, "Response type not map compatible"))?
2462 .map(|(k, v)| {
2463 Ok((from_owned_redis_value(k)?, from_owned_redis_value(v)?))
2464 })
2465 .collect(),
2466 }
2467 }
2468 }
2469 };
2470}
2471
2472impl_from_redis_value_for_map!(
2473 for <K, V, S> std::collections::HashMap<K, V, S>,
2474 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2475);
2476
2477#[cfg(feature = "hashbrown")]
2478impl_from_redis_value_for_map!(
2479 for <K, V, S> hashbrown::HashMap<K, V, S>,
2480 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2481);
2482
2483#[cfg(feature = "ahash")]
2484impl_from_redis_value_for_map!(
2485 for <K, V> ahash::AHashMap<K, V>,
2486 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue)
2487);
2488
2489impl_from_redis_value_for_map!(
2490 for <K, V> std::collections::BTreeMap<K, V>,
2491 where (K: FromRedisValue + Eq + Hash + Ord, V: FromRedisValue)
2492);
2493
2494macro_rules! impl_from_redis_value_for_set {
2495 (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+)) => {
2496 impl< $($TypeParam),+ > FromRedisValue for $SetType
2497 where
2498 $($WhereClause)+
2499 {
2500 fn from_redis_value(v: &Value) -> RedisResult<$SetType> {
2501 let v = get_inner_value(v);
2502 let items = v
2503 .as_sequence()
2504 .ok_or_else(|| invalid_type_error_inner!(v, "Response type not map compatible"))?;
2505 items.iter().map(|item| from_redis_value(item)).collect()
2506 }
2507
2508 fn from_owned_redis_value(v: Value) -> RedisResult<$SetType> {
2509 let v = get_owned_inner_value(v);
2510 let items = v
2511 .into_sequence()
2512 .map_err(|v| invalid_type_error_inner!(v, "Response type not map compatible"))?;
2513 items
2514 .into_iter()
2515 .map(|item| from_owned_redis_value(item))
2516 .collect()
2517 }
2518 }
2519 };
2520}
2521
2522impl_from_redis_value_for_set!(
2523 for <T, S> std::collections::HashSet<T, S>,
2524 where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2525);
2526
2527impl_from_redis_value_for_set!(
2528 for <T> std::collections::BTreeSet<T>,
2529 where (T: FromRedisValue + Eq + Ord)
2530);
2531
2532#[cfg(feature = "hashbrown")]
2533impl_from_redis_value_for_set!(
2534 for <T, S> hashbrown::HashSet<T, S>,
2535 where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2536);
2537
2538#[cfg(feature = "ahash")]
2539impl_from_redis_value_for_set!(
2540 for <T> ahash::AHashSet<T>,
2541 where (T: FromRedisValue + Eq + Hash)
2542);
2543
2544impl FromRedisValue for Value {
2545 fn from_redis_value(v: &Value) -> RedisResult<Value> {
2546 Ok(v.clone())
2547 }
2548 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2549 Ok(v)
2550 }
2551}
2552
2553impl FromRedisValue for () {
2554 fn from_redis_value(_v: &Value) -> RedisResult<()> {
2555 Ok(())
2556 }
2557}
2558
2559macro_rules! from_redis_value_for_tuple {
2560 () => ();
2561 ($(#[$meta:meta],)*$($name:ident,)+) => (
2562 $(#[$meta])*
2563 impl<$($name: FromRedisValue),*> FromRedisValue for ($($name,)*) {
2564 #[allow(non_snake_case, unused_variables)]
2567 fn from_redis_value(v: &Value) -> RedisResult<($($name,)*)> {
2568 let v = get_inner_value(v);
2569 match *v {
2570 Value::Array(ref items) => {
2571 let mut n = 0;
2573 $(let $name = (); n += 1;)*
2574 if items.len() != n {
2575 invalid_type_error!(v, "Array response of wrong dimension")
2576 }
2577
2578 let mut i = 0;
2581 Ok(($({let $name = (); from_redis_value(
2582 &items[{ i += 1; i - 1 }])?},)*))
2583 }
2584
2585 Value::Map(ref items) => {
2586 let mut n = 0;
2588 $(let $name = (); n += 1;)*
2589 if n != 2 {
2590 invalid_type_error!(v, "Map response of wrong dimension")
2591 }
2592
2593 let mut flatten_items = vec![];
2594 for (k,v) in items {
2595 flatten_items.push(k);
2596 flatten_items.push(v);
2597 }
2598
2599 let mut i = 0;
2602 Ok(($({let $name = (); from_redis_value(
2603 &flatten_items[{ i += 1; i - 1 }])?},)*))
2604 }
2605
2606 _ => invalid_type_error!(v, "Not a Array response")
2607 }
2608 }
2609
2610 #[allow(non_snake_case, unused_variables)]
2613 fn from_owned_redis_value(v: Value) -> RedisResult<($($name,)*)> {
2614 let v = get_owned_inner_value(v);
2615 match v {
2616 Value::Array(mut items) => {
2617 let mut n = 0;
2619 $(let $name = (); n += 1;)*
2620 if items.len() != n {
2621 invalid_type_error!(Value::Array(items), "Array response of wrong dimension")
2622 }
2623
2624 let mut i = 0;
2627 Ok(($({let $name = (); from_owned_redis_value(
2628 ::std::mem::replace(&mut items[{ i += 1; i - 1 }], Value::Nil)
2629 )?},)*))
2630 }
2631
2632 Value::Map(items) => {
2633 let mut n = 0;
2635 $(let $name = (); n += 1;)*
2636 if n != 2 {
2637 invalid_type_error!(Value::Map(items), "Map response of wrong dimension")
2638 }
2639
2640 let mut flatten_items = vec![];
2641 for (k,v) in items {
2642 flatten_items.push(k);
2643 flatten_items.push(v);
2644 }
2645
2646 let mut i = 0;
2649 Ok(($({let $name = (); from_redis_value(
2650 &flatten_items[{ i += 1; i - 1 }])?},)*))
2651 }
2652
2653 _ => invalid_type_error!(v, "Not a Array response")
2654 }
2655 }
2656
2657 #[allow(non_snake_case, unused_variables)]
2658 fn from_redis_values(items: &[Value]) -> RedisResult<Vec<($($name,)*)>> {
2659 let mut n = 0;
2661 $(let $name = (); n += 1;)*
2662 let mut rv = vec![];
2663 if items.len() == 0 {
2664 return Ok(rv)
2665 }
2666 for item in items {
2668 match item {
2669 Value::Array(ch) => {
2670 if let [$($name),*] = &ch[..] {
2671 rv.push(($(from_redis_value(&$name)?),*),)
2672 };
2673 },
2674 _ => {},
2675
2676 }
2677 }
2678 if !rv.is_empty(){
2679 return Ok(rv);
2680 }
2681
2682 if let [$($name),*] = items{
2683 rv.push(($(from_redis_value($name)?),*),);
2684 return Ok(rv);
2685 }
2686 for chunk in items.chunks_exact(n) {
2687 match chunk {
2688 [$($name),*] => rv.push(($(from_redis_value($name)?),*),),
2689 _ => {},
2690 }
2691 }
2692 Ok(rv)
2693 }
2694
2695 #[allow(non_snake_case, unused_variables)]
2696 fn from_owned_redis_values(mut items: Vec<Value>) -> RedisResult<Vec<($($name,)*)>> {
2697 let mut n = 0;
2699 $(let $name = (); n += 1;)*
2700
2701 let mut rv = vec![];
2702 if items.len() == 0 {
2703 return Ok(rv)
2704 }
2705 for item in items.iter_mut() {
2707 match item {
2708 Value::Array(ref mut ch) => {
2709 if let [$($name),*] = &mut ch[..] {
2710 rv.push(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))?),*),);
2711 };
2712 },
2713 _ => {},
2714 }
2715 }
2716 if !rv.is_empty(){
2717 return Ok(rv);
2718 }
2719
2720 let mut rv = Vec::with_capacity(items.len() / n);
2721 if items.len() == 0 {
2722 return Ok(rv)
2723 }
2724 for chunk in items.chunks_mut(n) {
2725 match chunk {
2726 [$($name),*] => rv.push(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))?),*),),
2731 _ => unreachable!(),
2732 }
2733 }
2734 Ok(rv)
2735 }
2736 }
2737 )
2738}
2739
2740from_redis_value_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
2741from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, }
2742from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, }
2743from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
2744from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
2745from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
2746from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
2747from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
2748from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
2749from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
2750from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2751from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2752
2753impl FromRedisValue for InfoDict {
2754 fn from_redis_value(v: &Value) -> RedisResult<InfoDict> {
2755 let v = get_inner_value(v);
2756 let s: String = from_redis_value(v)?;
2757 Ok(InfoDict::new(&s))
2758 }
2759 fn from_owned_redis_value(v: Value) -> RedisResult<InfoDict> {
2760 let v = get_owned_inner_value(v);
2761 let s: String = from_owned_redis_value(v)?;
2762 Ok(InfoDict::new(&s))
2763 }
2764}
2765
2766impl<T: FromRedisValue> FromRedisValue for Option<T> {
2767 fn from_redis_value(v: &Value) -> RedisResult<Option<T>> {
2768 let v = get_inner_value(v);
2769 if *v == Value::Nil {
2770 return Ok(None);
2771 }
2772 Ok(Some(from_redis_value(v)?))
2773 }
2774 fn from_owned_redis_value(v: Value) -> RedisResult<Option<T>> {
2775 let v = get_owned_inner_value(v);
2776 if v == Value::Nil {
2777 return Ok(None);
2778 }
2779 Ok(Some(from_owned_redis_value(v)?))
2780 }
2781}
2782
2783#[cfg(feature = "bytes")]
2784impl FromRedisValue for bytes::Bytes {
2785 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2786 let v = get_inner_value(v);
2787 match v {
2788 Value::BulkString(bytes_vec) => Ok(bytes::Bytes::copy_from_slice(bytes_vec.as_ref())),
2789 _ => invalid_type_error!(v, "Not a bulk string"),
2790 }
2791 }
2792 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2793 let v = get_owned_inner_value(v);
2794 match v {
2795 Value::BulkString(bytes_vec) => Ok(bytes_vec.into()),
2796 _ => invalid_type_error!(v, "Not a bulk string"),
2797 }
2798 }
2799}
2800
2801#[cfg(feature = "uuid")]
2802impl FromRedisValue for uuid::Uuid {
2803 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2804 match *v {
2805 Value::BulkString(ref bytes) => Ok(uuid::Uuid::from_slice(bytes)?),
2806 _ => invalid_type_error!(v, "Response type not uuid compatible."),
2807 }
2808 }
2809}
2810
2811#[cfg(feature = "uuid")]
2812impl ToRedisArgs for uuid::Uuid {
2813 fn write_redis_args<W>(&self, out: &mut W)
2814 where
2815 W: ?Sized + RedisWrite,
2816 {
2817 out.write_arg(self.as_bytes());
2818 }
2819}
2820
2821pub fn from_redis_value<T: FromRedisValue>(v: &Value) -> RedisResult<T> {
2824 FromRedisValue::from_redis_value(v)
2825}
2826
2827pub fn from_owned_redis_value<T: FromRedisValue>(v: Value) -> RedisResult<T> {
2830 FromRedisValue::from_owned_redis_value(v)
2831}
2832
2833#[derive(Clone, Eq, PartialEq, Default, Debug, Copy)]
2838pub enum ProtocolVersion {
2839 #[default]
2841 RESP2,
2842 RESP3,
2844}
2845
2846#[derive(Clone, Copy)]
2848pub enum ExpireOption {
2849 NONE,
2851 NX,
2853 XX,
2855 GT,
2857 LT,
2859}
2860
2861impl ToRedisArgs for ExpireOption {
2862 fn write_redis_args<W>(&self, out: &mut W)
2863 where
2864 W: ?Sized + RedisWrite,
2865 {
2866 match self {
2867 ExpireOption::NX => out.write_arg(b"NX"),
2868 ExpireOption::XX => out.write_arg(b"XX"),
2869 ExpireOption::GT => out.write_arg(b"GT"),
2870 ExpireOption::LT => out.write_arg(b"LT"),
2871 _ => {}
2872 }
2873 }
2874}
2875
2876#[derive(Debug, Clone, PartialEq)]
2877pub struct PushInfo {
2879 pub kind: PushKind,
2881 pub data: Vec<Value>,
2883}
2884
2885impl PushInfo {
2886 pub(crate) fn disconnect() -> Self {
2887 PushInfo {
2888 kind: crate::PushKind::Disconnection,
2889 data: vec![],
2890 }
2891 }
2892}
2893
2894pub(crate) type SyncPushSender = std::sync::mpsc::Sender<PushInfo>;
2895
2896#[cfg(any(feature = "aio", feature = "r2d2"))]
2898pub(crate) fn closed_connection_error() -> RedisError {
2899 RedisError::from(io::Error::from(io::ErrorKind::BrokenPipe))
2900}