ethers_abi/param_type/
reader.rs1#[cfg(not(feature = "std"))]
10use crate::no_std_prelude::*;
11use crate::{Error, ParamType};
12
13pub struct Reader;
15
16impl Reader {
17 pub fn read(name: &str) -> Result<ParamType, Error> {
19 match name.chars().last() {
20 Some(')') => {
22 if !name.starts_with('(') {
23 return Err(Error::InvalidName(name.to_owned()));
24 };
25
26 let mut subtypes = Vec::new();
27 let mut subtuples = Vec::new();
28 let mut nested = 0isize;
29 let mut top_level_paren_open = 0usize;
30 let mut last_item = 1;
31 let mut chars = name.chars().enumerate();
32
33 while let Some((mut pos, c)) = chars.next() {
35 match c {
36 '(' => {
37 top_level_paren_open = pos;
38 nested += 1;
39 if nested > 1 {
42 subtuples.push(vec![]);
43 last_item = pos + 1;
44 }
45 }
46 ')' => {
47 nested -= 1;
48
49 if nested < 0 {
51 return Err(Error::InvalidName(name.to_owned()));
52 }
53 else if name[last_item..pos].is_empty() {
56 last_item = pos + 1;
57 }
58 else if nested == 0 {
60 let sub = &name[last_item..pos];
62 let subtype = Reader::read(sub)?;
63 subtypes.push(subtype);
64 last_item = pos + 1;
65 }
66 else if nested > 0 {
68 loop {
70 match chars.clone().next() {
71 Some((_, ',')) | Some((_, ')')) | None => break,
72 _ => {
73 chars.next();
75 pos += 1;
76 }
77 }
78 }
79
80 let inner_tuple = &name[top_level_paren_open..=pos];
82 let subtype = Reader::read(inner_tuple)?;
83
84 if nested > 1 {
85 let mut subtuple = core::mem::take(&mut subtuples[(nested - 2) as usize]);
86 subtuple.push(subtype);
87 subtypes.push(ParamType::Tuple(subtuple));
88 } else {
89 subtypes.push(subtype);
90 }
91 last_item = pos + 1;
92 }
93 }
94 ',' => {
95 if name[last_item..pos].is_empty() {
98 last_item = pos + 1
99 }
100 else if nested == 1 {
102 let sub = &name[last_item..pos];
103 let subtype = Reader::read(sub)?;
104 subtypes.push(subtype);
105 last_item = pos + 1;
106 }
107 else if nested > 1 {
110 let sub = &name[last_item..pos];
111 let subtype = Reader::read(sub)?;
112 subtuples[(nested - 2) as usize].push(subtype);
113 last_item = pos + 1;
114 }
115 }
116 _ => (),
117 }
118 }
119 return Ok(ParamType::Tuple(subtypes));
120 }
121 Some(']') => {
123 let num: String =
125 name.chars().rev().skip(1).take_while(|c| *c != '[').collect::<String>().chars().rev().collect();
126
127 let count = name.chars().count();
128 return if num.is_empty() {
129 let subtype = Reader::read(&name[..count - 2])?;
131 Ok(ParamType::Array(Box::new(subtype)))
132 } else {
133 let len = num.parse().map_err(Error::ParseInt)?;
135 let subtype = Reader::read(&name[..count - num.len() - 2])?;
136 Ok(ParamType::FixedArray(Box::new(subtype), len))
137 };
138 }
139 _ => (),
140 }
141
142 let result = match name {
143 "address" => ParamType::Address,
144 "bytes" => ParamType::Bytes,
145 "bool" => ParamType::Bool,
146 "string" => ParamType::String,
147 "int" => ParamType::Int(256),
148 "tuple" => ParamType::Tuple(vec![]),
149 "uint" => ParamType::Uint(256),
150 s if s.starts_with("int") => {
151 let len = s[3..].parse().map_err(Error::ParseInt)?;
152 ParamType::Int(len)
153 }
154 s if s.starts_with("uint") => {
155 let len = s[4..].parse().map_err(Error::ParseInt)?;
156 ParamType::Uint(len)
157 }
158 s if s.starts_with("bytes") => {
159 let len = s[5..].parse().map_err(Error::ParseInt)?;
160 ParamType::FixedBytes(len)
161 }
162 _ => ParamType::Uint(8),
168 };
169
170 Ok(result)
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::Reader;
177 #[cfg(not(feature = "std"))]
178 use crate::no_std_prelude::*;
179 use crate::ParamType;
180
181 #[test]
182 fn test_read_param() {
183 assert_eq!(Reader::read("address").unwrap(), ParamType::Address);
184 assert_eq!(Reader::read("bytes").unwrap(), ParamType::Bytes);
185 assert_eq!(Reader::read("bytes32").unwrap(), ParamType::FixedBytes(32));
186 assert_eq!(Reader::read("bool").unwrap(), ParamType::Bool);
187 assert_eq!(Reader::read("string").unwrap(), ParamType::String);
188 assert_eq!(Reader::read("int").unwrap(), ParamType::Int(256));
189 assert_eq!(Reader::read("uint").unwrap(), ParamType::Uint(256));
190 assert_eq!(Reader::read("int32").unwrap(), ParamType::Int(32));
191 assert_eq!(Reader::read("uint32").unwrap(), ParamType::Uint(32));
192 }
193
194 #[test]
195 fn test_read_array_param() {
196 assert_eq!(Reader::read("address[]").unwrap(), ParamType::Array(Box::new(ParamType::Address)));
197 assert_eq!(Reader::read("uint[]").unwrap(), ParamType::Array(Box::new(ParamType::Uint(256))));
198 assert_eq!(Reader::read("bytes[]").unwrap(), ParamType::Array(Box::new(ParamType::Bytes)));
199 assert_eq!(
200 Reader::read("bool[][]").unwrap(),
201 ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bool))))
202 );
203 }
204
205 #[test]
206 fn test_read_fixed_array_param() {
207 assert_eq!(Reader::read("address[2]").unwrap(), ParamType::FixedArray(Box::new(ParamType::Address), 2));
208 assert_eq!(Reader::read("bool[17]").unwrap(), ParamType::FixedArray(Box::new(ParamType::Bool), 17));
209 assert_eq!(
210 Reader::read("bytes[45][3]").unwrap(),
211 ParamType::FixedArray(Box::new(ParamType::FixedArray(Box::new(ParamType::Bytes), 45)), 3)
212 );
213 }
214
215 #[test]
216 fn test_read_mixed_arrays() {
217 assert_eq!(
218 Reader::read("bool[][3]").unwrap(),
219 ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 3)
220 );
221 assert_eq!(
222 Reader::read("bool[3][]").unwrap(),
223 ParamType::Array(Box::new(ParamType::FixedArray(Box::new(ParamType::Bool), 3)))
224 );
225 }
226
227 #[test]
228 fn test_read_struct_param() {
229 assert_eq!(
230 Reader::read("(address,bool)").unwrap(),
231 ParamType::Tuple(vec![ParamType::Address, ParamType::Bool])
232 );
233 assert_eq!(
234 Reader::read("(bool[3],uint256)").unwrap(),
235 ParamType::Tuple(vec![ParamType::FixedArray(Box::new(ParamType::Bool), 3), ParamType::Uint(256)])
236 );
237 }
238
239 #[test]
240 fn test_read_nested_struct_param() {
241 assert_eq!(
242 Reader::read("(address,bool,(bool,uint256))").unwrap(),
243 ParamType::Tuple(vec![
244 ParamType::Address,
245 ParamType::Bool,
246 ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
247 ])
248 );
249 }
250
251 #[test]
252 fn test_read_complex_nested_struct_param() {
253 assert_eq!(
254 Reader::read("(address,bool,(bool,uint256,(bool,uint256)),(bool,uint256))").unwrap(),
255 ParamType::Tuple(vec![
256 ParamType::Address,
257 ParamType::Bool,
258 ParamType::Tuple(vec![
259 ParamType::Bool,
260 ParamType::Uint(256),
261 ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
262 ]),
263 ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
264 ])
265 );
266 }
267
268 #[test]
269 fn test_read_nested_tuple_array_param() {
270 assert_eq!(
271 Reader::read("(uint256,bytes32)[]").unwrap(),
272 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Uint(256), ParamType::FixedBytes(32)])))
273 )
274 }
275
276 #[test]
277 fn test_read_inner_tuple_array_param() {
278 use crate::param_type::Writer;
279 let abi = "((uint256,bytes32)[],address)";
280 let read = Reader::read(abi).unwrap();
281
282 let param = ParamType::Tuple(vec![
283 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Uint(256), ParamType::FixedBytes(32)]))),
284 ParamType::Address,
285 ]);
286
287 assert_eq!(read, param);
288
289 assert_eq!(abi, Writer::write(¶m));
290 }
291}