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 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
541pub 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
562pub 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}