ethabi_fork_ethcontract/
param.rs

1// Copyright 2015-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//! Function param.
10
11use serde::{
12	de::{Error, MapAccess, Visitor},
13	Deserialize, Deserializer,
14};
15use std::fmt;
16
17use crate::{ParamType, TupleParam};
18
19/// Function param.
20#[derive(Debug, Clone, PartialEq)]
21pub struct Param {
22	/// Param name.
23	pub name: String,
24	/// Param type.
25	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}