bencode_minimal/
try_from_value.rs1use super::{Dict, List, Value};
2
3pub 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}