ethabi_fork_ethcontract/
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
11use crate::ParamType;
12use serde::{
13	de::{Error, MapAccess, Visitor},
14	Deserialize, Deserializer,
15};
16use std::fmt;
17
18/// Tuple params specification
19#[derive(Debug, Clone, PartialEq)]
20pub struct TupleParam {
21	/// Param name.
22	pub name: Option<String>,
23
24	/// Param type.
25	pub kind: ParamType,
26}
27
28impl<'a> Deserialize<'a> for TupleParam {
29	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30	where
31		D: Deserializer<'a>,
32	{
33		deserializer.deserialize_any(TupleParamVisitor)
34	}
35}
36
37struct TupleParamVisitor;
38
39impl<'a> Visitor<'a> for TupleParamVisitor {
40	type Value = TupleParam;
41
42	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
43		write!(formatter, "a valid tuple parameter spec")
44	}
45
46	fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
47	where
48		A: 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("type"));
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
79		let mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
80		crate::param::set_tuple_components(&mut kind, components)?;
81		Ok(TupleParam { name, kind })
82	}
83}
84
85#[cfg(test)]
86mod tests {
87	use crate::{ParamType, TupleParam};
88
89	#[test]
90	fn tuple_param_deserialization() {
91		let s = r#"[{
92			"name": "foo",
93			"type": "address"
94			},{
95			"name": "bar",
96			"type": "address"
97			},{
98			"name": "baz",
99			"type": "address"
100			},{
101			"type": "bool"
102			}
103		]"#;
104
105		let deserialized: Vec<TupleParam> = serde_json::from_str(s).unwrap();
106
107		assert_eq!(
108			deserialized,
109			vec![
110				TupleParam { name: Some(String::from("foo")), kind: ParamType::Address },
111				TupleParam { name: Some(String::from("bar")), kind: ParamType::Address },
112				TupleParam { name: Some(String::from("baz")), kind: ParamType::Address },
113				TupleParam { name: None, kind: ParamType::Bool },
114			]
115		);
116	}
117}