ethabi_next/
tuple_param.rs1use crate::ParamType;
12use serde::{
13 de::{Error, MapAccess, Visitor},
14 Deserialize, Deserializer,
15};
16use std::fmt;
17
18#[derive(Debug, Clone, PartialEq)]
20pub struct TupleParam {
21 pub name: Option<String>,
23
24 pub kind: ParamType,
26}
27
28impl<'a> Deserialize<'a> for TupleParam {
29 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30 where
31 D: Deserializer<'a>,
32 {
33 deserializer.deserialize_any(TupleParamVisitor)
34 }
35}
36
37struct TupleParamVisitor;
38
39impl<'a> Visitor<'a> for TupleParamVisitor {
40 type Value = TupleParam;
41
42 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
43 write!(formatter, "a valid tuple parameter spec")
44 }
45
46 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
47 where
48 A: MapAccess<'a>,
49 {
50 let mut name = None;
51 let mut kind = None;
52 let mut components = None;
53
54 while let Some(ref key) = map.next_key::<String>()? {
55 match key.as_ref() {
56 "name" => {
57 if name.is_some() {
58 return Err(Error::duplicate_field("name"));
59 }
60 name = Some(map.next_value()?);
61 }
62 "type" => {
63 if kind.is_some() {
64 return Err(Error::duplicate_field("type"));
65 }
66 kind = Some(map.next_value()?);
67 }
68 "components" => {
69 if components.is_some() {
70 return Err(Error::duplicate_field("components"));
71 }
72 let component: Vec<TupleParam> = map.next_value()?;
73 components = Some(component)
74 }
75 _ => {}
76 }
77 }
78
79 let kind = kind.ok_or_else(|| Error::missing_field("kind")).and_then(|param_type| match param_type {
80 ParamType::Tuple(_) => {
81 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
82 Ok(ParamType::Tuple(tuple_params.into_iter().map(|param| param.kind).collect()))
83 }
84 ParamType::Array(ref inner) => {
85 if let ParamType::Tuple(_) = **inner {
86 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
87 Ok(ParamType::Array(Box::new(ParamType::Tuple(
88 tuple_params.into_iter().map(|param| param.kind).collect(),
89 ))))
90 } else {
91 Ok(param_type)
92 }
93 }
94 ParamType::FixedArray(ref inner, size) => {
95 if let ParamType::Tuple(_) = **inner {
96 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
97 Ok(ParamType::FixedArray(
98 Box::new(ParamType::Tuple(tuple_params.into_iter().map(|param| param.kind).collect())),
99 size,
100 ))
101 } else {
102 Ok(param_type)
103 }
104 }
105 _ => Ok(param_type),
106 })?;
107
108 Ok(TupleParam { name, kind })
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use crate::{ParamType, TupleParam};
115
116 #[test]
117 fn tuple_param_deserialization() {
118 let s = r#"[{
119 "name": "foo",
120 "type": "address"
121 },{
122 "name": "bar",
123 "type": "address"
124 },{
125 "name": "baz",
126 "type": "address"
127 },{
128 "type": "bool"
129 }
130 ]"#;
131
132 let deserialized: Vec<TupleParam> = serde_json::from_str(s).unwrap();
133
134 assert_eq!(
135 deserialized,
136 vec![
137 TupleParam { name: Some(String::from("foo")), kind: ParamType::Address },
138 TupleParam { name: Some(String::from("bar")), kind: ParamType::Address },
139 TupleParam { name: Some(String::from("baz")), kind: ParamType::Address },
140 TupleParam { name: None, kind: ParamType::Bool },
141 ]
142 );
143 }
144}