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