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