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
122
123
124
use crate::ParamType;
use serde::{
de::{Error, MapAccess, Visitor},
Deserialize, Deserializer,
};
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub struct TupleParam {
pub name: Option<String>,
pub kind: ParamType,
}
impl<'a> Deserialize<'a> for TupleParam {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(TupleParamVisitor)
}
}
struct TupleParamVisitor;
impl<'a> Visitor<'a> for TupleParamVisitor {
type Value = TupleParam;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid tuple parameter spec")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'a>,
{
let mut name = None;
let mut kind = None;
let mut components = None;
while let Some(ref key) = map.next_key::<String>()? {
match key.as_ref() {
"name" => {
if name.is_some() {
return Err(Error::duplicate_field("name"));
}
name = Some(map.next_value()?);
}
"type" => {
if kind.is_some() {
return Err(Error::duplicate_field("type"));
}
kind = Some(map.next_value()?);
}
"components" => {
if components.is_some() {
return Err(Error::duplicate_field("components"));
}
let component: Vec<TupleParam> = map.next_value()?;
components = Some(component)
}
_ => {}
}
}
let kind = kind.ok_or_else(|| Error::missing_field("kind")).and_then(|param_type| {
if let ParamType::Tuple(_) = param_type {
let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
Ok(ParamType::Tuple(tuple_params.into_iter().map(|param| param.kind).collect()))
} else {
Ok(param_type)
}
})?;
Ok(TupleParam { name, kind })
}
}
#[cfg(test)]
mod tests {
use crate::{ParamType, TupleParam};
#[test]
fn tuple_param_deserialization() {
let s = r#"[{
"name": "foo",
"type": "address"
},{
"name": "bar",
"type": "address"
},{
"name": "baz",
"type": "address"
},{
"type": "bool"
}
]"#;
let deserialized: Vec<TupleParam> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
TupleParam { name: Some(String::from("foo")), kind: ParamType::Address },
TupleParam { name: Some(String::from("bar")), kind: ParamType::Address },
TupleParam { name: Some(String::from("baz")), kind: ParamType::Address },
TupleParam { name: None, kind: ParamType::Bool },
]
);
}
}