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 mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
80 set_tuple_components::<V::Error>(&mut kind, components)?;
81 Ok(Param { name, kind })
82 }
83}
84
85fn inner_tuple(mut param: &mut ParamType) -> Option<&mut Vec<ParamType>> {
86 loop {
87 match param {
88 ParamType::Array(inner) => param = inner.as_mut(),
89 ParamType::FixedArray(inner, _) => param = inner.as_mut(),
90 ParamType::Tuple(inner) => return Some(inner),
91 _ => return None,
92 }
93 }
94}
95
96pub fn set_tuple_components<Error: serde::de::Error>(
97 kind: &mut ParamType,
98 components: Option<Vec<TupleParam>>,
99) -> Result<(), Error> {
100 if let Some(inner_tuple) = inner_tuple(kind) {
101 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
102 inner_tuple.extend(tuple_params.into_iter().map(|param| param.kind))
103 }
104 Ok(())
105}
106
107#[cfg(test)]
108mod tests {
109 use crate::{Param, ParamType};
110
111 #[test]
112 fn param_deserialization() {
113 let s = r#"{
114 "name": "foo",
115 "type": "address"
116 }"#;
117
118 let deserialized: Param = serde_json::from_str(s).unwrap();
119
120 assert_eq!(deserialized, Param { name: "foo".to_owned(), kind: ParamType::Address });
121 }
122
123 #[test]
124 fn param_tuple_deserialization() {
125 let s = r#"{
126 "name": "foo",
127 "type": "tuple",
128 "components": [
129 {
130 "name": "amount",
131 "type": "uint48"
132 },
133 {
134 "name": "things",
135 "type": "tuple",
136 "components": [
137 {
138 "name": "baseTupleParam",
139 "type": "address"
140 }
141 ]
142 }
143 ]
144 }"#;
145
146 let deserialized: Param = serde_json::from_str(s).unwrap();
147
148 assert_eq!(
149 deserialized,
150 Param {
151 name: "foo".to_owned(),
152 kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
153 }
154 );
155 }
156
157 #[test]
158 fn param_tuple_array_deserialization() {
159 let s = r#"{
160 "name": "foo",
161 "type": "tuple[]",
162 "components": [
163 {
164 "name": "amount",
165 "type": "uint48"
166 },
167 {
168 "name": "to",
169 "type": "address"
170 },
171 {
172 "name": "from",
173 "type": "address"
174 }
175 ]
176 }"#;
177
178 let deserialized: Param = serde_json::from_str(s).unwrap();
179
180 assert_eq!(
181 deserialized,
182 Param {
183 name: "foo".to_owned(),
184 kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
185 ParamType::Uint(48),
186 ParamType::Address,
187 ParamType::Address
188 ]))),
189 }
190 );
191 }
192
193 #[test]
194 fn param_array_of_array_of_tuple_deserialization() {
195 let s = r#"{
196 "name": "foo",
197 "type": "tuple[][]",
198 "components": [
199 {
200 "name": "u0",
201 "type": "uint8"
202 },
203 {
204 "name": "u1",
205 "type": "uint16"
206 }
207 ]
208 }"#;
209
210 let deserialized: Param = serde_json::from_str(s).unwrap();
211 assert_eq!(
212 deserialized,
213 Param {
214 name: "foo".to_owned(),
215 kind: ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Tuple(vec![
216 ParamType::Uint(8),
217 ParamType::Uint(16),
218 ]))))),
219 }
220 );
221 }
222
223 #[test]
224 fn param_tuple_fixed_array_deserialization() {
225 let s = r#"{
226 "name": "foo",
227 "type": "tuple[2]",
228 "components": [
229 {
230 "name": "amount",
231 "type": "uint48"
232 },
233 {
234 "name": "to",
235 "type": "address"
236 },
237 {
238 "name": "from",
239 "type": "address"
240 }
241 ]
242 }"#;
243
244 let deserialized: Param = serde_json::from_str(s).unwrap();
245
246 assert_eq!(
247 deserialized,
248 Param {
249 name: "foo".to_owned(),
250 kind: ParamType::FixedArray(
251 Box::new(ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Address, ParamType::Address])),
252 2
253 ),
254 }
255 );
256 }
257
258 #[test]
259 fn param_tuple_with_nested_tuple_arrays_deserialization() {
260 let s = r#"{
261 "name": "foo",
262 "type": "tuple",
263 "components": [
264 {
265 "name": "bar",
266 "type": "tuple[]",
267 "components": [
268 {
269 "name": "a",
270 "type": "address"
271 }
272 ]
273 },
274 {
275 "name": "baz",
276 "type": "tuple[42]",
277 "components": [
278 {
279 "name": "b",
280 "type": "address"
281 }
282 ]
283 }
284 ]
285 }"#;
286
287 let deserialized: Param = serde_json::from_str(s).unwrap();
288
289 assert_eq!(
290 deserialized,
291 Param {
292 name: "foo".to_owned(),
293 kind: ParamType::Tuple(vec![
294 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address]))),
295 ParamType::FixedArray(Box::new(ParamType::Tuple(vec![ParamType::Address])), 42,)
296 ]),
297 }
298 );
299 }
300}