redis_driver/resp/
from_value.rs

1use crate::{
2    resp::{BulkString, Command, IntoValueIterator, Value},
3    Error, Result,
4};
5use smallvec::{smallvec, SmallVec};
6use std::{
7    borrow::Borrow,
8    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
9    fmt::Display,
10    hash::{BuildHasher, Hash},
11};
12
13pub trait FromValue: Sized {
14    /// Used to do [`Value`](crate::resp::Value) to user type conversion
15    ///
16    /// # Errors
17    ///
18    /// Any parsing error ([`Error::Client`](crate::Error::Client)) due to incompatibility between Value variant and taget type
19    fn from_value(value: Value) -> Result<Self>;
20
21    fn from_value_with_command(value: Value, _command: &Command) -> Result<Self> {
22        Self::from_value(value)
23    }
24
25    #[must_use]
26    #[allow(clippy::complexity)]
27    fn next_functor<I: Iterator<Item = Value>>() -> Box<dyn FnMut(&mut I) -> Option<Result<Self>>> {
28        Box::new(|iter| {
29            let value = iter.next()?;
30            Some(value.into())
31        })
32    }
33}
34
35impl FromValue for Value {
36    fn from_value(value: Value) -> Result<Self> {
37        Ok(value)
38    }
39}
40
41impl FromValue for () {
42    fn from_value(value: Value) -> Result<Self> {
43        match value {
44            Value::SimpleString(_) => Ok(()),
45            _ => Err(Error::Client(format!(
46                "Cannot parse result {:?} to ())",
47                value
48            ))),
49        }
50    }
51}
52
53impl<T, const N: usize> FromValue for [T; N]
54where
55    T: FromValue,
56{
57    fn from_value(value: Value) -> Result<Self> {
58        match value {
59            Value::Array(Some(v)) if v.len() == N => v
60                .into_value_iter()
61                .collect::<Result<Vec<T>>>()?
62                .try_into()
63                .map_err(|_| Error::Client("Cannot convert vec to array".to_owned())),
64            Value::Error(e) => Err(Error::Redis(e)),
65            _ => Err(Error::Client(
66                "Cannot convert Nil into static array".to_owned(),
67            )),
68        }
69    }
70}
71
72impl<T> FromValue for Vec<T>
73where
74    T: FromValue,
75{
76    fn from_value(value: Value) -> Result<Self> {
77        match value {
78            Value::BulkString(None) | Value::Array(None) => Ok(Vec::new()),
79            Value::Array(Some(v)) => v.into_value_iter().collect(),
80            Value::Error(e) => Err(Error::Redis(e)),
81            _ => Ok(vec![value.into()?]),
82        }
83    }
84}
85
86impl<T, A> FromValue for SmallVec<A>
87where
88    A: smallvec::Array<Item = T>,
89    T: FromValue,
90{
91    fn from_value(value: Value) -> Result<Self> {
92        match value {
93            Value::BulkString(None) | Value::Array(None) => Ok(SmallVec::new()),
94            Value::Array(Some(v)) => v.into_value_iter().collect(),
95            Value::Error(e) => Err(Error::Redis(e)),
96            _ => Ok(smallvec![value.into()?]),
97        }
98    }
99}
100
101impl<T, S: BuildHasher + Default> FromValue for HashSet<T, S>
102where
103    T: FromValue + Eq + Hash,
104{
105    fn from_value(value: Value) -> Result<Self> {
106        match value {
107            Value::BulkString(None) | Value::Array(None) => Ok(HashSet::default()),
108            Value::Array(Some(v)) => v.into_value_iter().collect(),
109            Value::Error(e) => Err(Error::Redis(e)),
110            _ => {
111                let mut hash_set = HashSet::default();
112                hash_set.insert(value.into()?);
113                Ok(hash_set)
114            }
115        }
116    }
117}
118
119impl<T> FromValue for BTreeSet<T>
120where
121    T: FromValue + Ord,
122{
123    fn from_value(value: Value) -> Result<Self> {
124        match value {
125            Value::BulkString(None) | Value::Array(None) => Ok(BTreeSet::new()),
126            Value::Array(Some(v)) => v.into_value_iter().collect(),
127            Value::Error(e) => Err(Error::Redis(e)),
128            _ => Ok(BTreeSet::from([value.into()?])),
129        }
130    }
131}
132
133impl<K, V, S: BuildHasher + Default> FromValue for HashMap<K, V, S>
134where
135    K: FromValue + Eq + Hash,
136    V: FromValue,
137{
138    fn from_value(value: Value) -> Result<Self> {
139        match value {
140            Value::BulkString(None) | Value::Array(None) => Ok(HashMap::default()),
141            Value::Array(Some(v)) => v.into_value_iter().collect(),
142            Value::Error(e) => Err(Error::Redis(e)),
143            _ => Err(Error::Client("Unexpected result value type".to_owned())),
144        }
145    }
146}
147
148impl<K, V> FromValue for BTreeMap<K, V>
149where
150    K: FromValue + Ord,
151    V: FromValue,
152{
153    fn from_value(value: Value) -> Result<Self> {
154        match value {
155            Value::BulkString(None) | Value::Array(None) => Ok(BTreeMap::new()),
156            Value::Array(Some(v)) => v.into_value_iter().collect(),
157            Value::Error(e) => Err(Error::Redis(e)),
158            _ => Err(Error::Client("Unexpected result value type".to_owned())),
159        }
160    }
161}
162
163impl<T> FromValue for Option<T>
164where
165    T: FromValue,
166{
167    fn from_value(value: Value) -> Result<Self> {
168        match value {
169            Value::BulkString(None) | Value::Array(None) => Ok(None),
170            Value::Array(Some(a)) if a.is_empty() => Ok(None),
171            Value::Error(e) => Err(Error::Redis(e)),
172            _ => T::from_value(value).map(|v| Some(v)),
173        }
174    }
175}
176
177impl FromValue for bool {
178    fn from_value(value: Value) -> Result<Self> {
179        match value {
180            Value::Integer(i) => Ok(i != 0),
181            Value::SimpleString(s) if s == "OK" => Ok(true),
182            Value::BulkString(None) => Ok(false),
183            Value::BulkString(Some(s)) if s == b"0" || s == b"false" => Ok(false),
184            Value::BulkString(Some(s)) if s == b"1" || s == b"true" => Ok(true),
185            Value::Error(e) => Err(Error::Redis(e)),
186            _ => Err(Error::Client(format!(
187                "Cannot parse result {:?} to bool",
188                value
189            ))),
190        }
191    }
192}
193
194impl FromValue for i64 {
195    fn from_value(value: Value) -> Result<Self> {
196        match value {
197            Value::Integer(i) => Ok(i),
198            Value::BulkString(None) | Value::Array(None) => Ok(0),
199            Value::BulkString(Some(s)) => {
200                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
201                    Ok(s) => match s.parse::<i64>() {
202                        Ok(u) => Ok(u),
203                        Err(e) => Err(Error::Client(e.to_string())),
204                    },
205                    Err(e) => Err(e),
206                }
207            }
208            Value::SimpleString(s) => match s.parse::<i64>() {
209                Ok(u) => Ok(u),
210                Err(e) => Err(Error::Client(e.to_string())),
211            },
212            Value::Error(e) => Err(Error::Redis(e)),
213            _ => Err(Error::Client(format!(
214                "Cannot parse result {:?} to i64",
215                value
216            ))),
217        }
218    }
219}
220
221impl FromValue for u64 {
222    fn from_value(value: Value) -> Result<Self> {
223        match value {
224            Value::Integer(i) => {
225                u64::try_from(i).map_err(|_| Error::Client("Cannot parse result to u64".to_owned()))
226            }
227            Value::BulkString(None) | Value::Array(None) => Ok(0),
228            Value::BulkString(Some(s)) => {
229                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
230                    Ok(s) => match s.parse::<u64>() {
231                        Ok(u) => Ok(u),
232                        Err(e) => Err(Error::Client(e.to_string())),
233                    },
234                    Err(e) => Err(e),
235                }
236            }
237            Value::SimpleString(s) => match s.parse::<u64>() {
238                Ok(u) => Ok(u),
239                Err(e) => Err(Error::Client(e.to_string())),
240            },
241            Value::Error(e) => Err(Error::Redis(e)),
242            _ => Err(Error::Client(format!(
243                "Cannot parse result {:?} to u64",
244                value
245            ))),
246        }
247    }
248}
249
250impl FromValue for i32 {
251    fn from_value(value: Value) -> Result<Self> {
252        match value {
253            Value::Integer(i) => {
254                i32::try_from(i).map_err(|_| Error::Client("Cannot parse result to i32".to_owned()))
255            }
256            Value::BulkString(None) | Value::Array(None) => Ok(0),
257            Value::BulkString(Some(s)) => {
258                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
259                    Ok(s) => match s.parse::<i32>() {
260                        Ok(u) => Ok(u),
261                        Err(e) => Err(Error::Client(e.to_string())),
262                    },
263                    Err(e) => Err(e),
264                }
265            }
266            Value::SimpleString(s) => match s.parse::<i32>() {
267                Ok(u) => Ok(u),
268                Err(e) => Err(Error::Client(e.to_string())),
269            },
270            Value::Error(e) => Err(Error::Redis(e)),
271            _ => Err(Error::Client(format!(
272                "Cannot parse result {:?} to i32",
273                value
274            ))),
275        }
276    }
277}
278
279impl FromValue for u32 {
280    fn from_value(value: Value) -> Result<Self> {
281        match value {
282            Value::Integer(i) => {
283                u32::try_from(i).map_err(|_| Error::Client("Cannot parse result to u32".to_owned()))
284            }
285            Value::BulkString(None) | Value::Array(None) => Ok(0),
286            Value::BulkString(Some(s)) => {
287                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
288                    Ok(s) => match s.parse::<u32>() {
289                        Ok(u) => Ok(u),
290                        Err(e) => Err(Error::Client(e.to_string())),
291                    },
292                    Err(e) => Err(e),
293                }
294            }
295            Value::SimpleString(s) => match s.parse::<u32>() {
296                Ok(u) => Ok(u),
297                Err(e) => Err(Error::Client(e.to_string())),
298            },
299            Value::Error(e) => Err(Error::Redis(e)),
300            _ => Err(Error::Client(format!(
301                "Cannot parse result {:?} to u32",
302                value
303            ))),
304        }
305    }
306}
307
308impl FromValue for i16 {
309    fn from_value(value: Value) -> Result<Self> {
310        match value {
311            Value::Integer(i) => {
312                i16::try_from(i).map_err(|_| Error::Client("Cannot parse result to i16".to_owned()))
313            }
314            Value::BulkString(None) | Value::Array(None) => Ok(0),
315            Value::BulkString(Some(s)) => {
316                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
317                    Ok(s) => match s.parse::<i16>() {
318                        Ok(u) => Ok(u),
319                        Err(e) => Err(Error::Client(e.to_string())),
320                    },
321                    Err(e) => Err(e),
322                }
323            }
324            Value::SimpleString(s) => match s.parse::<i16>() {
325                Ok(u) => Ok(u),
326                Err(e) => Err(Error::Client(e.to_string())),
327            },
328            Value::Error(e) => Err(Error::Redis(e)),
329            _ => Err(Error::Client(format!(
330                "Cannot parse result {:?} to i16",
331                value
332            ))),
333        }
334    }
335}
336
337impl FromValue for u16 {
338    fn from_value(value: Value) -> Result<Self> {
339        match value {
340            Value::Integer(i) => {
341                u16::try_from(i).map_err(|_| Error::Client("Cannot parse result to u16".to_owned()))
342            }
343            Value::BulkString(None) | Value::Array(None) => Ok(0),
344            Value::BulkString(Some(s)) => {
345                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
346                    Ok(s) => match s.parse::<u16>() {
347                        Ok(u) => Ok(u),
348                        Err(e) => Err(Error::Client(e.to_string())),
349                    },
350                    Err(e) => Err(e),
351                }
352            }
353            Value::SimpleString(s) => match s.parse::<u16>() {
354                Ok(u) => Ok(u),
355                Err(e) => Err(Error::Client(e.to_string())),
356            },
357            Value::Error(e) => Err(Error::Redis(e)),
358            _ => Err(Error::Client(format!(
359                "Cannot parse result {:?} to u16",
360                value
361            ))),
362        }
363    }
364}
365
366impl FromValue for i8 {
367    fn from_value(value: Value) -> Result<Self> {
368        match value {
369            Value::Integer(i) => {
370                i8::try_from(i).map_err(|_| Error::Client("Cannot parse result i8 u64".to_owned()))
371            }
372            Value::BulkString(None) | Value::Array(None) => Ok(0),
373            Value::BulkString(Some(s)) => {
374                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
375                    Ok(s) => match s.parse::<i8>() {
376                        Ok(u) => Ok(u),
377                        Err(e) => Err(Error::Client(e.to_string())),
378                    },
379                    Err(e) => Err(e),
380                }
381            }
382            Value::SimpleString(s) => match s.parse::<i8>() {
383                Ok(u) => Ok(u),
384                Err(e) => Err(Error::Client(e.to_string())),
385            },
386            Value::Error(e) => Err(Error::Redis(e)),
387            _ => Err(Error::Client(format!(
388                "Cannot parse result {:?} to i8",
389                value
390            ))),
391        }
392    }
393}
394
395impl FromValue for u8 {
396    fn from_value(value: Value) -> Result<Self> {
397        match value {
398            Value::Integer(i) => u8::try_from(i)
399                .map_err(|_| Error::Client("Cannot parse result tu8o u64".to_owned())),
400            Value::BulkString(None) | Value::Array(None) => Ok(0),
401            Value::BulkString(Some(s)) => {
402                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
403                    Ok(s) => match s.parse::<u8>() {
404                        Ok(u) => Ok(u),
405                        Err(e) => Err(Error::Client(e.to_string())),
406                    },
407                    Err(e) => Err(e),
408                }
409            }
410            Value::SimpleString(s) => match s.parse::<u8>() {
411                Ok(u) => Ok(u),
412                Err(e) => Err(Error::Client(e.to_string())),
413            },
414            Value::Error(e) => Err(Error::Redis(e)),
415            _ => Err(Error::Client(format!(
416                "Cannot parse result {:?} to u8",
417                value
418            ))),
419        }
420    }
421}
422
423impl FromValue for isize {
424    fn from_value(value: Value) -> Result<Self> {
425        match value {
426            Value::Integer(i) => isize::try_from(i)
427                .map_err(|_| Error::Client("Cannot parse result to isize".to_owned())),
428            Value::BulkString(None) | Value::Array(None) => Ok(0),
429            Value::BulkString(Some(s)) => {
430                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
431                    Ok(s) => match s.parse::<isize>() {
432                        Ok(u) => Ok(u),
433                        Err(e) => Err(Error::Client(e.to_string())),
434                    },
435                    Err(e) => Err(e),
436                }
437            }
438            Value::SimpleString(s) => match s.parse::<isize>() {
439                Ok(u) => Ok(u),
440                Err(e) => Err(Error::Client(e.to_string())),
441            },
442            Value::Error(e) => Err(Error::Redis(e)),
443            _ => Err(Error::Client(format!(
444                "Cannot parse result {:?} to isize",
445                value
446            ))),
447        }
448    }
449}
450
451impl FromValue for usize {
452    fn from_value(value: Value) -> Result<Self> {
453        match value {
454            Value::Integer(i) => usize::try_from(i)
455                .map_err(|_| Error::Client("Cannot parse result to usize".to_owned())),
456            Value::BulkString(None) | Value::Array(None) => Ok(0),
457            Value::BulkString(Some(s)) => {
458                match String::from_utf8(s).map_err(|e| Error::Client(e.to_string())) {
459                    Ok(s) => match s.parse::<usize>() {
460                        Ok(u) => Ok(u),
461                        Err(e) => Err(Error::Client(e.to_string())),
462                    },
463                    Err(e) => Err(e),
464                }
465            }
466            Value::SimpleString(s) => match s.parse::<usize>() {
467                Ok(u) => Ok(u),
468                Err(e) => Err(Error::Client(e.to_string())),
469            },
470            Value::Error(e) => Err(Error::Redis(e)),
471            _ => Err(Error::Client(format!(
472                "Cannot parse result {:?} to usize",
473                value
474            ))),
475        }
476    }
477}
478
479impl FromValue for f32 {
480    fn from_value(value: Value) -> Result<Self> {
481        match value {
482            Value::BulkString(Some(b)) => Ok(String::from_utf8_lossy(&b).parse::<f32>()?),
483            Value::BulkString(None) | Value::Array(None) => Ok(0f32),
484            Value::SimpleString(s) => Ok(s.parse::<f32>()?),
485            Value::Error(e) => Err(Error::Redis(e)),
486            _ => Err(Error::Client(format!(
487                "Cannot parse result {:?} to f32",
488                value
489            ))),
490        }
491    }
492}
493
494impl FromValue for f64 {
495    fn from_value(value: Value) -> Result<Self> {
496        match value {
497            Value::BulkString(Some(b)) => Ok(String::from_utf8_lossy(&b).parse::<f64>()?),
498            Value::BulkString(None) | Value::Array(None) => Ok(0f64),
499            Value::SimpleString(s) => Ok(s.parse::<f64>()?),
500            Value::Double(d) => Ok(d),
501            Value::Error(e) => Err(Error::Redis(e)),
502            _ => Err(Error::Client(format!(
503                "Cannot parse result {:?} to f64",
504                value
505            ))),
506        }
507    }
508}
509
510impl FromValue for String {
511    fn from_value(value: Value) -> Result<Self> {
512        match value {
513            Value::BulkString(Some(s)) => {
514                String::from_utf8(s).map_err(|e| Error::Client(e.to_string()))
515            }
516            Value::BulkString(None) => Ok(String::from("")),
517            Value::SimpleString(s) => Ok(s),
518            Value::Error(e) => Err(Error::Redis(e)),
519            _ => Err(Error::Client(format!(
520                "Cannot parse result {:?} to String",
521                value
522            ))),
523        }
524    }
525}
526
527impl FromValue for BulkString {
528    fn from_value(value: Value) -> Result<Self> {
529        match value {
530            Value::BulkString(Some(s)) => Ok(BulkString(s)),
531            Value::BulkString(None) => Ok(BulkString(Vec::new())),
532            Value::Error(e) => Err(Error::Redis(e)),
533            _ => Err(Error::Client(format!(
534                "Cannot parse result {:?} to Bytes",
535                value
536            ))),
537        }
538    }
539}
540
541/// Marker for single value array
542pub trait FromSingleValueArray<T>: FromValue
543where
544    T: FromValue,
545{
546}
547
548impl<T, const N: usize> FromSingleValueArray<T> for [T; N] where T: FromValue {}
549impl<T> FromSingleValueArray<T> for Vec<T> where T: FromValue {}
550impl<T, A> FromSingleValueArray<T> for SmallVec<A>
551where
552    A: smallvec::Array<Item = T>,
553    T: FromValue,
554{
555}
556impl<T, S: BuildHasher + Default> FromSingleValueArray<T> for HashSet<T, S> where
557    T: FromValue + Eq + Hash
558{
559}
560impl<T> FromSingleValueArray<T> for BTreeSet<T> where T: FromValue + Ord {}
561
562/// Marker for key/value array
563pub trait FromKeyValueValueArray<K, V>: FromValue
564where
565    K: FromValue,
566    V: FromValue,
567{
568}
569
570impl<K, V> FromKeyValueValueArray<K, V> for Vec<(K, V)>
571where
572    K: FromValue,
573    V: FromValue,
574{
575}
576
577impl<K, V, A> FromKeyValueValueArray<K, V> for SmallVec<A>
578where
579    A: smallvec::Array<Item = (K, V)>,
580    K: FromValue,
581    V: FromValue,
582{
583}
584
585impl<K, V, S: BuildHasher + Default> FromKeyValueValueArray<K, V> for HashMap<K, V, S>
586where
587    K: FromValue + Eq + Hash,
588    V: FromValue,
589{
590}
591
592impl<K, V> FromKeyValueValueArray<K, V> for BTreeMap<K, V>
593where
594    K: FromValue + Ord,
595    V: FromValue,
596{
597}
598
599pub(crate) trait HashMapExt<K, V, S> {
600    fn remove_with_result<Q: ?Sized>(&mut self, k: &Q) -> Result<V>
601    where
602        K: Borrow<Q> + Hash + Eq,
603        Q: Hash + Eq + Display,
604        S: BuildHasher;
605
606    fn remove_or_default<Q: ?Sized>(&mut self, k: &Q) -> V
607    where
608        K: Borrow<Q> + Hash + Eq,
609        Q: Hash + Eq + Display,
610        S: BuildHasher,
611        V: Default;
612}
613
614impl<K, V, S> HashMapExt<K, V, S> for HashMap<K, V, S> {
615    fn remove_with_result<Q: ?Sized>(&mut self, k: &Q) -> Result<V>
616    where
617        K: Borrow<Q> + Hash + Eq,
618        Q: Hash + Eq + Display,
619        S: BuildHasher,
620    {
621        self.remove(k)
622            .ok_or_else(|| Error::Client(format!("Cannot parse field '{}'", k)))
623    }
624
625    fn remove_or_default<Q: ?Sized>(&mut self, k: &Q) -> V
626    where
627        K: Borrow<Q> + Hash + Eq,
628        Q: Hash + Eq + Display,
629        S: BuildHasher,
630        V: Default,
631    {
632        self.remove(k).unwrap_or_default()
633    }
634}