ethabi/
tuple_param.rs

1// Copyright 2020 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Tuple param type.
10
11#[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/// Tuple params specification
22#[derive(Debug, Clone, PartialEq)]
23pub struct TupleParam {
24	/// Param name.
25	pub name: Option<String>,
26
27	/// Param type.
28	pub kind: ParamType,
29
30	/// Additional Internal type.
31	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}