1#[cfg(not(feature = "std"))]
12use crate::no_std_prelude::*;
13use crate::{param_type::Writer, ParamType};
14use core::fmt;
15use serde::{
16 de::{Error, MapAccess, Visitor},
17 ser::SerializeMap,
18 Deserialize, Deserializer, Serialize, Serializer,
19};
20
21#[derive(Debug, Clone, PartialEq)]
23pub struct TupleParam {
24 pub name: Option<String>,
26
27 pub kind: ParamType,
29
30 pub internal_type: Option<String>,
32}
33
34impl<'a> Deserialize<'a> for TupleParam {
35 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36 where
37 D: Deserializer<'a>,
38 {
39 deserializer.deserialize_any(TupleParamVisitor)
40 }
41}
42
43struct TupleParamVisitor;
44
45impl<'a> Visitor<'a> for TupleParamVisitor {
46 type Value = TupleParam;
47
48 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
49 write!(formatter, "a valid tuple parameter spec")
50 }
51
52 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
53 where
54 A: MapAccess<'a>,
55 {
56 let mut name = None;
57 let mut kind = None;
58 let mut components = None;
59 let mut internal_type = None;
60
61 while let Some(ref key) = map.next_key::<String>()? {
62 match key.as_ref() {
63 "name" => {
64 if name.is_some() {
65 return Err(Error::duplicate_field("name"));
66 }
67 name = Some(map.next_value()?);
68 }
69 "type" => {
70 if kind.is_some() {
71 return Err(Error::duplicate_field("type"));
72 }
73 kind = Some(map.next_value()?);
74 }
75 "internalType" => {
76 if internal_type.is_some() {
77 return Err(Error::duplicate_field("internalType"));
78 }
79 internal_type = Some(map.next_value()?);
80 }
81 "components" => {
82 if components.is_some() {
83 return Err(Error::duplicate_field("components"));
84 }
85 let component: Vec<TupleParam> = map.next_value()?;
86 components = Some(component)
87 }
88 _ => {}
89 }
90 }
91
92 let mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
93 crate::param::set_tuple_components(&mut kind, components)?;
94 Ok(TupleParam { name, kind, internal_type })
95 }
96}
97
98impl Serialize for TupleParam {
99 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
100 where
101 S: Serializer,
102 {
103 let mut map = serializer.serialize_map(None)?;
104 if let Some(ref internal_type) = self.internal_type {
105 map.serialize_entry("internalType", internal_type)?;
106 }
107 if let Some(name) = &self.name {
108 map.serialize_entry("name", name)?;
109 }
110 map.serialize_entry("type", &Writer::write_for_abi(&self.kind, false))?;
111 if let Some(inner_tuple) = crate::param::inner_tuple(&self.kind) {
112 map.serialize_key("components")?;
113 map.serialize_value(&crate::param::SerializeableParamVec(inner_tuple))?;
114 }
115 map.end()
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 #[cfg(not(feature = "std"))]
122 use crate::no_std_prelude::*;
123 use crate::{
124 tests::{assert_json_eq, assert_ser_de},
125 ParamType, TupleParam,
126 };
127
128 #[test]
129 fn param_simple() {
130 let s = r#"{
131 "name": "foo",
132 "type": "address"
133 }"#;
134
135 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
136
137 assert_eq!(
138 deserialized,
139 TupleParam { name: Some("foo".to_owned()), kind: ParamType::Address, internal_type: None }
140 );
141
142 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
143 }
144
145 #[test]
146 fn param_internal_type() {
147 let s = r#"{
148 "internalType": "struct Verifier.Proof",
149 "name": "foo",
150 "type": "address"
151 }"#;
152
153 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
154
155 assert_eq!(
156 deserialized,
157 TupleParam {
158 name: Some("foo".to_owned()),
159 kind: ParamType::Address,
160 internal_type: Some("struct Verifier.Proof".to_string())
161 }
162 );
163
164 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
165 }
166
167 #[test]
168 fn param_unnamed() {
169 let s = r#"{
170 "type": "address"
171 }"#;
172
173 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
174
175 assert_eq!(deserialized, TupleParam { name: None, kind: ParamType::Address, internal_type: None });
176
177 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
178 }
179
180 #[test]
181 fn param_tuple() {
182 let s = r#"{
183 "type": "tuple",
184 "components": [
185 {
186 "type": "uint48"
187 },
188 {
189 "type": "tuple",
190 "components": [
191 {
192 "type": "address"
193 }
194 ]
195 }
196 ]
197 }"#;
198
199 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
200
201 assert_eq!(
202 deserialized,
203 TupleParam {
204 name: None,
205 kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
206 internal_type: None
207 }
208 );
209
210 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
211 }
212
213 #[test]
214 fn param_tuple_named() {
215 let s = r#"{
216 "type": "tuple",
217 "components": [
218 {
219 "name": "amount",
220 "type": "uint48"
221 },
222 {
223 "name": "things",
224 "type": "tuple",
225 "components": [
226 {
227 "name": "baseTupleParam",
228 "type": "address"
229 }
230 ]
231 }
232 ]
233 }"#;
234
235 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
236
237 assert_eq!(
238 deserialized,
239 TupleParam {
240 name: None,
241 kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
242 internal_type: None
243 }
244 );
245
246 assert_ser_de(&deserialized);
247 }
248
249 #[test]
250 fn param_tuple_array() {
251 let s = r#"{
252 "type": "tuple[]",
253 "components": [
254 {
255 "type": "uint48"
256 },
257 {
258 "type": "address"
259 },
260 {
261 "type": "address"
262 }
263 ]
264 }"#;
265
266 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
267
268 assert_eq!(
269 deserialized,
270 TupleParam {
271 name: None,
272 kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
273 ParamType::Uint(48),
274 ParamType::Address,
275 ParamType::Address
276 ]))),
277 internal_type: None
278 }
279 );
280
281 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
282 }
283
284 #[test]
285 fn param_array_of_array_of_tuple() {
286 let s = r#"{
287 "type": "tuple[][]",
288 "components": [
289 {
290 "type": "uint8"
291 },
292 {
293 "type": "uint16"
294 }
295 ]
296 }"#;
297
298 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
299 assert_eq!(
300 deserialized,
301 TupleParam {
302 name: None,
303 kind: ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Tuple(vec![
304 ParamType::Uint(8),
305 ParamType::Uint(16),
306 ]))))),
307 internal_type: None
308 }
309 );
310
311 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
312 }
313
314 #[test]
315 fn param_tuple_fixed_array() {
316 let s = r#"{
317 "type": "tuple[2]",
318 "components": [
319 {
320 "type": "uint48"
321 },
322 {
323 "type": "address"
324 },
325 {
326 "type": "address"
327 }
328 ]
329 }"#;
330
331 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
332
333 assert_eq!(
334 deserialized,
335 TupleParam {
336 name: None,
337 kind: ParamType::FixedArray(
338 Box::new(ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Address, ParamType::Address])),
339 2
340 ),
341 internal_type: None
342 }
343 );
344
345 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
346 }
347
348 #[test]
349 fn param_tuple_with_nested_tuple_arrays() {
350 let s = r#"{
351 "type": "tuple",
352 "components": [
353 {
354 "type": "tuple[]",
355 "components": [
356 {
357 "type": "address"
358 }
359 ]
360 },
361 {
362 "type": "tuple[42]",
363 "components": [
364 {
365 "type": "address"
366 }
367 ]
368 }
369 ]
370 }"#;
371
372 let deserialized: TupleParam = serde_json::from_str(s).unwrap();
373
374 assert_eq!(
375 deserialized,
376 TupleParam {
377 name: None,
378 kind: ParamType::Tuple(vec![
379 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address]))),
380 ParamType::FixedArray(Box::new(ParamType::Tuple(vec![ParamType::Address])), 42,)
381 ]),
382 internal_type: None
383 }
384 );
385
386 assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
387 }
388}