1use serde::{
12 de::{Error, MapAccess, Visitor},
13 Deserialize, Deserializer,
14};
15use std::fmt;
16
17use crate::{ParamType, TupleParam};
18
19#[derive(Debug, Clone, PartialEq)]
21pub struct Param {
22 pub name: String,
24 pub kind: ParamType,
26}
27
28impl<'a> Deserialize<'a> for Param {
29 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30 where
31 D: Deserializer<'a>,
32 {
33 deserializer.deserialize_any(ParamVisitor)
34 }
35}
36
37struct ParamVisitor;
38
39impl<'a> Visitor<'a> for ParamVisitor {
40 type Value = Param;
41
42 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
43 write!(formatter, "a valid event parameter spec")
44 }
45
46 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
47 where
48 V: 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("kind"));
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 let name = name.ok_or_else(|| Error::missing_field("name"))?;
79 let kind =
80 kind.ok_or_else(|| Error::missing_field("kind")).and_then(|param_type: ParamType| match param_type {
81 ParamType::Tuple(_) => {
82 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
83 Ok(ParamType::Tuple(tuple_params.into_iter().map(|param| param.kind).collect()))
84 }
85 ParamType::Array(inner_param_type) => match *inner_param_type {
86 ParamType::Tuple(_) => {
87 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
88 Ok(ParamType::Array(Box::new(ParamType::Tuple(
89 tuple_params.into_iter().map(|param| param.kind).collect(),
90 ))))
91 }
92 _ => Ok(ParamType::Array(inner_param_type)),
93 },
94 ParamType::FixedArray(inner_param_type, size) => match *inner_param_type {
95 ParamType::Tuple(_) => {
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 }
102 _ => Ok(ParamType::FixedArray(inner_param_type, size)),
103 },
104 _ => Ok(param_type),
105 })?;
106 Ok(Param { name, kind })
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use crate::{Param, ParamType};
113
114 #[test]
115 fn param_deserialization() {
116 let s = r#"{
117 "name": "foo",
118 "type": "address"
119 }"#;
120
121 let deserialized: Param = serde_json::from_str(s).unwrap();
122
123 assert_eq!(deserialized, Param { name: "foo".to_owned(), kind: ParamType::Address });
124 }
125
126 #[test]
127 fn param_tuple_deserialization() {
128 let s = r#"{
129 "name": "foo",
130 "type": "tuple",
131 "components": [
132 {
133 "name": "amount",
134 "type": "uint48"
135 },
136 {
137 "name": "things",
138 "type": "tuple",
139 "components": [
140 {
141 "name": "baseTupleParam",
142 "type": "address"
143 }
144 ]
145 }
146 ]
147 }"#;
148
149 let deserialized: Param = serde_json::from_str(s).unwrap();
150
151 assert_eq!(
152 deserialized,
153 Param {
154 name: "foo".to_owned(),
155 kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
156 }
157 );
158 }
159
160 #[test]
161 fn param_tuple_array_deserialization() {
162 let s = r#"{
163 "name": "foo",
164 "type": "tuple[]",
165 "components": [
166 {
167 "name": "amount",
168 "type": "uint48"
169 },
170 {
171 "name": "to",
172 "type": "address"
173 },
174 {
175 "name": "from",
176 "type": "address"
177 }
178 ]
179 }"#;
180
181 let deserialized: Param = serde_json::from_str(s).unwrap();
182
183 assert_eq!(
184 deserialized,
185 Param {
186 name: "foo".to_owned(),
187 kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
188 ParamType::Uint(48),
189 ParamType::Address,
190 ParamType::Address
191 ]))),
192 }
193 );
194 }
195
196 #[test]
197 fn param_tuple_fixed_array_deserialization() {
198 let s = r#"{
199 "name": "foo",
200 "type": "tuple[2]",
201 "components": [
202 {
203 "name": "amount",
204 "type": "uint48"
205 },
206 {
207 "name": "to",
208 "type": "address"
209 },
210 {
211 "name": "from",
212 "type": "address"
213 }
214 ]
215 }"#;
216
217 let deserialized: Param = serde_json::from_str(s).unwrap();
218
219 assert_eq!(
220 deserialized,
221 Param {
222 name: "foo".to_owned(),
223 kind: ParamType::FixedArray(
224 Box::new(ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Address, ParamType::Address])),
225 2
226 ),
227 }
228 );
229 }
230
231 #[test]
232 fn param_tuple_with_nested_tuple_arrays_deserialization() {
233 let s = r#"{
234 "name": "foo",
235 "type": "tuple",
236 "components": [
237 {
238 "name": "bar",
239 "type": "tuple[]",
240 "components": [
241 {
242 "name": "a",
243 "type": "address"
244 }
245 ]
246 },
247 {
248 "name": "baz",
249 "type": "tuple[42]",
250 "components": [
251 {
252 "name": "b",
253 "type": "address"
254 }
255 ]
256 }
257 ]
258 }"#;
259
260 let deserialized: Param = serde_json::from_str(s).unwrap();
261
262 assert_eq!(
263 deserialized,
264 Param {
265 name: "foo".to_owned(),
266 kind: ParamType::Tuple(vec![
267 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address]))),
268 ParamType::FixedArray(Box::new(ParamType::Tuple(vec![ParamType::Address])), 42,)
269 ]),
270 }
271 );
272 }
273}