ethabi_next/
event_param.rs1use crate::{ParamType, TupleParam};
12use serde::{
13 de::{Error, MapAccess, Visitor},
14 Deserialize, Deserializer,
15};
16use std::fmt;
17
18#[derive(Debug, Clone, PartialEq)]
20pub struct EventParam {
21 pub name: String,
23 pub kind: ParamType,
25 pub indexed: bool,
27}
28
29impl<'a> Deserialize<'a> for EventParam {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where
32 D: Deserializer<'a>,
33 {
34 deserializer.deserialize_any(EventParamVisitor)
35 }
36}
37
38struct EventParamVisitor;
39
40impl<'a> Visitor<'a> for EventParamVisitor {
41 type Value = EventParam;
42
43 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
44 write!(formatter, "a valid event parameter spec")
45 }
46
47 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
48 where
49 V: MapAccess<'a>,
50 {
51 let mut name = None;
52 let mut kind = None;
53 let mut indexed = None;
54 let mut components = None;
55
56 while let Some(ref key) = map.next_key::<String>()? {
57 match key.as_ref() {
58 "name" => {
59 if name.is_some() {
60 return Err(Error::duplicate_field("name"));
61 }
62 name = Some(map.next_value()?);
63 }
64 "type" => {
65 if kind.is_some() {
66 return Err(Error::duplicate_field("kind"));
67 }
68 kind = Some(map.next_value()?);
69 }
70 "components" => {
71 if components.is_some() {
72 return Err(Error::duplicate_field("components"));
73 }
74 let component: Vec<TupleParam> = map.next_value()?;
75 components = Some(component)
76 }
77 "indexed" => {
78 if indexed.is_some() {
79 return Err(Error::duplicate_field("indexed"));
80 }
81 indexed = Some(map.next_value()?);
82 }
83 _ => {}
84 }
85 }
86 let name = name.ok_or_else(|| Error::missing_field("name"))?;
87 let kind =
88 kind.ok_or_else(|| Error::missing_field("kind")).and_then(|param_type: ParamType| match param_type {
89 ParamType::Tuple(_) => {
90 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
91 Ok(ParamType::Tuple(tuple_params.into_iter().map(|param| param.kind).collect()))
92 }
93 ParamType::Array(inner_param_type) => match *inner_param_type {
94 ParamType::Tuple(_) => {
95 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
96 Ok(ParamType::Array(Box::new(ParamType::Tuple(
97 tuple_params.into_iter().map(|param| param.kind).collect(),
98 ))))
99 }
100 _ => Ok(ParamType::Array(inner_param_type)),
101 },
102 ParamType::FixedArray(inner_param_type, size) => match *inner_param_type {
103 ParamType::Tuple(_) => {
104 let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
105 Ok(ParamType::FixedArray(
106 Box::new(ParamType::Tuple(tuple_params.into_iter().map(|param| param.kind).collect())),
107 size,
108 ))
109 }
110 _ => Ok(ParamType::FixedArray(inner_param_type, size)),
111 },
112 _ => Ok(param_type),
113 })?;
114 let indexed = indexed.unwrap_or(false);
115 Ok(EventParam { name, kind, indexed })
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use crate::{EventParam, ParamType};
122
123 #[test]
124 fn event_param_deserialization() {
125 let s = r#"{
126 "name": "foo",
127 "type": "address",
128 "indexed": true
129 }"#;
130
131 let deserialized: EventParam = serde_json::from_str(s).unwrap();
132
133 assert_eq!(deserialized, EventParam { name: "foo".to_owned(), kind: ParamType::Address, indexed: true });
134 }
135
136 #[test]
137 fn event_param_tuple_deserialization() {
138 let s = r#"{
139 "name": "foo",
140 "type": "tuple",
141 "indexed": true,
142 "components": [
143 {
144 "name": "amount",
145 "type": "uint48"
146 },
147 {
148 "name": "things",
149 "type": "tuple",
150 "components": [
151 {
152 "name": "baseTupleParam",
153 "type": "address"
154 }
155 ]
156 }
157 ]
158 }"#;
159
160 let deserialized: EventParam = serde_json::from_str(s).unwrap();
161
162 assert_eq!(
163 deserialized,
164 EventParam {
165 name: "foo".to_owned(),
166 kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
167 indexed: true,
168 }
169 );
170 }
171
172 #[test]
173 fn event_param_tuple_array_deserialization() {
174 let s = r#"{
175 "components": [
176 { "type": "uint256" },
177 { "type": "address" },
178 {
179 "components": [
180 { "type": "address" },
181 { "type": "address" }
182 ],
183 "type": "tuple"
184 },
185 { "type": "uint256" },
186 {
187 "components": [
188 {
189 "components": [
190 { "type": "address" },
191 { "type": "bytes" }
192 ],
193 "type": "tuple[]"
194 },
195 {
196 "components": [
197 { "type": "address" },
198 { "type": "uint256" }
199 ],
200 "type": "tuple[]"
201 },
202 { "type": "uint256" }
203 ],
204 "type": "tuple[]"
205 },
206 { "type": "uint256" }
207 ],
208 "indexed": false,
209 "name": "LogTaskSubmitted",
210 "type": "tuple"
211 }"#;
212
213 let deserialized: EventParam = serde_json::from_str(s).unwrap();
214
215 assert_eq!(
216 deserialized,
217 EventParam {
218 name: "LogTaskSubmitted".to_owned(),
219 kind: ParamType::Tuple(vec![
220 ParamType::Uint(256),
221 ParamType::Address,
222 ParamType::Tuple(vec![ParamType::Address, ParamType::Address]),
223 ParamType::Uint(256),
224 ParamType::Array(Box::new(ParamType::Tuple(vec![
225 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address, ParamType::Bytes,]))),
226 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address, ParamType::Uint(256)]))),
227 ParamType::Uint(256),
228 ]))),
229 ParamType::Uint(256),
230 ]),
231 indexed: false,
232 }
233 );
234 }
235}