ethabi/
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
11#[cfg(feature = "serde")]
12use core::fmt;
13
14#[cfg(feature = "serde")]
15use serde::{
16	de::{Error, MapAccess, Visitor},
17	ser::{SerializeMap, SerializeSeq},
18	Deserialize, Deserializer, Serialize, Serializer,
19};
20
21#[cfg(not(feature = "std"))]
22use crate::no_std_prelude::*;
23use crate::ParamType;
24#[cfg(feature = "serde")]
25use crate::{param_type::Writer, TupleParam};
26
27/// Function param.
28#[derive(Debug, Clone, PartialEq)]
29pub struct Param {
30	/// Param name.
31	pub name: String,
32	/// Param type.
33	pub kind: ParamType,
34	/// Additional Internal type.
35	pub internal_type: Option<String>,
36}
37
38#[cfg(feature = "serde")]
39impl<'a> Deserialize<'a> for Param {
40	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
41	where
42		D: Deserializer<'a>,
43	{
44		deserializer.deserialize_any(ParamVisitor)
45	}
46}
47
48#[cfg(feature = "serde")]
49struct ParamVisitor;
50
51#[cfg(feature = "serde")]
52impl<'a> Visitor<'a> for ParamVisitor {
53	type Value = Param;
54
55	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
56		write!(formatter, "a valid event parameter spec")
57	}
58
59	fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
60	where
61		V: MapAccess<'a>,
62	{
63		let mut name = None;
64		let mut kind = None;
65		let mut components = None;
66		let mut internal_type = None;
67
68		while let Some(ref key) = map.next_key::<String>()? {
69			match key.as_ref() {
70				"name" => {
71					if name.is_some() {
72						return Err(Error::duplicate_field("name"));
73					}
74					name = Some(map.next_value()?);
75				}
76				"type" => {
77					if kind.is_some() {
78						return Err(Error::duplicate_field("kind"));
79					}
80					kind = Some(map.next_value()?);
81				}
82				"internalType" => {
83					if internal_type.is_some() {
84						return Err(Error::duplicate_field("internalType"));
85					}
86					internal_type = Some(map.next_value()?);
87				}
88				"components" => {
89					if components.is_some() {
90						return Err(Error::duplicate_field("components"));
91					}
92					let component: Vec<TupleParam> = map.next_value()?;
93					components = Some(component)
94				}
95				_ => {}
96			}
97		}
98		let name = name.ok_or_else(|| Error::missing_field("name"))?;
99		let mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
100		set_tuple_components::<V::Error>(&mut kind, components)?;
101		Ok(Param { name, kind, internal_type })
102	}
103}
104
105#[cfg(feature = "serde")]
106impl Serialize for Param {
107	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108	where
109		S: Serializer,
110	{
111		let mut map = serializer.serialize_map(None)?;
112		if let Some(ref internal_type) = self.internal_type {
113			map.serialize_entry("internalType", internal_type)?;
114		}
115		map.serialize_entry("name", &self.name)?;
116		map.serialize_entry("type", &Writer::write_for_abi(&self.kind, false))?;
117		if let Some(inner_tuple) = inner_tuple(&self.kind) {
118			map.serialize_key("components")?;
119			map.serialize_value(&SerializeableParamVec(inner_tuple))?;
120		}
121		map.end()
122	}
123}
124
125#[cfg(feature = "serde")]
126pub(crate) fn inner_tuple_mut(mut param: &mut ParamType) -> Option<&mut Vec<ParamType>> {
127	loop {
128		match param {
129			ParamType::Array(inner) => param = inner.as_mut(),
130			ParamType::FixedArray(inner, _) => param = inner.as_mut(),
131			ParamType::Tuple(inner) => return Some(inner),
132			_ => return None,
133		}
134	}
135}
136
137#[cfg(feature = "serde")]
138pub(crate) fn inner_tuple(mut param: &ParamType) -> Option<&Vec<ParamType>> {
139	loop {
140		match param {
141			ParamType::Array(inner) => param = inner.as_ref(),
142			ParamType::FixedArray(inner, _) => param = inner.as_ref(),
143			ParamType::Tuple(inner) => return Some(inner),
144			_ => return None,
145		}
146	}
147}
148
149#[cfg(feature = "serde")]
150pub(crate) fn set_tuple_components<Error: serde::de::Error>(
151	kind: &mut ParamType,
152	components: Option<Vec<TupleParam>>,
153) -> Result<(), Error> {
154	if let Some(inner_tuple_mut) = inner_tuple_mut(kind) {
155		let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
156		inner_tuple_mut.extend(tuple_params.into_iter().map(|param| param.kind))
157	}
158	Ok(())
159}
160
161#[cfg(feature = "serde")]
162pub(crate) struct SerializeableParamVec<'a>(pub(crate) &'a [ParamType]);
163
164#[cfg(feature = "serde")]
165impl Serialize for SerializeableParamVec<'_> {
166	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
167	where
168		S: Serializer,
169	{
170		let mut seq = serializer.serialize_seq(None)?;
171		for param in self.0 {
172			seq.serialize_element(&SerializeableParam(param))?;
173		}
174		seq.end()
175	}
176}
177
178#[cfg(feature = "serde")]
179pub(crate) struct SerializeableParam<'a>(pub(crate) &'a ParamType);
180
181#[cfg(feature = "serde")]
182impl Serialize for SerializeableParam<'_> {
183	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184	where
185		S: Serializer,
186	{
187		let mut map = serializer.serialize_map(None)?;
188		map.serialize_entry("type", &Writer::write_for_abi(self.0, false))?;
189		if let Some(inner_tuple) = inner_tuple(self.0) {
190			map.serialize_key("components")?;
191			map.serialize_value(&SerializeableParamVec(inner_tuple))?;
192		}
193		map.end()
194	}
195}
196
197#[cfg(all(test, feature = "serde"))]
198mod tests {
199	#[cfg(not(feature = "std"))]
200	use crate::no_std_prelude::*;
201	use crate::{
202		tests::{assert_json_eq, assert_ser_de},
203		Param, ParamType,
204	};
205
206	#[test]
207	fn param_simple() {
208		let s = r#"{
209			"name": "foo",
210			"type": "address"
211		}"#;
212
213		let deserialized: Param = serde_json::from_str(s).unwrap();
214
215		assert_eq!(deserialized, Param { name: "foo".to_owned(), kind: ParamType::Address, internal_type: None });
216
217		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
218	}
219
220	#[test]
221	fn param_simple_internal_type() {
222		let s = r#"{
223			"name": "foo",
224			"type": "address",
225			"internalType": "struct Verifier.Proof"
226		}"#;
227
228		let deserialized: Param = serde_json::from_str(s).unwrap();
229
230		assert_eq!(
231			deserialized,
232			Param {
233				name: "foo".to_owned(),
234				kind: ParamType::Address,
235				internal_type: Some("struct Verifier.Proof".to_string())
236			}
237		);
238
239		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
240	}
241
242	#[test]
243	fn param_tuple() {
244		let s = r#"{
245			"name": "foo",
246			"type": "tuple",
247			"components": [
248				{
249					"type": "uint48"
250				},
251				{
252					"type": "tuple",
253					"components": [
254						{
255							"type": "address"
256						}
257					]
258				}
259			]
260		}"#;
261
262		let deserialized: Param = serde_json::from_str(s).unwrap();
263
264		assert_eq!(
265			deserialized,
266			Param {
267				name: "foo".to_owned(),
268				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
269				internal_type: None
270			}
271		);
272
273		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
274	}
275
276	#[test]
277	fn param_tuple_internal_type() {
278		let s = r#"{
279			"name": "foo",
280			"type": "tuple",
281			"internalType": "struct Pairing.G1Point[]",
282			"components": [
283				{
284					"type": "uint48"
285				},
286				{
287					"type": "tuple",
288					"components": [
289						{
290							"type": "address"
291						}
292					]
293				}
294			]
295		}"#;
296
297		let deserialized: Param = serde_json::from_str(s).unwrap();
298
299		assert_eq!(
300			deserialized,
301			Param {
302				name: "foo".to_owned(),
303				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
304				internal_type: Some("struct Pairing.G1Point[]".to_string())
305			}
306		);
307
308		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
309	}
310
311	#[test]
312	fn param_tuple_named() {
313		let s = r#"{
314			"name": "foo",
315			"type": "tuple",
316			"components": [
317				{
318					"name": "amount",
319					"type": "uint48"
320				},
321				{
322					"name": "things",
323					"type": "tuple",
324					"components": [
325						{
326							"name": "baseTupleParam",
327							"type": "address"
328						}
329					]
330				}
331			]
332		}"#;
333
334		let deserialized: Param = serde_json::from_str(s).unwrap();
335
336		assert_eq!(
337			deserialized,
338			Param {
339				name: "foo".to_owned(),
340				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
341				internal_type: None
342			}
343		);
344
345		assert_ser_de(&deserialized);
346	}
347
348	#[test]
349	fn param_tuple_array() {
350		let s = r#"{
351			"name": "foo",
352			"type": "tuple[]",
353			"components": [
354				{
355					"type": "uint48"
356				},
357				{
358					"type": "address"
359				},
360				{
361					"type": "address"
362				}
363			]
364		}"#;
365
366		let deserialized: Param = serde_json::from_str(s).unwrap();
367
368		assert_eq!(
369			deserialized,
370			Param {
371				name: "foo".to_owned(),
372				kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
373					ParamType::Uint(48),
374					ParamType::Address,
375					ParamType::Address
376				]))),
377				internal_type: None
378			}
379		);
380
381		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
382	}
383
384	#[test]
385	fn param_array_of_array_of_tuple() {
386		let s = r#"{
387			"name": "foo",
388			"type": "tuple[][]",
389			"components": [
390				{
391					"type": "uint8"
392				},
393				{
394					"type": "uint16"
395				}
396			]
397		}"#;
398
399		let deserialized: Param = serde_json::from_str(s).unwrap();
400		assert_eq!(
401			deserialized,
402			Param {
403				name: "foo".to_owned(),
404				kind: ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Tuple(vec![
405					ParamType::Uint(8),
406					ParamType::Uint(16),
407				]))))),
408				internal_type: None
409			}
410		);
411
412		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
413	}
414
415	#[test]
416	fn param_tuple_fixed_array() {
417		let s = r#"{
418			"name": "foo",
419			"type": "tuple[2]",
420			"components": [
421				{
422					"type": "uint48"
423				},
424				{
425					"type": "address"
426				},
427				{
428					"type": "address"
429				}
430			]
431		}"#;
432
433		let deserialized: Param = serde_json::from_str(s).unwrap();
434
435		assert_eq!(
436			deserialized,
437			Param {
438				name: "foo".to_owned(),
439				kind: ParamType::FixedArray(
440					Box::new(ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Address, ParamType::Address])),
441					2
442				),
443				internal_type: None
444			}
445		);
446
447		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
448	}
449
450	#[test]
451	fn param_tuple_with_nested_tuple_arrays() {
452		let s = r#"{
453			"name": "foo",
454			"type": "tuple",
455			"components": [
456				{
457					"type": "tuple[]",
458					"components": [
459						{
460							"type": "address"
461						}
462					]
463				},
464				{
465					"type": "tuple[42]",
466					"components": [
467						{
468							"type": "address"
469						}
470					]
471				}
472			]
473		}"#;
474
475		let deserialized: Param = serde_json::from_str(s).unwrap();
476
477		assert_eq!(
478			deserialized,
479			Param {
480				name: "foo".to_owned(),
481				kind: ParamType::Tuple(vec![
482					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address]))),
483					ParamType::FixedArray(Box::new(ParamType::Tuple(vec![ParamType::Address])), 42,)
484				]),
485				internal_type: None
486			}
487		);
488
489		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
490	}
491}