1use crate::errors::ParsingError;
2#[cfg(feature = "ahash")]
3pub(crate) use ahash::{AHashMap as HashMap, AHashSet as HashSet};
4#[cfg(feature = "num-bigint")]
5use num_bigint::BigInt;
6use std::borrow::Cow;
7#[cfg(not(feature = "ahash"))]
8pub(crate) use std::collections::{HashMap, HashSet};
9use std::default::Default;
10use std::ffi::CString;
11use std::fmt;
12use std::hash::{BuildHasher, Hash};
13use std::io;
14use std::ops::Deref;
15use std::str::from_utf8;
16
17use crate::errors::{RedisError, ServerError};
18
19#[non_exhaustive]
21pub enum Expiry {
22 EX(u64),
24 PX(u64),
26 EXAT(u64),
28 PXAT(u64),
30 PERSIST,
32}
33
34#[derive(Clone, Copy)]
36#[non_exhaustive]
37pub enum SetExpiry {
38 EX(u64),
40 PX(u64),
42 EXAT(u64),
44 PXAT(u64),
46 KEEPTTL,
48}
49
50impl ToRedisArgs for SetExpiry {
51 fn write_redis_args<W>(&self, out: &mut W)
52 where
53 W: ?Sized + RedisWrite,
54 {
55 let mut buf = ::itoa::Buffer::new();
56 match self {
57 Self::EX(secs) => {
58 out.write_arg(b"EX");
59 out.write_arg(buf.format(*secs).as_bytes());
60 }
61 Self::PX(millis) => {
62 out.write_arg(b"PX");
63 out.write_arg(buf.format(*millis).as_bytes());
64 }
65 Self::EXAT(unix_time) => {
66 out.write_arg(b"EXAT");
67 out.write_arg(buf.format(*unix_time).as_bytes());
68 }
69 Self::PXAT(unix_time) => {
70 out.write_arg(b"PXAT");
71 out.write_arg(buf.format(*unix_time).as_bytes());
72 }
73 Self::KEEPTTL => {
74 out.write_arg(b"KEEPTTL");
75 }
76 }
77 }
78}
79
80#[derive(Clone, Copy)]
82#[non_exhaustive]
83pub enum ExistenceCheck {
84 NX,
86 XX,
88}
89
90impl ToRedisArgs for ExistenceCheck {
91 fn write_redis_args<W>(&self, out: &mut W)
92 where
93 W: ?Sized + RedisWrite,
94 {
95 match self {
96 Self::NX => {
97 out.write_arg(b"NX");
98 }
99 Self::XX => {
100 out.write_arg(b"XX");
101 }
102 }
103 }
104}
105
106#[derive(Clone, Copy)]
108#[non_exhaustive]
109pub enum FieldExistenceCheck {
110 FNX,
112 FXX,
114}
115
116impl ToRedisArgs for FieldExistenceCheck {
117 fn write_redis_args<W>(&self, out: &mut W)
118 where
119 W: ?Sized + RedisWrite,
120 {
121 match self {
122 Self::FNX => out.write_arg(b"FNX"),
123 Self::FXX => out.write_arg(b"FXX"),
124 }
125 }
126}
127
128#[derive(PartialEq, Eq, Clone, Debug, Copy)]
131#[non_exhaustive]
132pub enum NumericBehavior {
133 NonNumeric,
135 NumberIsInteger,
137 NumberIsFloat,
139}
140
141#[derive(PartialEq, Clone, Default)]
143#[non_exhaustive]
144pub enum Value {
145 #[default]
147 Nil,
148 Int(i64),
153 BulkString(Vec<u8>),
155 Array(Vec<Self>),
158 SimpleString(String),
160 Okay,
162 Map(Vec<(Self, Self)>),
164 Attribute {
166 data: Box<Self>,
168 attributes: Vec<(Self, Self)>,
170 },
171 Set(Vec<Self>),
173 Double(f64),
175 Boolean(bool),
177 VerbatimString {
179 format: VerbatimFormat,
181 text: String,
183 },
184 #[cfg(feature = "num-bigint")]
185 BigNumber(BigInt),
187 #[cfg(not(feature = "num-bigint"))]
188 BigNumber(Vec<u8>),
190 Push {
192 kind: PushKind,
194 data: Vec<Self>,
196 },
197 ServerError(ServerError),
199}
200
201#[derive(Clone, Debug)]
214#[non_exhaustive]
215pub enum ValueComparison {
216 IFEQ(String),
218 IFNE(String),
220 IFDEQ(String),
222 IFDNE(String),
224}
225
226impl ValueComparison {
227 pub fn ifeq(value: impl ToSingleRedisArg) -> Self {
234 Self::IFEQ(Self::arg_to_string(value))
235 }
236
237 pub fn ifne(value: impl ToSingleRedisArg) -> Self {
244 Self::IFNE(Self::arg_to_string(value))
245 }
246
247 pub fn ifdeq(digest: impl ToSingleRedisArg) -> Self {
256 Self::IFDEQ(Self::arg_to_string(digest))
257 }
258
259 pub fn ifdne(digest: impl ToSingleRedisArg) -> Self {
268 Self::IFDNE(Self::arg_to_string(digest))
269 }
270
271 fn arg_to_string(value: impl ToSingleRedisArg) -> String {
272 let args = value.to_redis_args();
273 String::from_utf8_lossy(&args[0]).into_owned()
274 }
275}
276
277impl ToRedisArgs for ValueComparison {
278 fn write_redis_args<W>(&self, out: &mut W)
279 where
280 W: ?Sized + RedisWrite,
281 {
282 match self {
283 Self::IFEQ(value) => {
284 out.write_arg(b"IFEQ");
285 out.write_arg(value.as_bytes());
286 }
287 Self::IFNE(value) => {
288 out.write_arg(b"IFNE");
289 out.write_arg(value.as_bytes());
290 }
291 Self::IFDEQ(digest) => {
292 out.write_arg(b"IFDEQ");
293 out.write_arg(digest.as_bytes());
294 }
295 Self::IFDNE(digest) => {
296 out.write_arg(b"IFDNE");
297 out.write_arg(digest.as_bytes());
298 }
299 }
300 }
301}
302
303#[derive(PartialEq, Clone, Debug)]
305#[non_exhaustive]
306pub enum VerbatimFormat {
307 Unknown(String),
309 Markdown,
311 Text,
313}
314
315#[derive(PartialEq, Clone, Debug)]
317#[non_exhaustive]
318pub enum PushKind {
319 Disconnection,
321 Other(String),
323 Invalidate,
325 Message,
327 PMessage,
329 SMessage,
331 Unsubscribe,
333 PUnsubscribe,
335 SUnsubscribe,
337 Subscribe,
339 PSubscribe,
341 SSubscribe,
343}
344
345impl PushKind {
346 #[cfg(feature = "aio")]
347 pub(crate) fn has_reply(&self) -> bool {
348 matches!(
349 self,
350 &Self::Unsubscribe
351 | &Self::PUnsubscribe
352 | &Self::SUnsubscribe
353 | &Self::Subscribe
354 | &Self::PSubscribe
355 | &Self::SSubscribe
356 )
357 }
358}
359
360impl fmt::Display for VerbatimFormat {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 match self {
363 Self::Markdown => write!(f, "mkd"),
364 Self::Unknown(val) => write!(f, "{val}"),
365 Self::Text => write!(f, "txt"),
366 }
367 }
368}
369
370impl fmt::Display for PushKind {
371 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372 match self {
373 Self::Other(kind) => write!(f, "{kind}"),
374 Self::Invalidate => write!(f, "invalidate"),
375 Self::Message => write!(f, "message"),
376 Self::PMessage => write!(f, "pmessage"),
377 Self::SMessage => write!(f, "smessage"),
378 Self::Unsubscribe => write!(f, "unsubscribe"),
379 Self::PUnsubscribe => write!(f, "punsubscribe"),
380 Self::SUnsubscribe => write!(f, "sunsubscribe"),
381 Self::Subscribe => write!(f, "subscribe"),
382 Self::PSubscribe => write!(f, "psubscribe"),
383 Self::SSubscribe => write!(f, "ssubscribe"),
384 Self::Disconnection => write!(f, "disconnection"),
385 }
386 }
387}
388
389#[non_exhaustive]
390pub enum MapIter<'a> {
391 Array(std::slice::Iter<'a, Value>),
392 Map(std::slice::Iter<'a, (Value, Value)>),
393}
394
395impl<'a> Iterator for MapIter<'a> {
396 type Item = (&'a Value, &'a Value);
397
398 fn next(&mut self) -> Option<Self::Item> {
399 match self {
400 MapIter::Array(iter) => Some((iter.next()?, iter.next()?)),
401 MapIter::Map(iter) => {
402 let (k, v) = iter.next()?;
403 Some((k, v))
404 }
405 }
406 }
407
408 fn size_hint(&self) -> (usize, Option<usize>) {
409 match self {
410 MapIter::Array(iter) => iter.size_hint(),
411 MapIter::Map(iter) => iter.size_hint(),
412 }
413 }
414}
415
416#[non_exhaustive]
417pub enum OwnedMapIter {
418 Array(std::vec::IntoIter<Value>),
419 Map(std::vec::IntoIter<(Value, Value)>),
420}
421
422impl Iterator for OwnedMapIter {
423 type Item = (Value, Value);
424
425 fn next(&mut self) -> Option<Self::Item> {
426 match self {
427 Self::Array(iter) => Some((iter.next()?, iter.next()?)),
428 Self::Map(iter) => iter.next(),
429 }
430 }
431
432 fn size_hint(&self) -> (usize, Option<usize>) {
433 match self {
434 Self::Array(iter) => {
435 let (low, high) = iter.size_hint();
436 (low / 2, high.map(|h| h / 2))
437 }
438 Self::Map(iter) => iter.size_hint(),
439 }
440 }
441}
442
443impl Value {
451 pub fn looks_like_cursor(&self) -> bool {
456 match *self {
457 Self::Array(ref items) => {
458 if items.len() != 2 {
459 return false;
460 }
461 matches!(items[0], Self::BulkString(_)) && matches!(items[1], Self::Array(_))
462 }
463 _ => false,
464 }
465 }
466
467 pub fn as_sequence(&self) -> Option<&[Self]> {
469 match self {
470 Self::Array(items) | Self::Set(items) => Some(&items[..]),
471 Self::Nil => Some(&[]),
472 _ => None,
473 }
474 }
475
476 pub fn into_sequence(self) -> Result<Vec<Self>, Self> {
479 match self {
480 Self::Array(items) | Self::Set(items) => Ok(items),
481 Self::Nil => Ok(vec![]),
482 _ => Err(self),
483 }
484 }
485
486 pub fn as_map_iter(&self) -> Option<MapIter<'_>> {
488 match self {
489 Self::Array(items) => (items.len() % 2 == 0).then(|| MapIter::Array(items.iter())),
490 Self::Map(items) => Some(MapIter::Map(items.iter())),
491 _ => None,
492 }
493 }
494
495 pub fn into_map_iter(self) -> Result<OwnedMapIter, Self> {
498 match self {
499 Self::Array(items) => {
500 if items.len() % 2 == 0 {
501 Ok(OwnedMapIter::Array(items.into_iter()))
502 } else {
503 Err(Self::Array(items))
504 }
505 }
506 Self::Map(items) => Ok(OwnedMapIter::Map(items.into_iter())),
507 _ => Err(self),
508 }
509 }
510
511 pub fn extract_error(self) -> RedisResult<Self> {
513 match self {
514 Self::Array(val) => Ok(Self::Array(Self::extract_error_vec(val)?)),
515 Self::Map(map) => Ok(Self::Map(Self::extract_error_map(map)?)),
516 Self::Attribute { data, attributes } => {
517 let data = Box::new((*data).extract_error()?);
518 let attributes = Self::extract_error_map(attributes)?;
519 Ok(Self::Attribute { data, attributes })
520 }
521 Self::Set(set) => Ok(Self::Set(Self::extract_error_vec(set)?)),
522 Self::Push { kind, data } => Ok(Self::Push {
523 kind,
524 data: Self::extract_error_vec(data)?,
525 }),
526 Self::ServerError(err) => Err(err.into()),
527 _ => Ok(self),
528 }
529 }
530
531 pub(crate) fn extract_error_vec(vec: Vec<Self>) -> RedisResult<Vec<Self>> {
532 vec.into_iter()
533 .map(Self::extract_error)
534 .collect::<RedisResult<Vec<_>>>()
535 }
536
537 pub(crate) fn extract_error_map(map: Vec<(Self, Self)>) -> RedisResult<Vec<(Self, Self)>> {
538 let mut vec = Vec::with_capacity(map.len());
539 for (key, value) in map.into_iter() {
540 vec.push((key.extract_error()?, value.extract_error()?));
541 }
542 Ok(vec)
543 }
544
545 fn is_collection_of_len(&self, len: usize) -> bool {
546 match self {
547 Self::Array(values) | Self::Set(values) => values.len() == len,
548 Self::Map(items) => items.len() * 2 == len,
549 _ => false,
550 }
551 }
552
553 #[cfg(feature = "cluster-async")]
554 pub(crate) fn is_error_that_requires_action(&self) -> bool {
555 matches!(self, Self::ServerError(error) if error.requires_action())
556 }
557}
558
559impl fmt::Debug for Value {
560 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561 match *self {
562 Self::Nil => write!(f, "nil"),
563 Self::Int(val) => write!(f, "int({val:?})"),
564 Self::BulkString(ref val) => match from_utf8(val) {
565 Ok(x) => write!(f, "bulk-string('{x:?}')"),
566 Err(_) => write!(f, "binary-data({val:?})"),
567 },
568 Self::Array(ref values) => write!(f, "array({values:?})"),
569 Self::Push { ref kind, ref data } => write!(f, "push({kind:?}, {data:?})"),
570 Self::Okay => write!(f, "ok"),
571 Self::SimpleString(ref s) => write!(f, "simple-string({s:?})"),
572 Self::Map(ref values) => write!(f, "map({values:?})"),
573 Self::Attribute {
574 ref data,
575 attributes: _,
576 } => write!(f, "attribute({data:?})"),
577 Self::Set(ref values) => write!(f, "set({values:?})"),
578 Self::Double(ref d) => write!(f, "double({d:?})"),
579 Self::Boolean(ref b) => write!(f, "boolean({b:?})"),
580 Self::VerbatimString {
581 ref format,
582 ref text,
583 } => {
584 write!(f, "verbatim-string({format:?},{text:?})")
585 }
586 Self::BigNumber(ref m) => write!(f, "big-number({m:?})"),
587 Self::ServerError(ref err) => match err.details() {
588 Some(details) => write!(f, "Server error: `{}: {details}`", err.code()),
589 None => write!(f, "Server error: `{}`", err.code()),
590 },
591 }
592 }
593}
594
595pub type RedisResult<T> = Result<T, RedisError>;
597
598impl<T: FromRedisValue> FromRedisValue for RedisResult<T> {
599 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
600 match v {
601 Value::ServerError(err) => Ok(Err(err.clone().into())),
602 _ => from_redis_value_ref(v).map(|result| Ok(result)),
603 }
604 }
605
606 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
607 match v {
608 Value::ServerError(err) => Ok(Err(err.into())),
609 _ => from_redis_value(v).map(|result| Ok(result)),
610 }
611 }
612}
613
614#[cfg(feature = "aio")]
616pub type RedisFuture<'a, T> = futures_util::future::BoxFuture<'a, RedisResult<T>>;
617
618#[derive(Debug, Clone)]
645pub struct InfoDict {
646 map: HashMap<String, Value>,
647}
648
649impl InfoDict {
650 pub fn new(kvpairs: &str) -> Self {
655 let mut map = HashMap::new();
656 for line in kvpairs.lines() {
657 if line.is_empty() || line.starts_with('#') {
658 continue;
659 }
660 let mut p = line.splitn(2, ':');
661 let (k, v) = match (p.next(), p.next()) {
662 (Some(k), Some(v)) => (k.to_string(), v.to_string()),
663 _ => continue,
664 };
665 map.insert(k, Value::SimpleString(v));
666 }
667 Self { map }
668 }
669
670 pub fn get<T: FromRedisValue>(&self, key: &str) -> Option<T> {
673 match self.find(&key) {
674 Some(x) => from_redis_value_ref(x).ok(),
675 None => None,
676 }
677 }
678
679 pub fn find(&self, key: &&str) -> Option<&Value> {
681 self.map.get(*key)
682 }
683
684 pub fn contains_key(&self, key: &&str) -> bool {
686 self.find(key).is_some()
687 }
688
689 pub fn len(&self) -> usize {
691 self.map.len()
692 }
693
694 pub fn is_empty(&self) -> bool {
696 self.map.is_empty()
697 }
698}
699
700impl Deref for InfoDict {
701 type Target = HashMap<String, Value>;
702
703 fn deref(&self) -> &Self::Target {
704 &self.map
705 }
706}
707
708#[derive(Debug, Clone, Eq, PartialEq)]
712#[non_exhaustive]
713pub enum Role {
714 Primary {
716 replication_offset: u64,
718 replicas: Vec<ReplicaInfo>,
720 },
721 Replica {
723 primary_ip: String,
725 primary_port: u16,
727 replication_state: String,
729 data_received: u64,
731 },
732 Sentinel {
734 primary_names: Vec<String>,
736 },
737}
738
739#[derive(Debug, Clone, Eq, PartialEq)]
743pub struct ReplicaInfo {
744 pub ip: String,
746 pub port: u16,
748 pub replication_offset: i64,
750}
751
752impl FromRedisValue for ReplicaInfo {
753 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
754 Self::from_redis_value(v.clone())
755 }
756
757 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
758 let v = match get_owned_inner_value(v).into_sequence() {
759 Ok(v) => v,
760 Err(v) => crate::errors::invalid_type_error!(v, "Replica response should be an array"),
761 };
762 if v.len() < 3 {
763 crate::errors::invalid_type_error!(
764 v,
765 "Replica array is too short, expected 3 elements"
766 );
767 }
768 let mut v = v.into_iter();
769 let ip = from_redis_value(v.next().expect("len was checked"))?;
770 let port = from_redis_value(v.next().expect("len was checked"))?;
771 let offset = from_redis_value(v.next().expect("len was checked"))?;
772 Ok(Self {
773 ip,
774 port,
775 replication_offset: offset,
776 })
777 }
778}
779
780impl FromRedisValue for Role {
781 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
782 Self::from_redis_value(v.clone())
783 }
784
785 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
786 let v = match get_owned_inner_value(v).into_sequence() {
787 Ok(v) => v,
788 Err(v) => crate::errors::invalid_type_error!(v, "Role response should be an array"),
789 };
790 if v.len() < 2 {
791 crate::errors::invalid_type_error!(
792 v,
793 "Role array is too short, expected at least 2 elements"
794 );
795 }
796 match &v[0] {
797 Value::BulkString(role) => match role.as_slice() {
798 b"master" => Self::new_primary(v),
799 b"slave" => Self::new_replica(v),
800 b"sentinel" => Self::new_sentinel(v),
801 _ => crate::errors::invalid_type_error!(
802 v,
803 "Role type is not master, slave or sentinel"
804 ),
805 },
806 _ => crate::errors::invalid_type_error!(v, "Role type is not a bulk string"),
807 }
808 }
809}
810
811impl Role {
812 fn new_primary(values: Vec<Value>) -> Result<Self, ParsingError> {
813 if values.len() < 3 {
814 crate::errors::invalid_type_error!(
815 values,
816 "Role primary response too short, expected 3 elements"
817 );
818 }
819
820 let mut values = values.into_iter();
821 _ = values.next();
822
823 let replication_offset = from_redis_value(values.next().expect("len was checked"))?;
824 let replicas = from_redis_value(values.next().expect("len was checked"))?;
825
826 Ok(Self::Primary {
827 replication_offset,
828 replicas,
829 })
830 }
831
832 fn new_replica(values: Vec<Value>) -> Result<Self, ParsingError> {
833 if values.len() < 5 {
834 crate::errors::invalid_type_error!(
835 values,
836 "Role replica response too short, expected 5 elements"
837 );
838 }
839
840 let mut values = values.into_iter();
841 _ = values.next();
842
843 let primary_ip = from_redis_value(values.next().expect("len was checked"))?;
844 let primary_port = from_redis_value(values.next().expect("len was checked"))?;
845 let replication_state = from_redis_value(values.next().expect("len was checked"))?;
846 let data_received = from_redis_value(values.next().expect("len was checked"))?;
847
848 Ok(Self::Replica {
849 primary_ip,
850 primary_port,
851 replication_state,
852 data_received,
853 })
854 }
855
856 fn new_sentinel(values: Vec<Value>) -> Result<Self, ParsingError> {
857 if values.len() < 2 {
858 crate::errors::invalid_type_error!(
859 values,
860 "Role sentinel response too short, expected at least 2 elements"
861 );
862 }
863 let second_val = values.into_iter().nth(1).expect("len was checked");
864 let primary_names = from_redis_value(second_val)?;
865 Ok(Self::Sentinel { primary_names })
866 }
867}
868
869pub trait RedisWrite {
871 fn write_arg(&mut self, arg: &[u8]);
873
874 fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
876 self.write_arg(arg.to_string().as_bytes());
877 }
878
879 fn writer_for_next_arg(&mut self) -> impl io::Write + '_;
888
889 fn reserve_space_for_args(&mut self, additional: impl IntoIterator<Item = usize>) {
921 let _do_nothing = additional;
924 }
925
926 #[cfg(feature = "bytes")]
927 fn bufmut_for_next_arg(&mut self, capacity: usize) -> impl bytes::BufMut + '_ {
940 struct Wrapper<'a> {
948 buf: Vec<u8>,
950 writer: Box<dyn io::Write + 'a>,
952 }
953 unsafe impl bytes::BufMut for Wrapper<'_> {
954 fn remaining_mut(&self) -> usize {
955 self.buf.remaining_mut()
956 }
957
958 unsafe fn advance_mut(&mut self, cnt: usize) {
959 unsafe {
960 self.buf.advance_mut(cnt);
961 }
962 }
963
964 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
965 self.buf.chunk_mut()
966 }
967
968 fn put<T: bytes::buf::Buf>(&mut self, src: T)
970 where
971 Self: Sized,
972 {
973 self.buf.put(src);
974 }
975
976 fn put_slice(&mut self, src: &[u8]) {
977 self.buf.put_slice(src);
978 }
979
980 fn put_bytes(&mut self, val: u8, cnt: usize) {
981 self.buf.put_bytes(val, cnt);
982 }
983 }
984 impl Drop for Wrapper<'_> {
985 fn drop(&mut self) {
986 self.writer.write_all(&self.buf).unwrap();
987 }
988 }
989
990 Wrapper {
991 buf: Vec::with_capacity(capacity),
992 writer: Box::new(self.writer_for_next_arg()),
993 }
994 }
995}
996
997impl RedisWrite for Vec<Vec<u8>> {
998 fn write_arg(&mut self, arg: &[u8]) {
999 self.push(arg.to_owned());
1000 }
1001
1002 fn write_arg_fmt(&mut self, arg: impl fmt::Display) {
1003 self.push(arg.to_string().into_bytes());
1004 }
1005
1006 fn writer_for_next_arg(&mut self) -> impl io::Write + '_ {
1007 self.push(Vec::new());
1008 self.last_mut().unwrap()
1009 }
1010
1011 fn reserve_space_for_args(&mut self, additional: impl IntoIterator<Item = usize>) {
1012 self.reserve(additional.into_iter().count());
1017 }
1018
1019 #[cfg(feature = "bytes")]
1020 fn bufmut_for_next_arg(&mut self, capacity: usize) -> impl bytes::BufMut + '_ {
1021 self.push(Vec::with_capacity(capacity));
1022 self.last_mut().unwrap()
1023 }
1024}
1025
1026pub trait ToSingleRedisArg: ToRedisArgs {}
1031
1032pub trait ToRedisArgs: Sized {
1036 fn to_redis_args(&self) -> Vec<Vec<u8>> {
1042 let mut out = Vec::new();
1043 self.write_redis_args(&mut out);
1044 out
1045 }
1046
1047 fn write_redis_args<W>(&self, out: &mut W)
1052 where
1053 W: ?Sized + RedisWrite;
1054
1055 fn describe_numeric_behavior(&self) -> NumericBehavior {
1060 NumericBehavior::NonNumeric
1061 }
1062
1063 fn num_of_args(&self) -> usize {
1070 1
1071 }
1072
1073 #[doc(hidden)]
1076 fn write_args_from_slice<W>(items: &[Self], out: &mut W)
1077 where
1078 W: ?Sized + RedisWrite,
1079 {
1080 Self::make_arg_iter_ref(items.iter(), out);
1081 }
1082
1083 #[doc(hidden)]
1086 fn make_arg_iter_ref<'a, I, W>(items: I, out: &mut W)
1087 where
1088 W: ?Sized + RedisWrite,
1089 I: Iterator<Item = &'a Self>,
1090 Self: 'a,
1091 {
1092 for item in items {
1093 item.write_redis_args(out);
1094 }
1095 }
1096
1097 #[doc(hidden)]
1098 fn is_single_vec_arg(items: &[Self]) -> bool {
1099 items.len() == 1 && items[0].num_of_args() <= 1
1100 }
1101}
1102
1103macro_rules! itoa_based_to_redis_impl {
1104 ($t:ty, $numeric:expr) => {
1105 impl ToRedisArgs for $t {
1106 fn write_redis_args<W>(&self, out: &mut W)
1107 where
1108 W: ?Sized + RedisWrite,
1109 {
1110 let mut buf = ::itoa::Buffer::new();
1111 let s = buf.format(*self);
1112 out.write_arg(s.as_bytes())
1113 }
1114
1115 fn describe_numeric_behavior(&self) -> NumericBehavior {
1116 $numeric
1117 }
1118 }
1119
1120 impl ToSingleRedisArg for $t {}
1121 };
1122}
1123
1124macro_rules! non_zero_itoa_based_to_redis_impl {
1125 ($t:ty, $numeric:expr) => {
1126 impl ToRedisArgs for $t {
1127 fn write_redis_args<W>(&self, out: &mut W)
1128 where
1129 W: ?Sized + RedisWrite,
1130 {
1131 let mut buf = ::itoa::Buffer::new();
1132 let s = buf.format(self.get());
1133 out.write_arg(s.as_bytes())
1134 }
1135
1136 fn describe_numeric_behavior(&self) -> NumericBehavior {
1137 $numeric
1138 }
1139 }
1140
1141 impl ToSingleRedisArg for $t {}
1142 };
1143}
1144
1145macro_rules! ryu_based_to_redis_impl {
1146 ($t:ty, $numeric:expr) => {
1147 impl ToRedisArgs for $t {
1148 fn write_redis_args<W>(&self, out: &mut W)
1149 where
1150 W: ?Sized + RedisWrite,
1151 {
1152 let mut buf = ::ryu::Buffer::new();
1153 let s = buf.format(*self);
1154 out.write_arg(s.as_bytes())
1155 }
1156
1157 fn describe_numeric_behavior(&self) -> NumericBehavior {
1158 $numeric
1159 }
1160 }
1161
1162 impl ToSingleRedisArg for $t {}
1163 };
1164}
1165
1166impl ToRedisArgs for u8 {
1167 fn write_redis_args<W>(&self, out: &mut W)
1168 where
1169 W: ?Sized + RedisWrite,
1170 {
1171 let mut buf = ::itoa::Buffer::new();
1172 let s = buf.format(*self);
1173 out.write_arg(s.as_bytes());
1174 }
1175
1176 fn write_args_from_slice<W>(items: &[Self], out: &mut W)
1177 where
1178 W: ?Sized + RedisWrite,
1179 {
1180 out.write_arg(items);
1181 }
1182
1183 fn is_single_vec_arg(_items: &[Self]) -> bool {
1184 true
1185 }
1186}
1187
1188impl ToSingleRedisArg for u8 {}
1189
1190itoa_based_to_redis_impl!(i8, NumericBehavior::NumberIsInteger);
1191itoa_based_to_redis_impl!(i16, NumericBehavior::NumberIsInteger);
1192itoa_based_to_redis_impl!(u16, NumericBehavior::NumberIsInteger);
1193itoa_based_to_redis_impl!(i32, NumericBehavior::NumberIsInteger);
1194itoa_based_to_redis_impl!(u32, NumericBehavior::NumberIsInteger);
1195itoa_based_to_redis_impl!(i64, NumericBehavior::NumberIsInteger);
1196itoa_based_to_redis_impl!(u64, NumericBehavior::NumberIsInteger);
1197itoa_based_to_redis_impl!(i128, NumericBehavior::NumberIsInteger);
1198itoa_based_to_redis_impl!(u128, NumericBehavior::NumberIsInteger);
1199itoa_based_to_redis_impl!(isize, NumericBehavior::NumberIsInteger);
1200itoa_based_to_redis_impl!(usize, NumericBehavior::NumberIsInteger);
1201
1202non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU8, NumericBehavior::NumberIsInteger);
1203non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI8, NumericBehavior::NumberIsInteger);
1204non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU16, NumericBehavior::NumberIsInteger);
1205non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI16, NumericBehavior::NumberIsInteger);
1206non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU32, NumericBehavior::NumberIsInteger);
1207non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI32, NumericBehavior::NumberIsInteger);
1208non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU64, NumericBehavior::NumberIsInteger);
1209non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI64, NumericBehavior::NumberIsInteger);
1210non_zero_itoa_based_to_redis_impl!(core::num::NonZeroU128, NumericBehavior::NumberIsInteger);
1211non_zero_itoa_based_to_redis_impl!(core::num::NonZeroI128, NumericBehavior::NumberIsInteger);
1212non_zero_itoa_based_to_redis_impl!(core::num::NonZeroUsize, NumericBehavior::NumberIsInteger);
1213non_zero_itoa_based_to_redis_impl!(core::num::NonZeroIsize, NumericBehavior::NumberIsInteger);
1214
1215ryu_based_to_redis_impl!(f32, NumericBehavior::NumberIsFloat);
1216ryu_based_to_redis_impl!(f64, NumericBehavior::NumberIsFloat);
1217
1218#[cfg(any(
1219 feature = "rust_decimal",
1220 feature = "bigdecimal",
1221 feature = "num-bigint"
1222))]
1223macro_rules! bignum_to_redis_impl {
1224 ($t:ty) => {
1225 impl ToRedisArgs for $t {
1226 fn write_redis_args<W>(&self, out: &mut W)
1227 where
1228 W: ?Sized + RedisWrite,
1229 {
1230 out.write_arg(&self.to_string().into_bytes())
1231 }
1232 }
1233
1234 impl ToSingleRedisArg for $t {}
1235 };
1236}
1237
1238#[cfg(feature = "rust_decimal")]
1239bignum_to_redis_impl!(rust_decimal::Decimal);
1240#[cfg(feature = "bigdecimal")]
1241bignum_to_redis_impl!(bigdecimal::BigDecimal);
1242#[cfg(feature = "num-bigint")]
1243bignum_to_redis_impl!(num_bigint::BigInt);
1244#[cfg(feature = "num-bigint")]
1245bignum_to_redis_impl!(num_bigint::BigUint);
1246
1247impl ToRedisArgs for bool {
1248 fn write_redis_args<W>(&self, out: &mut W)
1249 where
1250 W: ?Sized + RedisWrite,
1251 {
1252 out.write_arg(if *self { b"1" } else { b"0" });
1253 }
1254}
1255
1256impl ToSingleRedisArg for bool {}
1257
1258impl ToRedisArgs for String {
1259 fn write_redis_args<W>(&self, out: &mut W)
1260 where
1261 W: ?Sized + RedisWrite,
1262 {
1263 out.write_arg(self.as_bytes());
1264 }
1265}
1266impl ToSingleRedisArg for String {}
1267
1268impl ToRedisArgs for &str {
1269 fn write_redis_args<W>(&self, out: &mut W)
1270 where
1271 W: ?Sized + RedisWrite,
1272 {
1273 out.write_arg(self.as_bytes());
1274 }
1275}
1276
1277impl ToSingleRedisArg for &str {}
1278
1279impl<'a, T> ToRedisArgs for Cow<'a, T>
1280where
1281 T: ToOwned + ?Sized,
1282 &'a T: ToRedisArgs,
1283 T::Owned: ToRedisArgs,
1284{
1285 fn write_redis_args<W>(&self, out: &mut W)
1286 where
1287 W: ?Sized + RedisWrite,
1288 {
1289 match self {
1290 Cow::Borrowed(inner) => inner.write_redis_args(out),
1291 Cow::Owned(inner) => inner.write_redis_args(out),
1292 }
1293 }
1294}
1295
1296impl<'a, T> ToSingleRedisArg for Cow<'a, T>
1297where
1298 T: ToOwned + ?Sized,
1299 &'a T: ToSingleRedisArg,
1300 T::Owned: ToSingleRedisArg,
1301{
1302}
1303
1304impl<T: ToRedisArgs> ToRedisArgs for Option<T> {
1305 fn write_redis_args<W>(&self, out: &mut W)
1306 where
1307 W: ?Sized + RedisWrite,
1308 {
1309 if let Some(ref x) = *self {
1310 x.write_redis_args(out);
1311 }
1312 }
1313
1314 fn describe_numeric_behavior(&self) -> NumericBehavior {
1315 match *self {
1316 Some(ref x) => x.describe_numeric_behavior(),
1317 None => NumericBehavior::NonNumeric,
1318 }
1319 }
1320
1321 fn num_of_args(&self) -> usize {
1322 match *self {
1323 Some(ref x) => x.num_of_args(),
1324 None => 0,
1325 }
1326 }
1327}
1328
1329macro_rules! impl_write_redis_args_for_collection {
1330 ($type:ty) => {
1331 impl<'a, T> ToRedisArgs for $type
1332 where
1333 T: ToRedisArgs,
1334 {
1335 #[inline]
1336 fn write_redis_args<W>(&self, out: &mut W)
1337 where
1338 W: ?Sized + RedisWrite,
1339 {
1340 ToRedisArgs::write_args_from_slice(self, out)
1341 }
1342
1343 fn num_of_args(&self) -> usize {
1344 if ToRedisArgs::is_single_vec_arg(&self[..]) {
1345 return 1;
1346 }
1347 if self.len() == 1 {
1348 self[0].num_of_args()
1349 } else {
1350 self.len()
1351 }
1352 }
1353
1354 fn describe_numeric_behavior(&self) -> NumericBehavior {
1355 NumericBehavior::NonNumeric
1356 }
1357 }
1358 };
1359}
1360
1361macro_rules! deref_to_write_redis_args_impl {
1362 ($type:ty) => {
1363 impl<'a, T> ToRedisArgs for $type
1364 where
1365 T: ToRedisArgs,
1366 {
1367 #[inline]
1368 fn write_redis_args<W>(&self, out: &mut W)
1369 where
1370 W: ?Sized + RedisWrite,
1371 {
1372 (**self).write_redis_args(out)
1373 }
1374
1375 fn num_of_args(&self) -> usize {
1376 (**self).num_of_args()
1377 }
1378
1379 fn describe_numeric_behavior(&self) -> NumericBehavior {
1380 (**self).describe_numeric_behavior()
1381 }
1382 }
1383
1384 impl<'a, T> ToSingleRedisArg for $type where T: ToSingleRedisArg {}
1385 };
1386}
1387
1388deref_to_write_redis_args_impl! {&'a T}
1389deref_to_write_redis_args_impl! {&'a mut T}
1390deref_to_write_redis_args_impl! {Box<T>}
1391deref_to_write_redis_args_impl! {std::sync::Arc<T>}
1392deref_to_write_redis_args_impl! {std::rc::Rc<T>}
1393impl_write_redis_args_for_collection! {&'a [T]}
1394impl_write_redis_args_for_collection! {&'a mut [T]}
1395impl_write_redis_args_for_collection! {Box<[T]>}
1396impl_write_redis_args_for_collection! {std::sync::Arc<[T]>}
1397impl_write_redis_args_for_collection! {std::rc::Rc<[T]>}
1398impl_write_redis_args_for_collection! {Vec<T>}
1399impl ToSingleRedisArg for &[u8] {}
1400impl ToSingleRedisArg for &mut [u8] {}
1401impl ToSingleRedisArg for Vec<u8> {}
1402impl ToSingleRedisArg for Box<[u8]> {}
1403impl ToSingleRedisArg for std::rc::Rc<[u8]> {}
1404impl ToSingleRedisArg for std::sync::Arc<[u8]> {}
1405
1406macro_rules! impl_to_redis_args_for_set {
1410 (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+) ) => {
1411 impl< $($TypeParam),+ > ToRedisArgs for $SetType
1412 where
1413 $($WhereClause)+
1414 {
1415 fn write_redis_args<W>(&self, out: &mut W)
1416 where
1417 W: ?Sized + RedisWrite,
1418 {
1419 ToRedisArgs::make_arg_iter_ref(self.iter(), out)
1420 }
1421
1422 fn num_of_args(&self) -> usize {
1423 self.len()
1424 }
1425 }
1426 };
1427}
1428
1429impl_to_redis_args_for_set!(
1430 for <T, S> std::collections::HashSet<T, S>,
1431 where (T: ToRedisArgs)
1432);
1433
1434impl_to_redis_args_for_set!(
1435 for <T> std::collections::BTreeSet<T>,
1436 where (T: ToRedisArgs)
1437);
1438
1439#[cfg(feature = "hashbrown")]
1440impl_to_redis_args_for_set!(
1441 for <T, S> hashbrown::HashSet<T, S>,
1442 where (T: ToRedisArgs)
1443);
1444
1445#[cfg(feature = "ahash")]
1446impl_to_redis_args_for_set!(
1447 for <T, S> ahash::AHashSet<T, S>,
1448 where (T: ToRedisArgs)
1449);
1450
1451macro_rules! impl_to_redis_args_for_map {
1455 (
1456 $(#[$meta:meta])*
1457 for <$($TypeParam:ident),+> $MapType:ty,
1458 where ($($WhereClause:tt)+)
1459 ) => {
1460 $(#[$meta])*
1461 impl< $($TypeParam),+ > ToRedisArgs for $MapType
1462 where
1463 $($WhereClause)+
1464 {
1465 fn write_redis_args<W>(&self, out: &mut W)
1466 where
1467 W: ?Sized + RedisWrite,
1468 {
1469 for (key, value) in self {
1470 assert!(key.num_of_args() <= 1 && value.num_of_args() <= 1);
1472 key.write_redis_args(out);
1473 value.write_redis_args(out);
1474 }
1475 }
1476
1477 fn num_of_args(&self) -> usize {
1478 self.len()
1479 }
1480 }
1481 };
1482}
1483
1484impl_to_redis_args_for_map!(
1485 for <K, V, S> std::collections::HashMap<K, V, S>,
1486 where (K: ToRedisArgs, V: ToRedisArgs)
1487);
1488
1489impl_to_redis_args_for_map!(
1490 for <K, V> std::collections::BTreeMap<K, V>,
1492 where (K: ToRedisArgs, V: ToRedisArgs)
1493);
1494
1495#[cfg(feature = "hashbrown")]
1496impl_to_redis_args_for_map!(
1497 for <K, V, S> hashbrown::HashMap<K, V, S>,
1498 where (K: ToRedisArgs, V: ToRedisArgs)
1499);
1500
1501#[cfg(feature = "ahash")]
1502impl_to_redis_args_for_map!(
1503 for <K, V, S> ahash::AHashMap<K, V, S>,
1504 where (K: ToRedisArgs, V: ToRedisArgs)
1505);
1506
1507macro_rules! to_redis_args_for_tuple {
1508 () => ();
1509 ($(#[$meta:meta],)*$($name:ident,)+) => (
1510 $(#[$meta])*
1511 impl<$($name: ToRedisArgs),*> ToRedisArgs for ($($name,)*) {
1512 #[allow(non_snake_case, unused_variables)]
1515 fn write_redis_args<W>(&self, out: &mut W) where W: ?Sized + RedisWrite {
1516 let ($(ref $name,)*) = *self;
1517 $($name.write_redis_args(out);)*
1518 }
1519
1520 #[allow(non_snake_case, unused_variables)]
1521 fn num_of_args(&self) -> usize {
1522 let mut n: usize = 0;
1523 $(let $name = (); n += 1;)*
1524 n
1525 }
1526 }
1527 )
1528}
1529
1530to_redis_args_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
1531to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, }
1532to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, }
1533to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
1534to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
1535to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
1536to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
1537to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
1538to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
1539to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
1540to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
1541to_redis_args_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
1542
1543impl<T: ToRedisArgs, const N: usize> ToRedisArgs for &[T; N] {
1544 fn write_redis_args<W>(&self, out: &mut W)
1545 where
1546 W: ?Sized + RedisWrite,
1547 {
1548 ToRedisArgs::write_args_from_slice(self.as_slice(), out);
1549 }
1550
1551 fn num_of_args(&self) -> usize {
1552 if ToRedisArgs::is_single_vec_arg(&self[..]) {
1553 return 1;
1554 }
1555 if self.len() == 1 {
1556 self[0].num_of_args()
1557 } else {
1558 self.len()
1559 }
1560 }
1561}
1562impl<const N: usize> ToSingleRedisArg for &[u8; N] {}
1563
1564fn vec_to_array<T, const N: usize>(
1565 items: Vec<T>,
1566 original_value: &Value,
1567) -> Result<[T; N], ParsingError> {
1568 match items.try_into() {
1569 Ok(array) => Ok(array),
1570 Err(items) => {
1571 let msg = format!(
1572 "Response has wrong dimension, expected {N}, got {}",
1573 items.len()
1574 );
1575 crate::errors::invalid_type_error!(original_value, msg)
1576 }
1577 }
1578}
1579
1580impl<T: FromRedisValue, const N: usize> FromRedisValue for [T; N] {
1581 fn from_redis_value_ref(v: &Value) -> Result<[T; N], ParsingError> {
1582 match *v {
1583 Value::BulkString(ref bytes) => match FromRedisValue::from_byte_slice(bytes) {
1584 Some(items) => vec_to_array(items, v),
1585 None => {
1586 let msg = format!(
1587 "Conversion to Array[{}; {N}] failed",
1588 std::any::type_name::<T>()
1589 );
1590 crate::errors::invalid_type_error!(v, msg)
1591 }
1592 },
1593 Value::Array(ref items) => {
1594 let items = FromRedisValue::from_redis_value_refs(items)?;
1595 vec_to_array(items, v)
1596 }
1597 Value::Nil => vec_to_array(vec![], v),
1598 _ => crate::errors::invalid_type_error!(v, "Response type not array compatible"),
1599 }
1600 }
1601
1602 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1603 Self::from_redis_value_ref(&v)
1604 }
1605}
1606
1607pub trait FromRedisValue: Sized {
1621 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
1625 Self::from_redis_value(v.clone())
1629 }
1630
1631 fn from_redis_value(v: Value) -> Result<Self, ParsingError>;
1635
1636 fn from_redis_value_refs(items: &[Value]) -> Result<Vec<Self>, ParsingError> {
1640 items
1641 .iter()
1642 .map(FromRedisValue::from_redis_value_ref)
1643 .collect()
1644 }
1645
1646 fn from_redis_values(items: Vec<Value>) -> Result<Vec<Self>, ParsingError> {
1649 items
1650 .into_iter()
1651 .map(FromRedisValue::from_redis_value)
1652 .collect()
1653 }
1654
1655 fn from_each_redis_values(items: Vec<Value>) -> Vec<Result<Self, ParsingError>> {
1658 items
1659 .into_iter()
1660 .map(FromRedisValue::from_redis_value)
1661 .collect()
1662 }
1663
1664 fn from_byte_slice(_vec: &[u8]) -> Option<Vec<Self>> {
1666 Self::from_redis_value(Value::BulkString(_vec.into()))
1667 .map(|rv| vec![rv])
1668 .ok()
1669 }
1670
1671 fn from_byte_vec(_vec: Vec<u8>) -> Result<Vec<Self>, ParsingError> {
1673 Self::from_redis_value(Value::BulkString(_vec)).map(|rv| vec![rv])
1674 }
1675}
1676
1677fn get_inner_value(v: &Value) -> &Value {
1678 if let Value::Attribute {
1679 data,
1680 attributes: _,
1681 } = v
1682 {
1683 data.as_ref()
1684 } else {
1685 v
1686 }
1687}
1688
1689fn get_owned_inner_value(v: Value) -> Value {
1690 if let Value::Attribute {
1691 data,
1692 attributes: _,
1693 } = v
1694 {
1695 *data
1696 } else {
1697 v
1698 }
1699}
1700
1701macro_rules! from_redis_value_for_num_internal {
1702 ($t:ty, $v:expr) => {{
1703 let v = if let Value::Attribute {
1704 data,
1705 attributes: _,
1706 } = $v
1707 {
1708 data
1709 } else {
1710 $v
1711 };
1712 match *v {
1713 Value::Int(val) => Ok(val as $t),
1714 Value::SimpleString(ref s) => match s.parse::<$t>() {
1715 Ok(rv) => Ok(rv),
1716 Err(_) => crate::errors::invalid_type_error!(v, "Could not convert from string."),
1717 },
1718 Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
1719 Ok(rv) => Ok(rv),
1720 Err(_) => crate::errors::invalid_type_error!(v, "Could not convert from string."),
1721 },
1722 Value::Double(val) => Ok(val as $t),
1723 _ => crate::errors::invalid_type_error!(v, "Response type not convertible to numeric."),
1724 }
1725 }};
1726}
1727
1728macro_rules! from_redis_value_for_num {
1729 ($t:ty) => {
1730 impl FromRedisValue for $t {
1731 fn from_redis_value_ref(v: &Value) -> Result<$t, ParsingError> {
1732 from_redis_value_for_num_internal!($t, v)
1733 }
1734
1735 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1736 Self::from_redis_value_ref(&v)
1737 }
1738 }
1739 };
1740}
1741
1742impl FromRedisValue for u8 {
1743 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
1744 from_redis_value_for_num_internal!(Self, v)
1745 }
1746
1747 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1748 Self::from_redis_value_ref(&v)
1749 }
1750
1751 fn from_byte_slice(vec: &[u8]) -> Option<Vec<Self>> {
1753 Some(vec.to_vec())
1754 }
1755 fn from_byte_vec(vec: Vec<u8>) -> Result<Vec<Self>, ParsingError> {
1756 Ok(vec)
1757 }
1758}
1759
1760from_redis_value_for_num!(i8);
1761from_redis_value_for_num!(i16);
1762from_redis_value_for_num!(u16);
1763from_redis_value_for_num!(i32);
1764from_redis_value_for_num!(u32);
1765from_redis_value_for_num!(i64);
1766from_redis_value_for_num!(u64);
1767from_redis_value_for_num!(i128);
1768from_redis_value_for_num!(u128);
1769from_redis_value_for_num!(f32);
1770from_redis_value_for_num!(f64);
1771from_redis_value_for_num!(isize);
1772from_redis_value_for_num!(usize);
1773
1774#[cfg(any(
1775 feature = "rust_decimal",
1776 feature = "bigdecimal",
1777 feature = "num-bigint"
1778))]
1779macro_rules! from_redis_value_for_bignum_internal {
1780 ($t:ty, $v:expr) => {{
1781 let v = $v;
1782 match *v {
1783 Value::Int(val) => <$t>::try_from(val).map_err(|_| {
1784 crate::errors::invalid_type_error_inner!(v, "Could not convert from integer.")
1785 }),
1786 Value::SimpleString(ref s) => match s.parse::<$t>() {
1787 Ok(rv) => Ok(rv),
1788 Err(_) => crate::errors::invalid_type_error!(v, "Could not convert from string."),
1789 },
1790 Value::BulkString(ref bytes) => match from_utf8(bytes)?.parse::<$t>() {
1791 Ok(rv) => Ok(rv),
1792 Err(_) => crate::errors::invalid_type_error!(v, "Could not convert from string."),
1793 },
1794 _ => crate::errors::invalid_type_error!(v, "Response type not convertible to numeric."),
1795 }
1796 }};
1797}
1798
1799#[cfg(any(
1800 feature = "rust_decimal",
1801 feature = "bigdecimal",
1802 feature = "num-bigint"
1803))]
1804macro_rules! from_redis_value_for_bignum {
1805 ($t:ty) => {
1806 impl FromRedisValue for $t {
1807 fn from_redis_value_ref(v: &Value) -> Result<$t, ParsingError> {
1808 from_redis_value_for_bignum_internal!($t, v)
1809 }
1810
1811 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1812 Self::from_redis_value_ref(&v)
1813 }
1814 }
1815 };
1816}
1817
1818#[cfg(feature = "rust_decimal")]
1819from_redis_value_for_bignum!(rust_decimal::Decimal);
1820#[cfg(feature = "bigdecimal")]
1821from_redis_value_for_bignum!(bigdecimal::BigDecimal);
1822#[cfg(feature = "num-bigint")]
1823from_redis_value_for_bignum!(num_bigint::BigInt);
1824#[cfg(feature = "num-bigint")]
1825from_redis_value_for_bignum!(num_bigint::BigUint);
1826
1827impl FromRedisValue for bool {
1828 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
1829 let v = get_inner_value(v);
1830 match *v {
1831 Value::Nil => Ok(false),
1832 Value::Int(val) => Ok(val != 0),
1833 Value::SimpleString(ref s) => {
1834 if &s[..] == "1" {
1835 Ok(true)
1836 } else if &s[..] == "0" {
1837 Ok(false)
1838 } else {
1839 crate::errors::invalid_type_error!(v, "Response status not valid boolean");
1840 }
1841 }
1842 Value::BulkString(ref bytes) => {
1843 if bytes == b"1" {
1844 Ok(true)
1845 } else if bytes == b"0" {
1846 Ok(false)
1847 } else {
1848 crate::errors::invalid_type_error!(v, "Response type not bool compatible.");
1849 }
1850 }
1851 Value::Boolean(b) => Ok(b),
1852 Value::Okay => Ok(true),
1853 _ => crate::errors::invalid_type_error!(v, "Response type not bool compatible."),
1854 }
1855 }
1856
1857 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1858 Self::from_redis_value_ref(&v)
1859 }
1860}
1861
1862impl FromRedisValue for CString {
1863 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
1864 let v = get_inner_value(v);
1865 match *v {
1866 Value::BulkString(ref bytes) => Ok(Self::new(bytes.as_slice())?),
1867 Value::Okay => Ok(Self::new("OK")?),
1868 Value::SimpleString(ref val) => Ok(Self::new(val.as_bytes())?),
1869 _ => crate::errors::invalid_type_error!(v, "Response type not CString compatible."),
1870 }
1871 }
1872 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1873 let v = get_owned_inner_value(v);
1874 match v {
1875 Value::BulkString(bytes) => Ok(Self::new(bytes)?),
1876 Value::Okay => Ok(Self::new("OK")?),
1877 Value::SimpleString(val) => Ok(Self::new(val)?),
1878 _ => crate::errors::invalid_type_error!(v, "Response type not CString compatible."),
1879 }
1880 }
1881}
1882
1883impl FromRedisValue for String {
1884 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
1885 let v = get_inner_value(v);
1886 match *v {
1887 Value::BulkString(ref bytes) => Ok(from_utf8(bytes)?.to_string()),
1888 Value::Okay => Ok("OK".to_string()),
1889 Value::SimpleString(ref val) => Ok(val.to_string()),
1890 Value::VerbatimString {
1891 format: _,
1892 ref text,
1893 } => Ok(text.to_string()),
1894 Value::Double(ref val) => Ok(val.to_string()),
1895 Value::Int(val) => Ok(val.to_string()),
1896 _ => crate::errors::invalid_type_error!(v, "Response type not string compatible."),
1897 }
1898 }
1899
1900 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
1901 let v = get_owned_inner_value(v);
1902 match v {
1903 Value::BulkString(bytes) => Ok(Self::from_utf8(bytes)?),
1904 Value::Okay => Ok("OK".to_string()),
1905 Value::SimpleString(val) => Ok(val),
1906 Value::VerbatimString { format: _, text } => Ok(text),
1907 Value::Double(val) => Ok(val.to_string()),
1908 Value::Int(val) => Ok(val.to_string()),
1909 _ => crate::errors::invalid_type_error!(v, "Response type not string compatible."),
1910 }
1911 }
1912}
1913
1914macro_rules! pointer_from_redis_value_impl {
1915 (
1916 $(#[$attr:meta])*
1917 $id:ident, $ty:ty, $func:expr
1918 ) => {
1919 $(#[$attr])*
1920 impl<$id: FromRedisValue> FromRedisValue for $ty {
1921 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError>
1922 {
1923 FromRedisValue::from_redis_value_ref(v).map($func)
1924 }
1925
1926 fn from_redis_value(v: Value) -> Result<Self, ParsingError>{
1927 FromRedisValue::from_redis_value(v).map($func)
1928 }
1929 }
1930 }
1931}
1932
1933pointer_from_redis_value_impl!(T, Box<T>, Box::new);
1934pointer_from_redis_value_impl!(T, std::sync::Arc<T>, std::sync::Arc::new);
1935pointer_from_redis_value_impl!(T, std::rc::Rc<T>, std::rc::Rc::new);
1936
1937macro_rules! from_vec_from_redis_value {
1942 (<$T:ident> $Type:ty) => {
1943 from_vec_from_redis_value!(<$T> $Type; Into::into);
1944 };
1945
1946 (<$T:ident> $Type:ty; $convert:expr) => {
1947 impl<$T: FromRedisValue> FromRedisValue for $Type {
1948 fn from_redis_value_ref(v: &Value) -> Result<$Type, ParsingError> {
1949 match v {
1950 Value::BulkString(bytes) => match FromRedisValue::from_byte_slice(bytes) {
1953 Some(x) => Ok($convert(x)),
1954 None => crate::errors::invalid_type_error!(
1955 v,
1956 format!("Conversion to {} failed.", std::any::type_name::<$Type>())
1957 ),
1958 },
1959 Value::Array(items) => FromRedisValue::from_redis_value_refs(items).map($convert),
1960 Value::Set(items) => FromRedisValue::from_redis_value_refs(items).map($convert),
1961 Value::Map(items) => {
1962 let mut n: Vec<T> = vec![];
1963 for item in items {
1964 match FromRedisValue::from_redis_value_ref(&Value::Map(vec![item.clone()])) {
1965 Ok(v) => {
1966 n.push(v);
1967 }
1968 Err(e) => {
1969 return Err(e);
1970 }
1971 }
1972 }
1973 Ok($convert(n))
1974 }
1975 Value::Nil => Ok($convert(Vec::new())),
1976 _ => crate::errors::invalid_type_error!(v, "Response type not vector compatible."),
1977 }
1978 }
1979 fn from_redis_value(v: Value) -> Result<$Type, ParsingError> {
1980 match v {
1981 Value::BulkString(bytes) => FromRedisValue::from_byte_vec(bytes).map($convert),
1985 Value::Array(items) => FromRedisValue::from_redis_values(items).map($convert),
1986 Value::Set(items) => FromRedisValue::from_redis_values(items).map($convert),
1987 Value::Map(items) => {
1988 let mut n: Vec<T> = vec![];
1989 for item in items {
1990 match FromRedisValue::from_redis_value(Value::Map(vec![item])) {
1991 Ok(v) => {
1992 n.push(v);
1993 }
1994 Err(e) => {
1995 return Err(e);
1996 }
1997 }
1998 }
1999 Ok($convert(n))
2000 }
2001 Value::Nil => Ok($convert(Vec::new())),
2002 _ => crate::errors::invalid_type_error!(v, "Response type not vector compatible."),
2003 }
2004 }
2005 }
2006 };
2007}
2008
2009from_vec_from_redis_value!(<T> Vec<T>);
2010from_vec_from_redis_value!(<T> std::sync::Arc<[T]>);
2011from_vec_from_redis_value!(<T> Box<[T]>; Vec::into_boxed_slice);
2012
2013macro_rules! impl_from_redis_value_for_map {
2014 (for <$($TypeParam:ident),+> $MapType:ty, where ($($WhereClause:tt)+)) => {
2015 impl< $($TypeParam),+ > FromRedisValue for $MapType
2016 where
2017 $($WhereClause)+
2018 {
2019 fn from_redis_value_ref(v: &Value) -> Result<$MapType, ParsingError> {
2020 let v = get_inner_value(v);
2021 match *v {
2022 Value::Nil => Ok(Default::default()),
2023 _ => v
2024 .as_map_iter()
2025 .ok_or_else(|| crate::errors::invalid_type_error_inner!(v, "Response type not map compatible"))?
2026 .map(|(k, v)| {
2027 Ok((from_redis_value_ref(k)?, from_redis_value_ref(v)?))
2028 })
2029 .collect(),
2030 }
2031 }
2032
2033 fn from_redis_value(v: Value) -> Result<$MapType, ParsingError> {
2034 let v = get_owned_inner_value(v);
2035 match v {
2036 Value::Nil => Ok(Default::default()),
2037 _ => v
2038 .into_map_iter()
2039 .map_err(|v| crate::errors::invalid_type_error_inner!(v, "Response type not map compatible"))?
2040 .map(|(k, v)| {
2041 Ok((from_redis_value(k)?, from_redis_value(v)?))
2042 })
2043 .collect(),
2044 }
2045 }
2046 }
2047 };
2048}
2049
2050impl_from_redis_value_for_map!(
2051 for <K, V, S> std::collections::HashMap<K, V, S>,
2052 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2053);
2054
2055impl_from_redis_value_for_map!(
2056 for <K, V> std::collections::BTreeMap<K, V>,
2057 where (K: FromRedisValue + Eq + Ord, V: FromRedisValue)
2058);
2059
2060#[cfg(feature = "hashbrown")]
2061impl_from_redis_value_for_map!(
2062 for <K, V, S> hashbrown::HashMap<K, V, S>,
2063 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default)
2064);
2065
2066#[cfg(feature = "ahash")]
2068impl_from_redis_value_for_map!(
2069 for <K, V> ahash::AHashMap<K, V>,
2070 where (K: FromRedisValue + Eq + Hash, V: FromRedisValue)
2071);
2072
2073macro_rules! impl_from_redis_value_for_set {
2074 (for <$($TypeParam:ident),+> $SetType:ty, where ($($WhereClause:tt)+)) => {
2075 impl< $($TypeParam),+ > FromRedisValue for $SetType
2076 where
2077 $($WhereClause)+
2078 {
2079 fn from_redis_value_ref(v: &Value) -> Result<$SetType, ParsingError> {
2080 let v = get_inner_value(v);
2081 let items = v
2082 .as_sequence()
2083 .ok_or_else(|| crate::errors::invalid_type_error_inner!(v, "Response type not map compatible"))?;
2084 items.iter().map(|item| from_redis_value_ref(item)).collect()
2085 }
2086
2087 fn from_redis_value(v: Value) -> Result<$SetType, ParsingError> {
2088 let v = get_owned_inner_value(v);
2089 let items = v
2090 .into_sequence()
2091 .map_err(|v| crate::errors::invalid_type_error_inner!(v, "Response type not map compatible"))?;
2092 items
2093 .into_iter()
2094 .map(|item| from_redis_value(item))
2095 .collect()
2096 }
2097 }
2098 };
2099}
2100
2101impl_from_redis_value_for_set!(
2102 for <T, S> std::collections::HashSet<T, S>,
2103 where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2104);
2105
2106impl_from_redis_value_for_set!(
2107 for <T> std::collections::BTreeSet<T>,
2108 where (T: FromRedisValue + Ord)
2109);
2110
2111#[cfg(feature = "hashbrown")]
2112impl_from_redis_value_for_set!(
2113 for <T, S> hashbrown::HashSet<T, S>,
2114 where (T: FromRedisValue + Eq + Hash, S: BuildHasher + Default)
2115);
2116
2117#[cfg(feature = "ahash")]
2119impl_from_redis_value_for_set!(
2120 for <T> ahash::AHashSet<T>,
2121 where (T: FromRedisValue + Eq + Hash)
2122);
2123
2124impl FromRedisValue for Value {
2125 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2126 Ok(v.clone())
2127 }
2128
2129 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2130 Ok(v)
2131 }
2132}
2133
2134impl FromRedisValue for () {
2135 fn from_redis_value_ref(v: &Value) -> Result<(), ParsingError> {
2136 match v {
2137 Value::ServerError(err) => Err(ParsingError::from(err.to_string())),
2138 _ => Ok(()),
2139 }
2140 }
2141
2142 fn from_redis_value(v: Value) -> Result<(), ParsingError> {
2143 Self::from_redis_value_ref(&v)
2144 }
2145}
2146
2147macro_rules! from_redis_value_for_tuple {
2148 () => ();
2149 ($(#[$meta:meta],)*$($name:ident,)+) => (
2150 $(#[$meta])*
2151 impl<$($name: FromRedisValue),*> FromRedisValue for ($($name,)*) {
2152 #[allow(non_snake_case, unused_variables)]
2155 fn from_redis_value_ref(v: &Value) -> Result<($($name,)*), ParsingError> {
2156 let v = get_inner_value(v);
2157 let mut n = 0;
2159 $(let $name = (); n += 1;)*
2160
2161 match *v {
2162 Value::Array(ref items) => {
2163 if items.len() != n {
2164 crate::errors::invalid_type_error!(v, "Array response of wrong dimension")
2165 }
2166
2167 let mut i = 0;
2169 Ok(($({let $name = (); from_redis_value_ref(
2170 &items[{ i += 1; i - 1 }])?},)*))
2171 }
2172
2173 Value::Set(ref items) => {
2174 if items.len() != n {
2175 crate::errors::invalid_type_error!(v, "Set response of wrong dimension")
2176 }
2177
2178 let mut i = 0;
2180 Ok(($({let $name = (); from_redis_value_ref(
2181 &items[{ i += 1; i - 1 }])?},)*))
2182 }
2183
2184 Value::Map(ref items) => {
2185 if n != items.len() * 2 {
2186 crate::errors::invalid_type_error!(v, "Map response of wrong dimension")
2187 }
2188
2189 let mut flatten_items = items.iter().map(|(a,b)|[a,b]).flatten();
2190
2191 Ok(($({let $name = (); from_redis_value_ref(
2192 &flatten_items.next().unwrap())?},)*))
2193 }
2194
2195 _ => crate::errors::invalid_type_error!(v, "Not a Array response")
2196 }
2197 }
2198
2199 #[allow(non_snake_case, unused_variables)]
2202 fn from_redis_value(v: Value) -> Result<($($name,)*), ParsingError> {
2203 let v = get_owned_inner_value(v);
2204 let mut n = 0;
2206 $(let $name = (); n += 1;)*
2207 match v {
2208 Value::Array(mut items) => {
2209 if items.len() != n {
2210 crate::errors::invalid_type_error!(Value::Array(items), "Array response of wrong dimension")
2211 }
2212
2213 let mut i = 0;
2215 Ok(($({let $name = (); from_redis_value(
2216 ::std::mem::replace(&mut items[{ i += 1; i - 1 }], Value::Nil)
2217 )?},)*))
2218 }
2219
2220 Value::Set(mut items) => {
2221 if items.len() != n {
2222 crate::errors::invalid_type_error!(Value::Array(items), "Set response of wrong dimension")
2223 }
2224
2225 let mut i = 0;
2227 Ok(($({let $name = (); from_redis_value(
2228 ::std::mem::replace(&mut items[{ i += 1; i - 1 }], Value::Nil)
2229 )?},)*))
2230 }
2231
2232 Value::Map(items) => {
2233 if n != items.len() * 2 {
2234 crate::errors::invalid_type_error!(Value::Map(items), "Map response of wrong dimension")
2235 }
2236
2237 let mut flatten_items = items.into_iter().map(|(a,b)|[a,b]).flatten();
2238
2239 Ok(($({let $name = (); from_redis_value(
2240 ::std::mem::replace(&mut flatten_items.next().unwrap(), Value::Nil)
2241 )?},)*))
2242 }
2243
2244 _ => crate::errors::invalid_type_error!(v, "Not a Array response")
2245 }
2246 }
2247
2248 #[allow(non_snake_case, unused_variables)]
2249 fn from_redis_value_refs(items: &[Value]) -> Result<Vec<($($name,)*)>, ParsingError> {
2250 let mut n = 0;
2252 $(let $name = (); n += 1;)*
2253 if items.len() == 0 {
2254 return Ok(vec![]);
2255 }
2256
2257 if items.iter().all(|item| item.is_collection_of_len(n)) {
2258 return items.iter().map(|item| from_redis_value_ref(item)).collect();
2259 }
2260
2261 let mut rv = Vec::with_capacity(items.len() / n);
2262 if let [$($name),*] = items {
2263 rv.push(($(from_redis_value_ref($name)?,)*));
2264 return Ok(rv);
2265 }
2266 for chunk in items.chunks(n) {
2267 match chunk {
2268 [$($name),*] => rv.push(($(from_redis_value_ref($name)?,)*)),
2269 _ => return Err(format!("Vector of length {} doesn't have arity of {n}", items.len()).into()),
2270 }
2271 }
2272 Ok(rv)
2273 }
2274
2275 #[allow(non_snake_case, unused_variables)]
2276 fn from_each_redis_values(mut items: Vec<Value>) -> Vec<Result<($($name,)*), ParsingError>> {
2277 #[allow(unused_parens)]
2278 let extract = |val: ($(Result<$name, ParsingError>,)*)| -> Result<($($name,)*), ParsingError> {
2279 let ($($name,)*) = val;
2280 Ok(($($name?,)*))
2281 };
2282
2283 let mut n = 0;
2285 $(let $name = (); n += 1;)*
2286
2287 if items.len() == 0 {
2289 return vec![];
2290 }
2291 if items.iter().all(|item| item.is_collection_of_len(n)) {
2292 return items.into_iter().map(|item| from_redis_value(item).map_err(|err|err.into())).collect();
2293 }
2294
2295 let mut rv = Vec::with_capacity(items.len() / n);
2296
2297 for chunk in items.chunks_mut(n) {
2298 match chunk {
2299 [$($name),*] => rv.push(extract(($(from_redis_value(std::mem::replace($name, Value::Nil)).into(),)*))),
2304 _ => return vec![Err(format!("Vector of length {} doesn't have arity of {n}", items.len()).into())],
2305 }
2306 }
2307 rv
2308 }
2309
2310 #[allow(non_snake_case, unused_variables)]
2311 fn from_redis_values(mut items: Vec<Value>) -> Result<Vec<($($name,)*)>, ParsingError> {
2312 let mut n = 0;
2314 $(let $name = (); n += 1;)*
2315
2316 if items.len() == 0 {
2318 return Ok(vec![])
2319 }
2320 if items.iter().all(|item| item.is_collection_of_len(n)) {
2321 return items.into_iter().map(|item| from_redis_value(item)).collect();
2322 }
2323
2324 let mut rv = Vec::with_capacity(items.len() / n);
2325 for chunk in items.chunks_mut(n) {
2326 match chunk {
2327 [$($name),*] => rv.push(($(from_redis_value(std::mem::replace($name, Value::Nil))?,)*)),
2332 _ => return Err(format!("Vector of length {} doesn't have arity of {n}", items.len()).into()),
2333 }
2334 }
2335 Ok(rv)
2336 }
2337 }
2338 )
2339}
2340
2341from_redis_value_for_tuple! { #[cfg_attr(docsrs, doc(fake_variadic))], #[doc = "This trait is implemented for tuples up to 12 items long."], T, }
2342from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, }
2343from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, }
2344from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, }
2345from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, }
2346from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, }
2347from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, }
2348from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, }
2349from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, }
2350from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, }
2351from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
2352from_redis_value_for_tuple! { #[doc(hidden)], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, }
2353
2354impl FromRedisValue for InfoDict {
2355 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2356 let v = get_inner_value(v);
2357 let s: String = from_redis_value_ref(v)?;
2358 Ok(Self::new(&s))
2359 }
2360 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2361 let v = get_owned_inner_value(v);
2362 let s: String = from_redis_value(v)?;
2363 Ok(Self::new(&s))
2364 }
2365}
2366
2367impl<T: FromRedisValue> FromRedisValue for Option<T> {
2368 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2369 let v = get_inner_value(v);
2370 if *v == Value::Nil {
2371 return Ok(None);
2372 }
2373 Ok(Some(from_redis_value_ref(v)?))
2374 }
2375 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2376 let v = get_owned_inner_value(v);
2377 if v == Value::Nil {
2378 return Ok(None);
2379 }
2380 Ok(Some(from_redis_value(v)?))
2381 }
2382}
2383
2384#[cfg(feature = "bytes")]
2385impl FromRedisValue for bytes::Bytes {
2386 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2387 let v = get_inner_value(v);
2388 match v {
2389 Value::BulkString(bytes_vec) => Ok(Self::copy_from_slice(bytes_vec.as_ref())),
2390 _ => crate::errors::invalid_type_error!(v, "Not a bulk string"),
2391 }
2392 }
2393 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2394 let v = get_owned_inner_value(v);
2395 match v {
2396 Value::BulkString(bytes_vec) => Ok(bytes_vec.into()),
2397 _ => crate::errors::invalid_type_error!(v, "Not a bulk string"),
2398 }
2399 }
2400}
2401
2402#[cfg(feature = "uuid")]
2403impl FromRedisValue for uuid::Uuid {
2404 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2405 match *v {
2406 Value::BulkString(ref bytes) => Ok(Self::from_slice(bytes)?),
2407 _ => crate::errors::invalid_type_error!(v, "Response type not uuid compatible."),
2408 }
2409 }
2410
2411 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2412 Self::from_redis_value_ref(&v)
2413 }
2414}
2415
2416#[cfg(feature = "uuid")]
2417impl ToRedisArgs for uuid::Uuid {
2418 fn write_redis_args<W>(&self, out: &mut W)
2419 where
2420 W: ?Sized + RedisWrite,
2421 {
2422 out.write_arg(self.as_bytes());
2423 }
2424}
2425
2426#[cfg(feature = "uuid")]
2427impl ToSingleRedisArg for uuid::Uuid {}
2428
2429pub fn from_redis_value_ref<T: FromRedisValue>(v: &Value) -> Result<T, ParsingError> {
2432 FromRedisValue::from_redis_value_ref(v)
2433}
2434
2435pub fn from_redis_value<T: FromRedisValue>(v: Value) -> Result<T, ParsingError> {
2438 FromRedisValue::from_redis_value(v)
2439}
2440
2441pub fn calculate_value_digest<T: ToRedisArgs>(value: T) -> String {
2457 use xxhash_rust::xxh3::xxh3_64;
2458
2459 let args = value.to_redis_args();
2461
2462 let mut combined_bytes = Vec::new();
2465 for arg in args {
2466 combined_bytes.extend_from_slice(&arg);
2467 }
2468
2469 let hash = xxh3_64(&combined_bytes);
2471 format!("{hash:016x}")
2472}
2473
2474pub fn is_valid_16_bytes_hex_digest(s: &str) -> bool {
2476 s.len() == 16 && s.chars().all(|c| c.is_ascii_hexdigit())
2477}
2478
2479#[derive(Clone, Eq, PartialEq, Default, Debug, Copy)]
2484#[non_exhaustive]
2485pub enum ProtocolVersion {
2486 #[default]
2488 RESP2,
2489 RESP3,
2491}
2492
2493impl ProtocolVersion {
2494 pub fn supports_resp3(&self) -> bool {
2496 !matches!(self, Self::RESP2)
2497 }
2498}
2499
2500#[derive(Clone, Copy)]
2502#[non_exhaustive]
2503pub enum ExpireOption {
2504 NONE,
2506 NX,
2508 XX,
2510 GT,
2512 LT,
2514}
2515
2516impl ToRedisArgs for ExpireOption {
2517 fn write_redis_args<W>(&self, out: &mut W)
2518 where
2519 W: ?Sized + RedisWrite,
2520 {
2521 match self {
2522 Self::NX => out.write_arg(b"NX"),
2523 Self::XX => out.write_arg(b"XX"),
2524 Self::GT => out.write_arg(b"GT"),
2525 Self::LT => out.write_arg(b"LT"),
2526 _ => {}
2527 }
2528 }
2529}
2530
2531#[derive(Debug, Clone, PartialEq)]
2532pub struct PushInfo {
2534 pub kind: PushKind,
2536 pub data: Vec<Value>,
2538}
2539
2540impl PushInfo {
2541 pub(crate) fn disconnect() -> Self {
2542 Self {
2543 kind: crate::PushKind::Disconnection,
2544 data: vec![],
2545 }
2546 }
2547}
2548
2549pub(crate) type SyncPushSender = std::sync::mpsc::Sender<PushInfo>;
2550
2551#[derive(Debug, Clone, PartialEq)]
2553#[non_exhaustive]
2554pub enum ValueType {
2555 None,
2557 String,
2559 List,
2561 Set,
2563 ZSet,
2565 Hash,
2567 Stream,
2569 VectorSet,
2571 JSON,
2573 BloomFilterRedis,
2575 CuckooFilter,
2577 CountMin,
2579 TDigest,
2581 TopK,
2583 TimeSeries,
2585 Trie,
2587 BloomFilterValKey,
2589 Unknown(String),
2591}
2592
2593impl<T: AsRef<str>> From<T> for ValueType {
2594 fn from(s: T) -> Self {
2595 match s.as_ref() {
2596 "none" => Self::None,
2597 "string" => Self::String,
2598 "list" => Self::List,
2599 "set" => Self::Set,
2600 "zset" => Self::ZSet,
2601 "hash" => Self::Hash,
2602 "stream" => Self::Stream,
2603 "vectorset" => Self::VectorSet,
2604 "ReJSON-RL" => Self::JSON,
2606 "CMSk-TYPE" => Self::CountMin,
2608 "MBbloom--" => Self::BloomFilterRedis,
2609 "MBbloomCF" => Self::CuckooFilter,
2610 "TDIS-TYPE" => Self::TDigest,
2611 "TopK-TYPE" => Self::TopK,
2612 "trietype0" => Self::Trie,
2614 "TSDB-TYPE" => Self::TimeSeries,
2616 "bloomfltr" => Self::BloomFilterValKey,
2618 s => Self::Unknown(s.to_string()),
2620 }
2621 }
2622}
2623
2624impl From<ValueType> for String {
2625 fn from(v: ValueType) -> Self {
2626 match v {
2627 ValueType::None => "none".to_string(),
2628 ValueType::String => "string".to_string(),
2629 ValueType::List => "list".to_string(),
2630 ValueType::Set => "set".to_string(),
2631 ValueType::ZSet => "zset".to_string(),
2632 ValueType::Hash => "hash".to_string(),
2633 ValueType::Stream => "stream".to_string(),
2634 ValueType::VectorSet => "vectorset".to_string(),
2635 ValueType::JSON => "ReJSON-RL".to_string(),
2637 ValueType::BloomFilterRedis => "MBbloom--".to_string(),
2639 ValueType::CuckooFilter => "MBbloomCF".to_string(),
2640 ValueType::TDigest => "TDIS-TYPE".to_string(),
2641 ValueType::TopK => "TopK-TYPE".to_string(),
2642 ValueType::CountMin => "CMSk-TYPE".to_string(),
2643 ValueType::Trie => "trietype0".to_string(),
2645 ValueType::TimeSeries => "TSDB-TYPE".to_string(),
2647 ValueType::BloomFilterValKey => "bloomfltr".to_string(),
2649 ValueType::Unknown(s) => s,
2651 }
2652 }
2653}
2654
2655impl FromRedisValue for ValueType {
2656 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2657 match v {
2658 Value::SimpleString(s) => Ok(s.into()),
2659 _ => crate::errors::invalid_type_error!(v, "Value type should be a simple string"),
2660 }
2661 }
2662
2663 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2664 match v {
2665 Value::SimpleString(s) => Ok(s.into()),
2666 _ => crate::errors::invalid_type_error!(v, "Value type should be a simple string"),
2667 }
2668 }
2669}
2670
2671#[derive(Debug, PartialEq, Clone)]
2673#[non_exhaustive]
2674pub enum IntegerReplyOrNoOp {
2675 IntegerReply(usize),
2677 NotExists,
2679 ExistsButNotRelevant,
2681}
2682
2683impl IntegerReplyOrNoOp {
2684 pub fn raw(&self) -> isize {
2686 match self {
2687 Self::IntegerReply(s) => *s as isize,
2688 Self::NotExists => -2,
2689 Self::ExistsButNotRelevant => -1,
2690 }
2691 }
2692}
2693
2694impl FromRedisValue for IntegerReplyOrNoOp {
2695 fn from_redis_value_ref(v: &Value) -> Result<Self, ParsingError> {
2696 match v {
2697 Value::Int(s) => match s {
2698 -2 => Ok(Self::NotExists),
2699 -1 => Ok(Self::ExistsButNotRelevant),
2700 _ => Ok(Self::IntegerReply(*s as usize)),
2701 },
2702 _ => crate::errors::invalid_type_error!(v, "Value should be an integer"),
2703 }
2704 }
2705
2706 fn from_redis_value(v: Value) -> Result<Self, ParsingError> {
2707 match v {
2708 Value::Int(s) => match s {
2709 -2 => Ok(Self::NotExists),
2710 -1 => Ok(Self::ExistsButNotRelevant),
2711 _ => Ok(Self::IntegerReply(s as usize)),
2712 },
2713 _ => crate::errors::invalid_type_error!(v, "Value should be an integer"),
2714 }
2715 }
2716}
2717
2718impl PartialEq<isize> for IntegerReplyOrNoOp {
2719 fn eq(&self, other: &isize) -> bool {
2720 match self {
2721 Self::IntegerReply(s) => *s as isize == *other,
2722 Self::NotExists => *other == -2,
2723 Self::ExistsButNotRelevant => *other == -1,
2724 }
2725 }
2726}
2727
2728impl PartialEq<usize> for IntegerReplyOrNoOp {
2729 fn eq(&self, other: &usize) -> bool {
2730 match self {
2731 Self::IntegerReply(s) => *s == *other,
2732 _ => false,
2733 }
2734 }
2735}
2736
2737impl PartialEq<i32> for IntegerReplyOrNoOp {
2738 fn eq(&self, other: &i32) -> bool {
2739 match self {
2740 Self::IntegerReply(s) => *s as i32 == *other,
2741 Self::NotExists => *other == -2,
2742 Self::ExistsButNotRelevant => *other == -1,
2743 }
2744 }
2745}
2746
2747impl PartialEq<u32> for IntegerReplyOrNoOp {
2748 fn eq(&self, other: &u32) -> bool {
2749 match self {
2750 Self::IntegerReply(s) => *s as u32 == *other,
2751 _ => false,
2752 }
2753 }
2754}