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(PartialEq, Eq, Clone, Debug, Copy)]
74pub enum NumericBehavior {
75 NonNumeric,
77 NumberIsInteger,
79 NumberIsFloat,
81}
82
83#[derive(PartialEq, Eq, Copy, Clone, Debug)]
85#[non_exhaustive]
86pub enum ErrorKind {
87 ResponseError,
89 ParseError,
91 AuthenticationFailed,
93 TypeError,
95 ExecAbortError,
97 BusyLoadingError,
99 NoScriptError,
101 InvalidClientConfig,
104 Moved,
106 Ask,
108 TryAgain,
110 ClusterDown,
112 CrossSlot,
114 MasterDown,
116 IoError,
120 ClientError,
122 ExtensionError,
125 ReadOnly,
127 MasterNameNotFoundBySentinel,
129 NoValidReplicasFoundBySentinel,
131 EmptySentinelList,
133 NotBusy,
135 ClusterConnectionNotFound,
137 NoSub,
139
140 #[cfg(feature = "json")]
141 Serialize,
143
144 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 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#[derive(PartialEq, Clone)]
248pub enum Value {
249 Nil,
251 Int(i64),
256 BulkString(Vec<u8>),
258 Array(Vec<Value>),
261 SimpleString(String),
263 Okay,
265 Map(Vec<(Value, Value)>),
267 Attribute {
269 data: Box<Value>,
271 attributes: Vec<(Value, Value)>,
273 },
274 Set(Vec<Value>),
276 Double(f64),
278 Boolean(bool),
280 VerbatimString {
282 format: VerbatimFormat,
284 text: String,
286 },
287 BigNumber(BigInt),
289 Push {
291 kind: PushKind,
293 data: Vec<Value>,
295 },
296 ServerError(ServerError),
298}
299
300#[derive(PartialEq, Clone, Debug)]
302pub enum VerbatimFormat {
303 Unknown(String),
305 Markdown,
307 Text,
309}
310
311#[derive(PartialEq, Clone, Debug)]
313pub enum PushKind {
314 Disconnection,
316 Other(String),
318 Invalidate,
320 Message,
322 PMessage,
324 SMessage,
326 Unsubscribe,
328 PUnsubscribe,
330 SUnsubscribe,
332 Subscribe,
334 PSubscribe,
336 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
436impl Value {
444 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 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 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 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 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 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
583pub 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#[non_exhaustive]
795pub enum RetryMethod {
796 Reconnect,
798 NoRetry,
800 RetryImmediately,
802 WaitAndRetry,
804 AskRedirect,
806 MovedRedirect,
808 ReconnectFromInitialConnections,
810}
811
812impl RedisError {
814 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 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 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 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 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 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 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 io::ErrorKind::NotFound => cfg!(unix),
924 _ => false,
925 }
926 }
927 _ => false,
928 }
929 }
930
931 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 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 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 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 #[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 #[cfg(feature = "connection-manager")] 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 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
1093pub type RedisResult<T> = Result<T, RedisError>;
1095
1096#[cfg(feature = "aio")]
1098pub type RedisFuture<'a, T> = futures_util::future::BoxFuture<'a, RedisResult<T>>;
1099
1100#[derive(Debug, Clone)]
1102pub struct InfoDict {
1103 map: HashMap<String, Value>,
1104}
1105
1106impl InfoDict {
1123 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 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 pub fn find(&self, key: &&str) -> Option<&Value> {
1154 self.map.get(*key)
1155 }
1156
1157 pub fn contains_key(&self, key: &&str) -> bool {
1159 self.find(key).is_some()
1160 }
1161
1162 pub fn len(&self) -> usize {
1164 self.map.len()
1165 }
1166
1167 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#[derive(Debug, Clone, Eq, PartialEq)]
1185pub enum Role {
1186 Primary {
1188 replication_offset: u64,
1190 replicas: Vec<ReplicaInfo>,
1192 },
1193 Replica {
1195 primary_ip: String,
1197 primary_port: u16,
1199 replication_state: String,
1201 data_received: u64,
1203 },
1204 Sentinel {
1206 primary_names: Vec<String>,
1208 },
1209}
1210
1211#[derive(Debug, Clone, Eq, PartialEq)]
1215pub struct ReplicaInfo {
1216 pub ip: String,
1218 pub port: u16,
1220 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
1332pub trait RedisWrite {
1334 fn write_arg(&mut self, arg: &[u8]);
1336
1337 fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
1339 self.write_arg(arg.to_string().as_bytes())
1340 }
1341
1342 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
1362pub trait ToRedisArgs: Sized {
1366 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 fn write_redis_args<W>(&self, out: &mut W)
1382 where
1383 W: ?Sized + RedisWrite;
1384
1385 fn describe_numeric_behavior(&self) -> NumericBehavior {
1390 NumericBehavior::NonNumeric
1391 }
1392
1393 fn num_of_args(&self) -> usize {
1400 1
1401 }
1402
1403 #[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 #[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
1718macro_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
1763macro_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 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 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 #[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
1836macro_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
1901pub trait FromRedisValue: Sized {
1915 fn from_redis_value(v: &Value) -> RedisResult<Self>;
1919
1920 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
1924 Self::from_redis_value(&v)
1928 }
1929
1930 fn from_redis_values(items: &[Value]) -> RedisResult<Vec<Self>> {
1934 items.iter().map(FromRedisValue::from_redis_value).collect()
1935 }
1936
1937 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 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 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 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
2202macro_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 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 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 #[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 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 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 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 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 #[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 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 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 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 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 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 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 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 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 [$($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
2584macro_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
2661pub fn from_redis_value<T: FromRedisValue>(v: &Value) -> RedisResult<T> {
2664 FromRedisValue::from_redis_value(v)
2665}
2666
2667pub fn from_owned_redis_value<T: FromRedisValue>(v: Value) -> RedisResult<T> {
2670 FromRedisValue::from_owned_redis_value(v)
2671}
2672
2673#[derive(Clone, Eq, PartialEq, Default, Debug, Copy)]
2678pub enum ProtocolVersion {
2679 #[default]
2681 RESP2,
2682 RESP3,
2684}
2685
2686#[derive(Clone, Copy)]
2688pub enum ExpireOption {
2689 NONE,
2691 NX,
2693 XX,
2695 GT,
2697 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)]
2717pub struct PushInfo {
2719 pub kind: PushKind,
2721 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#[cfg(any(feature = "aio", feature = "r2d2"))]
2738pub(crate) fn closed_connection_error() -> RedisError {
2739 RedisError::from(io::Error::from(io::ErrorKind::BrokenPipe))
2740}