Skip to main content

bencode_minimal/
try_from_value.rs

1use super::{Dict, List, Value};
2
3/// Conversion from [Value]
4pub trait TryFromValue<'a>: Sized {
5    fn try_from(value: &'a Value) -> Option<Self>;
6}
7
8macro_rules! from {
9    ($t:ident, $value:ident as $item:ident => $expr:expr) => {{
10        if let Value::$t($item) = $value {
11            $expr
12        } else {
13            None
14        }
15    }};
16}
17
18impl<'a> TryFromValue<'a> for i64 {
19    fn try_from(value: &'a Value<'a>) -> Option<Self> {
20        from!(Int, value as v => Some(*v))
21    }
22}
23
24impl<'a> TryFromValue<'a> for &'a [u8] {
25    fn try_from(value: &'a Value) -> Option<Self> {
26        from!(Str, value as v => Some(v.as_ref()))
27    }
28}
29
30impl<'a, const N: usize> TryFromValue<'a> for [u8; N] {
31    fn try_from(value: &'a Value) -> Option<Self> {
32        from!(Str, value as v => TryFrom::try_from(v.as_ref()).ok())
33    }
34}
35
36impl<'a, A: TryFromValue<'a>, B: TryFromValue<'a>> TryFromValue<'a> for (A, B) {
37    fn try_from(value: &'a Value) -> Option<Self> {
38        from!(List, value as v => {
39            let a = v.get(0).map(A::try_from)?;
40            let b = v.get(1).map(B::try_from)?;
41            a.zip(b)
42        })
43    }
44}
45
46impl<'a> TryFromValue<'a> for &'a str {
47    fn try_from(value: &'a Value) -> Option<Self> {
48        from!(Str, value as v => std::str::from_utf8(v).ok())
49    }
50}
51
52impl<'a> TryFromValue<'a> for &'a List<'a> {
53    fn try_from(value: &'a Value) -> Option<Self> {
54        from!(List, value as v => Some(v))
55    }
56}
57
58impl<'a> TryFromValue<'a> for &'a Dict<'a> {
59    fn try_from(value: &'a Value) -> Option<Self> {
60        from!(Dict, value as v => Some(v))
61    }
62}
63
64impl<'a> TryFromValue<'a> for &'a Value<'a> {
65    fn try_from(value: &'a Value) -> Option<Self> {
66        Some(value)
67    }
68}