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!(i128, NumericBehavior::NumberIsInteger);
1674itoa_based_to_redis_impl!(u128, NumericBehavior::NumberIsInteger);
1675itoa_based_to_redis_impl!(isize, NumericBehavior::NumberIsInteger);
1676itoa_based_to_redis_impl!(usize, NumericBehavior::NumberIsInteger);
1677
1678non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU8, NumericBehavior::NumberIsInteger);
1679non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI8, NumericBehavior::NumberIsInteger);
1680non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU16, NumericBehavior::NumberIsInteger);
1681non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI16, NumericBehavior::NumberIsInteger);
1682non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU32, NumericBehavior::NumberIsInteger);
1683non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI32, NumericBehavior::NumberIsInteger);
1684non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU64, NumericBehavior::NumberIsInteger);
1685non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI64, NumericBehavior::NumberIsInteger);
1686non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU128, NumericBehavior::NumberIsInteger);
1687non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI128, NumericBehavior::NumberIsInteger);
1688non_zero_itoa_based_to_redis_impl!(core::num::NonZeroUsize, NumericBehavior::NumberIsInteger);
1689non_zero_itoa_based_to_redis_impl!(core::num::NonZeroIsize, NumericBehavior::NumberIsInteger);
1690
1691ryu_based_to_redis_impl!(f32, NumericBehavior::NumberIsFloat);
1692ryu_based_to_redis_impl!(f64, NumericBehavior::NumberIsFloat);
1693
1694#[cfg(any(
1695 feature = "rust_decimal",
1696 feature = "bigdecimal",
1697 feature = "num-bigint"
1698))]
1699macro_rules! bignum_to_redis_impl {
1700 ($t:ty) => {
1701 impl ToRedisArgs for $t {
1702 fn write_redis_args<W>(&self, out: &mut W)
1703 where
1704 W: ?Sized + RedisWrite,
1705 {
1706 out.write_arg(&self.to_string().into_bytes())
1707 }
1708 }
1709 };
1710}
1711
1712#[cfg(feature = "rust_decimal")]
1713bignum_to_redis_impl!(rust_decimal::Decimal);
1714#[cfg(feature = "bigdecimal")]
1715bignum_to_redis_impl!(bigdecimal::BigDecimal);
1716#[cfg(feature = "num-bigint")]
1717bignum_to_redis_impl!(num_bigint::BigInt);
1718#[cfg(feature = "num-bigint")]
1719bignum_to_redis_impl!(num_bigint::BigUint);
1720
1721impl ToRedisArgs for bool {
1722 fn write_redis_args<W>(&self, out: &mut W)
1723 where
1724 W: ?Sized + RedisWrite,
1725 {
1726 out.write_arg(if *self { b"1" } else { b"0" })
1727 }
1728}
1729
1730impl ToRedisArgs for String {
1731 fn write_redis_args<W>(&self, out: &mut W)
1732 where
1733 W: ?Sized + RedisWrite,
1734 {
1735 out.write_arg(self.as_bytes())
1736 }
1737}
1738
1739impl ToRedisArgs for &str {
1740 fn write_redis_args<W>(&self, out: &mut W)
1741 where
1742 W: ?Sized + RedisWrite,
1743 {
1744 out.write_arg(self.as_bytes())
1745 }
1746}
1747
1748impl<'a, T> ToRedisArgs for Cow<'a, T>
1749where
1750 T: ToOwned + ?Sized,
1751 &'a T: ToRedisArgs,
1752 for<'b> &'b T::Owned: ToRedisArgs,
1753{
1754 fn write_redis_args<W>(&self, out: &mut W)
1755 where
1756 W: ?Sized + RedisWrite,
1757 {
1758 match self {
1759 Cow::Borrowed(inner) => inner.write_redis_args(out),
1760 Cow::Owned(inner) => inner.write_redis_args(out),
1761 }
1762 }
1763}
1764
1765impl<T: ToRedisArgs> ToRedisArgs for Vec<T> {
1766 fn write_redis_args<W>(&self, out: &mut W)
1767 where
1768 W: ?Sized + RedisWrite,
1769 {
1770 ToRedisArgs::write_args_from_slice(self, out)
1771 }
1772
1773 fn num_of_args(&self) -> usize {
1774 if ToRedisArgs::is_single_vec_arg(&self[..]) {
1775 return 1;
1776 }
1777 if self.len() == 1 {
1778 self[0].num_of_args()
1779 } else {
1780 self.len()
1781 }
1782 }
1783}
1784
1785impl<T: ToRedisArgs> ToRedisArgs for &[T] {
1786 fn write_redis_args<W>(&self, out: &mut W)
1787 where
1788 W: ?Sized + RedisWrite,
1789 {
1790 ToRedisArgs::write_args_from_slice(self, out)
1791 }
1792
1793 fn num_of_args(&self) -> usize {
1794 if ToRedisArgs::is_single_vec_arg(&self[..]) {
1795 return 1;
1796 }
1797 if self.len() == 1 {
1798 self[0].num_of_args()
1799 } else {
1800 self.len()
1801 }
1802 }
1803}
1804
1805impl<T: ToRedisArgs> ToRedisArgs for Option<T> {
1806 fn write_redis_args<W>(&self, out: &mut W)
1807 where
1808 W: ?Sized + RedisWrite,
1809 {
1810 if let Some(ref x) = *self {
1811 x.write_redis_args(out);
1812 }
1813 }
1814
1815 fn describe_numeric_behavior(&self) -> NumericBehavior {
1816 match *self {
1817 Some(ref x) => x.describe_numeric_behavior(),
1818 None => NumericBehavior::NonNumeric,
1819 }
1820 }
1821
1822 fn num_of_args(&self) -> usize {
1823 match *self {
1824 Some(ref x) => x.num_of_args(),
1825 None => 0,
1826 }
1827 }
1828}
1829
1830macro_rules! deref_to_write_redis_args_impl {
1831 (
1832 $(#[$attr:meta])*
1833 <$($desc:tt)+
1834 ) => {
1835 $(#[$attr])*
1836 impl <$($desc)+ {
1837 #[inline]
1838 fn write_redis_args<W>(&self, out: &mut W)
1839 where
1840 W: ?Sized + RedisWrite,
1841 {
1842 (**self).write_redis_args(out)
1843 }
1844
1845 fn num_of_args(&self) -> usize {
1846 (**self).num_of_args()
1847 }
1848
1849 fn describe_numeric_behavior(&self) -> NumericBehavior {
1850 (**self).describe_numeric_behavior()
1851 }
1852 }
1853 };
1854}
1855
1856deref_to_write_redis_args_impl! {
1857 <'a, T> ToRedisArgs for &'a T where T: ToRedisArgs
1858}
1859
1860deref_to_write_redis_args_impl! {
1861 <'a, T> ToRedisArgs for &'a mut T where T: ToRedisArgs
1862}
1863
1864deref_to_write_redis_args_impl! {
1865 <T> ToRedisArgs for Box<T> where T: ToRedisArgs
1866}
1867
1868deref_to_write_redis_args_impl! {
1869 <T> ToRedisArgs for std::sync::Arc<T> where T: ToRedisArgs
1870}
1871
1872deref_to_write_redis_args_impl! {
1873 <T> ToRedisArgs for std::rc::Rc<T> where T: ToRedisArgs
1874}
1875
1876macro_rules! impl_to_redis_args_for_set {
1880 (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+) ) => {
1881 impl< $($TypeParam),+ > ToRedisArgs for $SetType
1882 where
1883 $($WhereClause)+
1884 {
1885 fn write_redis_args<W>(&self, out: &mut W)
1886 where
1887 W: ?Sized + RedisWrite,
1888 {
1889 ToRedisArgs::make_arg_iter_ref(self.iter(), out)
1890 }
1891
1892 fn num_of_args(&self) -> usize {
1893 self.len()
1894 }
1895 }
1896 };
1897}
1898
1899impl_to_redis_args_for_set!(
1900 for <T, S> std::collections::HashSet<T, S>,
1901 where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1902);
1903
1904impl_to_redis_args_for_set!(
1905 for <T> std::collections::BTreeSet<T>,
1906 where (T: ToRedisArgs + Hash + Eq + Ord)
1907);
1908
1909#[cfg(feature = "hashbrown")]
1910impl_to_redis_args_for_set!(
1911 for <T, S> hashbrown::HashSet<T, S>,
1912 where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1913);
1914
1915#[cfg(feature = "ahash")]
1916impl_to_redis_args_for_set!(
1917 for <T, S> ahash::AHashSet<T, S>,
1918 where (T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default)
1919);
1920
1921macro_rules! impl_to_redis_args_for_map {
1925 (
1926 $(#[$meta:meta])*
1927 for <$($TypeParam:ident),+> $MapType:ty,
1928 where ($($WhereClause:tt)+)
1929 ) => {
1930 $(#[$meta])*
1931 impl< $($TypeParam),+ > ToRedisArgs for $MapType
1932 where
1933 $($WhereClause)+
1934 {
1935 fn write_redis_args<W>(&self, out: &mut W)
1936 where
1937 W: ?Sized + RedisWrite,
1938 {
1939 for (key, value) in self {
1940 assert!(key.num_of_args() <= 1 && value.num_of_args() <= 1);
1942 key.write_redis_args(out);
1943 value.write_redis_args(out);
1944 }
1945 }
1946
1947 fn num_of_args(&self) -> usize {
1948 self.len()
1949 }
1950 }
1951 };
1952}
1953impl_to_redis_args_for_map!(
1954 for <K, V> std::collections::HashMap<K, V>,
1955 where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1956);
1957
1958impl_to_redis_args_for_map!(
1959 for <K, V> std::collections::BTreeMap<K, V>,
1961 where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1962);
1963
1964#[cfg(feature = "hashbrown")]
1965impl_to_redis_args_for_map!(
1966 for <K, V> hashbrown::HashMap<K, V>,
1967 where (K: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs)
1968);
1969
1970macro_rules! to_redis_args_for_tuple {
1971 () => ();
1972 ($(#[$meta:meta],)*$($name:ident,)+) => (
1973 $(#[$meta])*
1974 impl<$($name: ToRedisArgs),*> ToRedisArgs for ($($name,)*) {
1975 #[allow(non_snake_case, unused_variables)]
1978 fn write_redis_args<W>(&self, out: &mut W) where W: ?Sized + RedisWrite {
1979 let ($(ref $name,)*) = *self;
1980 $($name.write_redis_args(out);)*
1981 }
1982
1983 #[allow(non_snake_case, unused_variables)]
1984 fn num_of_args(&self) -> usize {
1985 let mut n: usize = 0;
1986 $(let $name = (); n += 1;)*
1987 n
1988 }
1989 }
1990 )
1991}
1992
1993to_redis_args_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
1994to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, }
1995to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, }
1996to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
1997to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
1998to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
1999to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
2000to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
2001to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
2002to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
2003to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2004to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2005
2006impl<T: ToRedisArgs, const N: usize> ToRedisArgs for &[T; N] {
2007 fn write_redis_args<W>(&self, out: &mut W)
2008 where
2009 W: ?Sized + RedisWrite,
2010 {
2011 ToRedisArgs::write_args_from_slice(self.as_slice(), out)
2012 }
2013
2014 fn num_of_args(&self) -> usize {
2015 if ToRedisArgs::is_single_vec_arg(&self[..]) {
2016 return 1;
2017 }
2018 if self.len() == 1 {
2019 self[0].num_of_args()
2020 } else {
2021 self.len()
2022 }
2023 }
2024}
2025
2026fn vec_to_array<T, const N: usize>(items: Vec<T>, original_value: &Value) -> RedisResult<[T; N]> {
2027 match items.try_into() {
2028 Ok(array) => Ok(array),
2029 Err(items) => {
2030 let msg = format!(
2031 "Response has wrong dimension, expected {N}, got {}",
2032 items.len()
2033 );
2034 invalid_type_error!(original_value, msg)
2035 }
2036 }
2037}
2038
2039impl<T: FromRedisValue, const N: usize> FromRedisValue for [T; N] {
2040 fn from_redis_value(value: &Value) -> RedisResult<[T; N]> {
2041 match *value {
2042 Value::BulkString(ref bytes) => match FromRedisValue::from_byte_vec(bytes) {
2043 Some(items) => vec_to_array(items, value),
2044 None => {
2045 let msg = format!(
2046 "Conversion to Array[{}; {N}] failed",
2047 std::any::type_name::<T>()
2048 );
2049 invalid_type_error!(value, msg)
2050 }
2051 },
2052 Value::Array(ref items) => {
2053 let items = FromRedisValue::from_redis_values(items)?;
2054 vec_to_array(items, value)
2055 }
2056 Value::Nil => vec_to_array(vec![], value),
2057 _ => invalid_type_error!(value, "Response type not array compatible"),
2058 }
2059 }
2060}
2061
2062pub trait FromRedisValue: Sized {
2076 fn from_redis_value(v: &Value) -> RedisResult<Self>;
2080
2081 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2085 Self::from_redis_value(&v)
2089 }
2090
2091 fn from_redis_values(items: &[Value]) -> RedisResult<Vec<Self>> {
2095 items.iter().map(FromRedisValue::from_redis_value).collect()
2096 }
2097
2098 fn from_owned_redis_values(items: Vec<Value>) -> RedisResult<Vec<Self>> {
2101 items
2102 .into_iter()
2103 .map(FromRedisValue::from_owned_redis_value)
2104 .collect()
2105 }
2106
2107 fn from_each_owned_redis_values(items: Vec<Value>) -> Vec<RedisResult<Self>> {
2110 items
2111 .into_iter()
2112 .map(FromRedisValue::from_owned_redis_value)
2113 .collect()
2114 }
2115
2116 fn from_byte_vec(_vec: &[u8]) -> Option<Vec<Self>> {
2118 Self::from_owned_redis_value(Value::BulkString(_vec.into()))
2119 .map(|rv| vec![rv])
2120 .ok()
2121 }
2122
2123 fn from_owned_byte_vec(_vec: Vec<u8>) -> RedisResult<Vec<Self>> {
2125 Self::from_owned_redis_value(Value::BulkString(_vec)).map(|rv| vec![rv])
2126 }
2127}
2128
2129fn get_inner_value(v: &Value) -> &Value {
2130 if let Value::Attribute {
2131 data,
2132 attributes: _,
2133 } = v
2134 {
2135 data.as_ref()
2136 } else {
2137 v
2138 }
2139}
2140
2141fn get_owned_inner_value(v: Value) -> Value {
2142 if let Value::Attribute {
2143 data,
2144 attributes: _,
2145 } = v
2146 {
2147 *data
2148 } else {
2149 v
2150 }
2151}
2152
2153macro_rules! from_redis_value_for_num_internal {
2154 ($t:ty, $v:expr) => {{
2155 let v = if let Value::Attribute {
2156 data,
2157 attributes: _,
2158 } = $v
2159 {
2160 data
2161 } else {
2162 $v
2163 };
2164 match *v {
2165 Value::Int(val) => Ok(val as $t),
2166 Value::SimpleString(ref s) => match s.parse::<$t>() {
2167 Ok(rv) => Ok(rv),
2168 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2169 },
2170 Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
2171 Ok(rv) => Ok(rv),
2172 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2173 },
2174 Value::Double(val) => Ok(val as $t),
2175 _ => invalid_type_error!(v, "Response type not convertible to numeric."),
2176 }
2177 }};
2178}
2179
2180macro_rules! from_redis_value_for_num {
2181 ($t:ty) => {
2182 impl FromRedisValue for $t {
2183 fn from_redis_value(v: &Value) -> RedisResult<$t> {
2184 from_redis_value_for_num_internal!($t, v)
2185 }
2186 }
2187 };
2188}
2189
2190impl FromRedisValue for u8 {
2191 fn from_redis_value(v: &Value) -> RedisResult<u8> {
2192 from_redis_value_for_num_internal!(u8, v)
2193 }
2194
2195 fn from_byte_vec(vec: &[u8]) -> Option<Vec<u8>> {
2197 Some(vec.to_vec())
2198 }
2199 fn from_owned_byte_vec(vec: Vec<u8>) -> RedisResult<Vec<u8>> {
2200 Ok(vec)
2201 }
2202}
2203
2204from_redis_value_for_num!(i8);
2205from_redis_value_for_num!(i16);
2206from_redis_value_for_num!(u16);
2207from_redis_value_for_num!(i32);
2208from_redis_value_for_num!(u32);
2209from_redis_value_for_num!(i64);
2210from_redis_value_for_num!(u64);
2211from_redis_value_for_num!(i128);
2212from_redis_value_for_num!(u128);
2213from_redis_value_for_num!(f32);
2214from_redis_value_for_num!(f64);
2215from_redis_value_for_num!(isize);
2216from_redis_value_for_num!(usize);
2217
2218#[cfg(any(
2219 feature = "rust_decimal",
2220 feature = "bigdecimal",
2221 feature = "num-bigint"
2222))]
2223macro_rules! from_redis_value_for_bignum_internal {
2224 ($t:ty, $v:expr) => {{
2225 let v = $v;
2226 match *v {
2227 Value::Int(val) => <$t>::try_from(val)
2228 .map_err(|_| invalid_type_error_inner!(v, "Could not convert from integer.")),
2229 Value::SimpleString(ref s) => match s.parse::<$t>() {
2230 Ok(rv) => Ok(rv),
2231 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2232 },
2233 Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
2234 Ok(rv) => Ok(rv),
2235 Err(_) => invalid_type_error!(v, "Could not convert from string."),
2236 },
2237 _ => invalid_type_error!(v, "Response type not convertible to numeric."),
2238 }
2239 }};
2240}
2241
2242#[cfg(any(
2243 feature = "rust_decimal",
2244 feature = "bigdecimal",
2245 feature = "num-bigint"
2246))]
2247macro_rules! from_redis_value_for_bignum {
2248 ($t:ty) => {
2249 impl FromRedisValue for $t {
2250 fn from_redis_value(v: &Value) -> RedisResult<$t> {
2251 from_redis_value_for_bignum_internal!($t, v)
2252 }
2253 }
2254 };
2255}
2256
2257#[cfg(feature = "rust_decimal")]
2258from_redis_value_for_bignum!(rust_decimal::Decimal);
2259#[cfg(feature = "bigdecimal")]
2260from_redis_value_for_bignum!(bigdecimal::BigDecimal);
2261#[cfg(feature = "num-bigint")]
2262from_redis_value_for_bignum!(num_bigint::BigInt);
2263#[cfg(feature = "num-bigint")]
2264from_redis_value_for_bignum!(num_bigint::BigUint);
2265
2266impl FromRedisValue for bool {
2267 fn from_redis_value(v: &Value) -> RedisResult<bool> {
2268 let v = get_inner_value(v);
2269 match *v {
2270 Value::Nil => Ok(false),
2271 Value::Int(val) => Ok(val != 0),
2272 Value::SimpleString(ref s) => {
2273 if &s[..] == "1" {
2274 Ok(true)
2275 } else if &s[..] == "0" {
2276 Ok(false)
2277 } else {
2278 invalid_type_error!(v, "Response status not valid boolean");
2279 }
2280 }
2281 Value::BulkString(ref bytes) => {
2282 if bytes == b"1" {
2283 Ok(true)
2284 } else if bytes == b"0" {
2285 Ok(false)
2286 } else {
2287 invalid_type_error!(v, "Response type not bool compatible.");
2288 }
2289 }
2290 Value::Boolean(b) => Ok(b),
2291 Value::Okay => Ok(true),
2292 _ => invalid_type_error!(v, "Response type not bool compatible."),
2293 }
2294 }
2295}
2296
2297impl FromRedisValue for CString {
2298 fn from_redis_value(v: &Value) -> RedisResult<CString> {
2299 let v = get_inner_value(v);
2300 match *v {
2301 Value::BulkString(ref bytes) => Ok(CString::new(bytes.as_slice())?),
2302 Value::Okay => Ok(CString::new("OK")?),
2303 Value::SimpleString(ref val) => Ok(CString::new(val.as_bytes())?),
2304 _ => invalid_type_error!(v, "Response type not CString compatible."),
2305 }
2306 }
2307 fn from_owned_redis_value(v: Value) -> RedisResult<CString> {
2308 let v = get_owned_inner_value(v);
2309 match v {
2310 Value::BulkString(bytes) => Ok(CString::new(bytes)?),
2311 Value::Okay => Ok(CString::new("OK")?),
2312 Value::SimpleString(val) => Ok(CString::new(val)?),
2313 _ => invalid_type_error!(v, "Response type not CString compatible."),
2314 }
2315 }
2316}
2317
2318impl FromRedisValue for String {
2319 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2320 let v = get_inner_value(v);
2321 match *v {
2322 Value::BulkString(ref bytes) => Ok(from_utf8(bytes)?.to_string()),
2323 Value::Okay => Ok("OK".to_string()),
2324 Value::SimpleString(ref val) => Ok(val.to_string()),
2325 Value::VerbatimString {
2326 format: _,
2327 ref text,
2328 } => Ok(text.to_string()),
2329 Value::Double(ref 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 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2336 let v = get_owned_inner_value(v);
2337 match v {
2338 Value::BulkString(bytes) => Ok(Self::from_utf8(bytes)?),
2339 Value::Okay => Ok("OK".to_string()),
2340 Value::SimpleString(val) => Ok(val),
2341 Value::VerbatimString { format: _, text } => Ok(text),
2342 Value::Double(val) => Ok(val.to_string()),
2343 Value::Int(val) => Ok(val.to_string()),
2344 _ => invalid_type_error!(v, "Response type not string compatible."),
2345 }
2346 }
2347}
2348
2349macro_rules! pointer_from_redis_value_impl {
2350 (
2351 $(#[$attr:meta])*
2352 $id:ident, $ty:ty, $func:expr
2353 ) => {
2354 $(#[$attr])*
2355 impl<$id: FromRedisValue> FromRedisValue for $ty {
2356 fn from_redis_value(v: &Value) -> RedisResult<Self>
2357 {
2358 FromRedisValue::from_redis_value(v).map($func)
2359 }
2360
2361 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2362 FromRedisValue::from_owned_redis_value(v).map($func)
2363 }
2364 }
2365 }
2366}
2367
2368pointer_from_redis_value_impl!(T, Box<T>, Box::new);
2369pointer_from_redis_value_impl!(T, std::sync::Arc<T>, std::sync::Arc::new);
2370pointer_from_redis_value_impl!(T, std::rc::Rc<T>, std::rc::Rc::new);
2371
2372macro_rules! from_vec_from_redis_value {
2377 (<$T:ident> $Type:ty) => {
2378 from_vec_from_redis_value!(<$T> $Type; Into::into);
2379 };
2380
2381 (<$T:ident> $Type:ty; $convert:expr) => {
2382 impl<$T: FromRedisValue> FromRedisValue for $Type {
2383 fn from_redis_value(v: &Value) -> RedisResult<$Type> {
2384 match v {
2385 Value::BulkString(bytes) => match FromRedisValue::from_byte_vec(bytes) {
2388 Some(x) => Ok($convert(x)),
2389 None => invalid_type_error!(
2390 v,
2391 format!("Conversion to {} failed.", std::any::type_name::<$Type>())
2392 ),
2393 },
2394 Value::Array(items) => FromRedisValue::from_redis_values(items).map($convert),
2395 Value::Set(ref items) => FromRedisValue::from_redis_values(items).map($convert),
2396 Value::Map(ref items) => {
2397 let mut n: Vec<T> = vec![];
2398 for item in items {
2399 match FromRedisValue::from_redis_value(&Value::Map(vec![item.clone()])) {
2400 Ok(v) => {
2401 n.push(v);
2402 }
2403 Err(e) => {
2404 return Err(e);
2405 }
2406 }
2407 }
2408 Ok($convert(n))
2409 }
2410 Value::Nil => Ok($convert(Vec::new())),
2411 _ => invalid_type_error!(v, "Response type not vector compatible."),
2412 }
2413 }
2414 fn from_owned_redis_value(v: Value) -> RedisResult<$Type> {
2415 match v {
2416 Value::BulkString(bytes) => FromRedisValue::from_owned_byte_vec(bytes).map($convert),
2420 Value::Array(items) => FromRedisValue::from_owned_redis_values(items).map($convert),
2421 Value::Set(items) => FromRedisValue::from_owned_redis_values(items).map($convert),
2422 Value::Map(items) => {
2423 let mut n: Vec<T> = vec![];
2424 for item in items {
2425 match FromRedisValue::from_owned_redis_value(Value::Map(vec![item])) {
2426 Ok(v) => {
2427 n.push(v);
2428 }
2429 Err(e) => {
2430 return Err(e);
2431 }
2432 }
2433 }
2434 Ok($convert(n))
2435 }
2436 Value::Nil => Ok($convert(Vec::new())),
2437 _ => invalid_type_error!(v, "Response type not vector compatible."),
2438 }
2439 }
2440 }
2441 };
2442}
2443
2444from_vec_from_redis_value!(<T> Vec<T>);
2445from_vec_from_redis_value!(<T> std::sync::Arc<[T]>);
2446from_vec_from_redis_value!(<T> Box<[T]>; Vec::into_boxed_slice);
2447
2448macro_rules! impl_from_redis_value_for_map {
2449 (for <$($TypeParam:ident),+> $MapType:ty, where ($($WhereClause:tt)+)) => {
2450 impl< $($TypeParam),+ > FromRedisValue for $MapType
2451 where
2452 $($WhereClause)+
2453 {
2454 fn from_redis_value(v: &Value) -> RedisResult<$MapType> {
2455 let v = get_inner_value(v);
2456 match *v {
2457 Value::Nil => Ok(Default::default()),
2458 _ => v
2459 .as_map_iter()
2460 .ok_or_else(|| invalid_type_error_inner!(v, "Response type not map compatible"))?
2461 .map(|(k, v)| {
2462 Ok((from_redis_value(k)?, from_redis_value(v)?))
2463 })
2464 .collect(),
2465 }
2466 }
2467
2468 fn from_owned_redis_value(v: Value) -> RedisResult<$MapType> {
2469 let v = get_owned_inner_value(v);
2470 match v {
2471 Value::Nil => Ok(Default::default()),
2472 _ => v
2473 .into_map_iter()
2474 .map_err(|v| invalid_type_error_inner!(v, "Response type not map compatible"))?
2475 .map(|(k, v)| {
2476 Ok((from_owned_redis_value(k)?, from_owned_redis_value(v)?))
2477 })
2478 .collect(),
2479 }
2480 }
2481 }
2482 };
2483}
2484
2485impl_from_redis_value_for_map!(
2486 for <K, V, S> std::collections::HashMap<K, V, S>,
2487 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2488);
2489
2490#[cfg(feature = "hashbrown")]
2491impl_from_redis_value_for_map!(
2492 for <K, V, S> hashbrown::HashMap<K, V, S>,
2493 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2494);
2495
2496#[cfg(feature = "ahash")]
2497impl_from_redis_value_for_map!(
2498 for <K, V> ahash::AHashMap<K, V>,
2499 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue)
2500);
2501
2502impl_from_redis_value_for_map!(
2503 for <K, V> std::collections::BTreeMap<K, V>,
2504 where (K: FromRedisValue + Eq + Hash + Ord, V: FromRedisValue)
2505);
2506
2507macro_rules! impl_from_redis_value_for_set {
2508 (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+)) => {
2509 impl< $($TypeParam),+ > FromRedisValue for $SetType
2510 where
2511 $($WhereClause)+
2512 {
2513 fn from_redis_value(v: &Value) -> RedisResult<$SetType> {
2514 let v = get_inner_value(v);
2515 let items = v
2516 .as_sequence()
2517 .ok_or_else(|| invalid_type_error_inner!(v, "Response type not map compatible"))?;
2518 items.iter().map(|item| from_redis_value(item)).collect()
2519 }
2520
2521 fn from_owned_redis_value(v: Value) -> RedisResult<$SetType> {
2522 let v = get_owned_inner_value(v);
2523 let items = v
2524 .into_sequence()
2525 .map_err(|v| invalid_type_error_inner!(v, "Response type not map compatible"))?;
2526 items
2527 .into_iter()
2528 .map(|item| from_owned_redis_value(item))
2529 .collect()
2530 }
2531 }
2532 };
2533}
2534
2535impl_from_redis_value_for_set!(
2536 for <T, S> std::collections::HashSet<T, S>,
2537 where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2538);
2539
2540impl_from_redis_value_for_set!(
2541 for <T> std::collections::BTreeSet<T>,
2542 where (T: FromRedisValue + Eq + Ord)
2543);
2544
2545#[cfg(feature = "hashbrown")]
2546impl_from_redis_value_for_set!(
2547 for <T, S> hashbrown::HashSet<T, S>,
2548 where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2549);
2550
2551#[cfg(feature = "ahash")]
2552impl_from_redis_value_for_set!(
2553 for <T> ahash::AHashSet<T>,
2554 where (T: FromRedisValue + Eq + Hash)
2555);
2556
2557impl FromRedisValue for Value {
2558 fn from_redis_value(v: &Value) -> RedisResult<Value> {
2559 Ok(v.clone())
2560 }
2561 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2562 Ok(v)
2563 }
2564}
2565
2566impl FromRedisValue for () {
2567 fn from_redis_value(_v: &Value) -> RedisResult<()> {
2568 Ok(())
2569 }
2570}
2571
2572macro_rules! from_redis_value_for_tuple {
2573 () => ();
2574 ($(#[$meta:meta],)*$($name:ident,)+) => (
2575 $(#[$meta])*
2576 impl<$($name: FromRedisValue),*> FromRedisValue for ($($name,)*) {
2577 #[allow(non_snake_case, unused_variables)]
2580 fn from_redis_value(v: &Value) -> RedisResult<($($name,)*)> {
2581 let v = get_inner_value(v);
2582 match *v {
2583 Value::Array(ref items) => {
2584 let mut n = 0;
2586 $(let $name = (); n += 1;)*
2587 if items.len() != n {
2588 invalid_type_error!(v, "Array response of wrong dimension")
2589 }
2590
2591 let mut i = 0;
2594 Ok(($({let $name = (); from_redis_value(
2595 &items[{ i += 1; i - 1 }])?},)*))
2596 }
2597
2598 Value::Map(ref items) => {
2599 let mut n = 0;
2601 $(let $name = (); n += 1;)*
2602 if n != 2 {
2603 invalid_type_error!(v, "Map response of wrong dimension")
2604 }
2605
2606 let mut flatten_items = vec![];
2607 for (k,v) in items {
2608 flatten_items.push(k);
2609 flatten_items.push(v);
2610 }
2611
2612 let mut i = 0;
2615 Ok(($({let $name = (); from_redis_value(
2616 &flatten_items[{ i += 1; i - 1 }])?},)*))
2617 }
2618
2619 _ => invalid_type_error!(v, "Not a Array response")
2620 }
2621 }
2622
2623 #[allow(non_snake_case, unused_variables)]
2626 fn from_owned_redis_value(v: Value) -> RedisResult<($($name,)*)> {
2627 let v = get_owned_inner_value(v);
2628 match v {
2629 Value::Array(mut items) => {
2630 let mut n = 0;
2632 $(let $name = (); n += 1;)*
2633 if items.len() != n {
2634 invalid_type_error!(Value::Array(items), "Array response of wrong dimension")
2635 }
2636
2637 let mut i = 0;
2640 Ok(($({let $name = (); from_owned_redis_value(
2641 ::std::mem::replace(&mut items[{ i += 1; i - 1 }], Value::Nil)
2642 )?},)*))
2643 }
2644
2645 Value::Map(items) => {
2646 let mut n = 0;
2648 $(let $name = (); n += 1;)*
2649 if n != 2 {
2650 invalid_type_error!(Value::Map(items), "Map response of wrong dimension")
2651 }
2652
2653 let mut flatten_items = vec![];
2654 for (k,v) in items {
2655 flatten_items.push(k);
2656 flatten_items.push(v);
2657 }
2658
2659 let mut i = 0;
2662 Ok(($({let $name = (); from_redis_value(
2663 &flatten_items[{ i += 1; i - 1 }])?},)*))
2664 }
2665
2666 _ => invalid_type_error!(v, "Not a Array response")
2667 }
2668 }
2669
2670 #[allow(non_snake_case, unused_variables)]
2671 fn from_redis_values(items: &[Value]) -> RedisResult<Vec<($($name,)*)>> {
2672 let mut n = 0;
2674 $(let $name = (); n += 1;)*
2675 let mut rv = vec![];
2676 if items.len() == 0 {
2677 return Ok(rv)
2678 }
2679 for item in items {
2681 match item {
2682 Value::Array(ch) => {
2683 if let [$($name),*] = &ch[..] {
2684 rv.push(($(from_redis_value(&$name)?),*),)
2685 };
2686 },
2687 _ => {},
2688
2689 }
2690 }
2691 if !rv.is_empty(){
2692 return Ok(rv);
2693 }
2694
2695 if let [$($name),*] = items{
2696 rv.push(($(from_redis_value($name)?),*),);
2697 return Ok(rv);
2698 }
2699 for chunk in items.chunks_exact(n) {
2700 match chunk {
2701 [$($name),*] => rv.push(($(from_redis_value($name)?),*),),
2702 _ => {},
2703 }
2704 }
2705 Ok(rv)
2706 }
2707
2708 #[allow(non_snake_case, unused_variables)]
2709 fn from_each_owned_redis_values(mut items: Vec<Value>) -> Vec<RedisResult<($($name,)*)>> {
2710
2711 #[allow(unused_parens)]
2712 let extract = |val: ($(RedisResult<$name>),*)| -> RedisResult<($($name,)*)> {
2713 let ($($name),*) = val;
2714 Ok(($($name?),*,))
2715 };
2716
2717 let mut n = 0;
2719 $(let $name = (); n += 1;)*
2720
2721 let mut rv = vec![];
2722 if items.len() == 0 {
2723 return rv
2724 }
2725 for item in items.iter_mut() {
2727 match item {
2728 Value::Array(ref mut ch) => {
2729 if let [$($name),*] = &mut ch[..] {
2730 rv.push(extract(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))),*)));
2731 };
2732 },
2733 _ => {},
2734 }
2735 }
2736 if !rv.is_empty(){
2737 return rv;
2738 }
2739
2740 let mut rv = Vec::with_capacity(items.len() / n);
2741
2742 for chunk in items.chunks_mut(n) {
2743 match chunk {
2744 [$($name),*] => rv.push(extract(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))),*))),
2749 _ => unreachable!(),
2750 }
2751 }
2752 rv
2753 }
2754
2755 #[allow(non_snake_case, unused_variables)]
2756 fn from_owned_redis_values(mut items: Vec<Value>) -> RedisResult<Vec<($($name,)*)>> {
2757 let mut n = 0;
2759 $(let $name = (); n += 1;)*
2760
2761 let mut rv = vec![];
2762 if items.len() == 0 {
2763 return Ok(rv)
2764 }
2765 for item in items.iter_mut() {
2767 match item {
2768 Value::Array(ref mut ch) => {
2769 if let [$($name),*] = &mut ch[..] {
2770 rv.push(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))?),*),);
2771 };
2772 },
2773 _ => {},
2774 }
2775 }
2776 if !rv.is_empty(){
2777 return Ok(rv);
2778 }
2779
2780 let mut rv = Vec::with_capacity(items.len() / n);
2781 if items.len() == 0 {
2782 return Ok(rv)
2783 }
2784 for chunk in items.chunks_mut(n) {
2785 match chunk {
2786 [$($name),*] => rv.push(($(from_owned_redis_value(std::mem::replace($name, Value::Nil))?),*),),
2791 _ => unreachable!(),
2792 }
2793 }
2794 Ok(rv)
2795 }
2796 }
2797 )
2798}
2799
2800from_redis_value_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
2801from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, }
2802from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, }
2803from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
2804from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
2805from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
2806from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
2807from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
2808from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
2809from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
2810from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2811from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2812
2813impl FromRedisValue for InfoDict {
2814 fn from_redis_value(v: &Value) -> RedisResult<InfoDict> {
2815 let v = get_inner_value(v);
2816 let s: String = from_redis_value(v)?;
2817 Ok(InfoDict::new(&s))
2818 }
2819 fn from_owned_redis_value(v: Value) -> RedisResult<InfoDict> {
2820 let v = get_owned_inner_value(v);
2821 let s: String = from_owned_redis_value(v)?;
2822 Ok(InfoDict::new(&s))
2823 }
2824}
2825
2826impl<T: FromRedisValue> FromRedisValue for Option<T> {
2827 fn from_redis_value(v: &Value) -> RedisResult<Option<T>> {
2828 let v = get_inner_value(v);
2829 if *v == Value::Nil {
2830 return Ok(None);
2831 }
2832 Ok(Some(from_redis_value(v)?))
2833 }
2834 fn from_owned_redis_value(v: Value) -> RedisResult<Option<T>> {
2835 let v = get_owned_inner_value(v);
2836 if v == Value::Nil {
2837 return Ok(None);
2838 }
2839 Ok(Some(from_owned_redis_value(v)?))
2840 }
2841}
2842
2843#[cfg(feature = "bytes")]
2844impl FromRedisValue for bytes::Bytes {
2845 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2846 let v = get_inner_value(v);
2847 match v {
2848 Value::BulkString(bytes_vec) => Ok(bytes::Bytes::copy_from_slice(bytes_vec.as_ref())),
2849 _ => invalid_type_error!(v, "Not a bulk string"),
2850 }
2851 }
2852 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2853 let v = get_owned_inner_value(v);
2854 match v {
2855 Value::BulkString(bytes_vec) => Ok(bytes_vec.into()),
2856 _ => invalid_type_error!(v, "Not a bulk string"),
2857 }
2858 }
2859}
2860
2861#[cfg(feature = "uuid")]
2862impl FromRedisValue for uuid::Uuid {
2863 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2864 match *v {
2865 Value::BulkString(ref bytes) => Ok(uuid::Uuid::from_slice(bytes)?),
2866 _ => invalid_type_error!(v, "Response type not uuid compatible."),
2867 }
2868 }
2869}
2870
2871#[cfg(feature = "uuid")]
2872impl ToRedisArgs for uuid::Uuid {
2873 fn write_redis_args<W>(&self, out: &mut W)
2874 where
2875 W: ?Sized + RedisWrite,
2876 {
2877 out.write_arg(self.as_bytes());
2878 }
2879}
2880
2881pub fn from_redis_value<T: FromRedisValue>(v: &Value) -> RedisResult<T> {
2884 FromRedisValue::from_redis_value(v)
2885}
2886
2887pub fn from_owned_redis_value<T: FromRedisValue>(v: Value) -> RedisResult<T> {
2890 FromRedisValue::from_owned_redis_value(v)
2891}
2892
2893#[derive(Clone, Eq, PartialEq, Default, Debug, Copy)]
2898pub enum ProtocolVersion {
2899 #[default]
2901 RESP2,
2902 RESP3,
2904}
2905
2906#[derive(Clone, Copy)]
2908pub enum ExpireOption {
2909 NONE,
2911 NX,
2913 XX,
2915 GT,
2917 LT,
2919}
2920
2921impl ToRedisArgs for ExpireOption {
2922 fn write_redis_args<W>(&self, out: &mut W)
2923 where
2924 W: ?Sized + RedisWrite,
2925 {
2926 match self {
2927 ExpireOption::NX => out.write_arg(b"NX"),
2928 ExpireOption::XX => out.write_arg(b"XX"),
2929 ExpireOption::GT => out.write_arg(b"GT"),
2930 ExpireOption::LT => out.write_arg(b"LT"),
2931 _ => {}
2932 }
2933 }
2934}
2935
2936#[derive(Debug, Clone, PartialEq)]
2937pub struct PushInfo {
2939 pub kind: PushKind,
2941 pub data: Vec<Value>,
2943}
2944
2945impl PushInfo {
2946 pub(crate) fn disconnect() -> Self {
2947 PushInfo {
2948 kind: crate::PushKind::Disconnection,
2949 data: vec![],
2950 }
2951 }
2952}
2953
2954pub(crate) type SyncPushSender = std::sync::mpsc::Sender<PushInfo>;
2955
2956#[cfg(any(feature = "aio", feature = "r2d2"))]
2958pub(crate) fn closed_connection_error() -> RedisError {
2959 RedisError::from(io::Error::from(io::ErrorKind::BrokenPipe))
2960}
2961
2962#[derive(Debug, Clone, PartialEq)]
2964pub enum ValueType {
2965 String,
2967 List,
2969 Set,
2971 ZSet,
2973 Hash,
2975 Stream,
2977 Unknown(String),
2979}
2980
2981impl FromRedisValue for ValueType {
2982 fn from_redis_value(v: &Value) -> RedisResult<Self> {
2983 match v {
2984 Value::SimpleString(s) => match s.as_str() {
2985 "string" => Ok(ValueType::String),
2986 "list" => Ok(ValueType::List),
2987 "set" => Ok(ValueType::Set),
2988 "zset" => Ok(ValueType::ZSet),
2989 "hash" => Ok(ValueType::Hash),
2990 "stream" => Ok(ValueType::Stream),
2991 _ => Ok(ValueType::Unknown(s.clone())),
2992 },
2993 _ => invalid_type_error!(v, "Value type should be a simple string"),
2994 }
2995 }
2996
2997 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
2998 match v {
2999 Value::SimpleString(s) => match s.as_str() {
3000 "string" => Ok(ValueType::String),
3001 "list" => Ok(ValueType::List),
3002 "set" => Ok(ValueType::Set),
3003 "zset" => Ok(ValueType::ZSet),
3004 "hash" => Ok(ValueType::Hash),
3005 "stream" => Ok(ValueType::Stream),
3006 _ => Ok(ValueType::Unknown(s)),
3007 },
3008 _ => invalid_type_error!(v, "Value type should be a simple string"),
3009 }
3010 }
3011}
3012
3013#[derive(Debug, PartialEq, Clone)]
3015pub enum IntegerReplyOrNoOp {
3016 IntegerReply(usize),
3018 NotExists,
3020 ExistsButNotRelevant,
3022}
3023
3024impl IntegerReplyOrNoOp {
3025 pub fn raw(&self) -> isize {
3027 match self {
3028 IntegerReplyOrNoOp::IntegerReply(s) => *s as isize,
3029 IntegerReplyOrNoOp::NotExists => -2,
3030 IntegerReplyOrNoOp::ExistsButNotRelevant => -1,
3031 }
3032 }
3033}
3034
3035impl FromRedisValue for IntegerReplyOrNoOp {
3036 fn from_redis_value(v: &Value) -> RedisResult<Self> {
3037 match v {
3038 Value::Int(s) => match s {
3039 -2 => Ok(IntegerReplyOrNoOp::NotExists),
3040 -1 => Ok(IntegerReplyOrNoOp::ExistsButNotRelevant),
3041 _ => Ok(IntegerReplyOrNoOp::IntegerReply(*s as usize)),
3042 },
3043 _ => invalid_type_error!(v, "Value should be an integer"),
3044 }
3045 }
3046
3047 fn from_owned_redis_value(v: Value) -> RedisResult<Self> {
3048 match v {
3049 Value::Int(s) => match s {
3050 -2 => Ok(IntegerReplyOrNoOp::NotExists),
3051 -1 => Ok(IntegerReplyOrNoOp::ExistsButNotRelevant),
3052 _ => Ok(IntegerReplyOrNoOp::IntegerReply(s as usize)),
3053 },
3054 _ => invalid_type_error!(v, "Value should be an integer"),
3055 }
3056 }
3057}
3058
3059impl PartialEq<isize> for IntegerReplyOrNoOp {
3060 fn eq(&self, other: &isize) -> bool {
3061 match self {
3062 IntegerReplyOrNoOp::IntegerReply(s) => *s as isize == *other,
3063 IntegerReplyOrNoOp::NotExists => *other == -2,
3064 IntegerReplyOrNoOp::ExistsButNotRelevant => *other == -1,
3065 }
3066 }
3067}
3068
3069impl PartialEq<usize> for IntegerReplyOrNoOp {
3070 fn eq(&self, other: &usize) -> bool {
3071 match self {
3072 IntegerReplyOrNoOp::IntegerReply(s) => *s == *other,
3073 _ => false,
3074 }
3075 }
3076}
3077
3078impl PartialEq<i32> for IntegerReplyOrNoOp {
3079 fn eq(&self, other: &i32) -> bool {
3080 match self {
3081 IntegerReplyOrNoOp::IntegerReply(s) => *s as i32 == *other,
3082 IntegerReplyOrNoOp::NotExists => *other == -2,
3083 IntegerReplyOrNoOp::ExistsButNotRelevant => *other == -1,
3084 }
3085 }
3086}
3087
3088impl PartialEq<u32> for IntegerReplyOrNoOp {
3089 fn eq(&self, other: &u32) -> bool {
3090 match self {
3091 IntegerReplyOrNoOp::IntegerReply(s) => *s as u32 == *other,
3092 _ => false,
3093 }
3094 }
3095}