1use rmpv::Value;
18
19pub trait TryUnpack<V> {
24 fn try_unpack(self) -> Result<V, Value>;
30}
31
32impl TryUnpack<Value> for Value {
35 fn try_unpack(self) -> Result<Value, Value> {
36 Ok(self)
37 }
38}
39
40impl TryUnpack<()> for Value {
41 fn try_unpack(self) -> Result<(), Value> {
42 if self.is_nil() {
43 Ok(())
44 } else {
45 Err(self)
46 }
47 }
48}
49
50impl TryUnpack<String> for Value {
52 fn try_unpack(self) -> Result<String, Value> {
53 match self {
54 Value::String(s) if s.is_str() => {
55 Ok(s.into_str().expect("This was valid UTF8"))
56 }
57 val => Err(val),
58 }
59 }
60}
61
62impl TryUnpack<(i64, i64)> for Value {
63 fn try_unpack(self) -> Result<(i64, i64), Value> {
64 if let Value::Array(ref v) = self {
65 if v.len() == 2 {
66 let mut vi = v.iter().map(Value::as_i64);
67 if let (Some(Some(i)), Some(Some(j))) = (vi.next(), vi.next()) {
68 return Ok((i, j));
69 }
70 }
71 }
72 Err(self)
73 }
74}
75
76impl<T> TryUnpack<Vec<T>> for Value
80where
81 Value: TryUnpack<T> + From<T>,
82{
83 fn try_unpack(self) -> Result<Vec<T>, Value> {
84 match self {
85 Value::Array(v) => {
86 let mut newvec = vec![];
87 let mut vi = v.into_iter();
88
89 while let Some(ele) = vi.next() {
90 match ele.try_unpack() {
91 Ok(t) => newvec.push(t),
92 Err(ele) => {
93 let mut restorevec: Vec<Value> =
94 newvec.into_iter().map(Value::from).collect();
95 restorevec.push(ele);
96 restorevec.extend(vi);
97 return Err(Value::Array(restorevec));
98 }
99 }
100 }
101 Ok(newvec)
102 }
103 val => Err(val),
104 }
105 }
106}
107
108macro_rules! impl_try_unpack_tryfrom {
109 ($t: ty) => {
110 impl TryUnpack<$t> for Value {
111 fn try_unpack(self) -> Result<$t, Value> {
112 use std::convert::TryInto;
113 self.try_into()
114 }
115 }
116 };
117}
118
119impl_try_unpack_tryfrom!(i64);
120impl_try_unpack_tryfrom!(bool);
121impl_try_unpack_tryfrom!(Vec<(Value, Value)>);