1use crate::{Error, ParamType};
10
11pub struct Reader;
13
14impl Reader {
15 pub fn read(name: &str) -> Result<ParamType, Error> {
17 match name.chars().last() {
18 Some(')') => {
20 if !name.starts_with('(') {
21 return Err(Error::InvalidName(name.to_owned()));
22 };
23
24 let mut subtypes = Vec::new();
25 let mut subtuples = Vec::new();
26 let mut nested = 0isize;
27 let mut top_level_paren_open = 0usize;
28 let mut last_item = 1;
29 let mut chars = name.chars().enumerate();
30
31 while let Some((mut pos, c)) = chars.next() {
33 match c {
34 '(' => {
35 top_level_paren_open = pos;
36 nested += 1;
37 if nested > 1 {
40 subtuples.push(vec![]);
41 last_item = pos + 1;
42 }
43 }
44 ')' => {
45 nested -= 1;
46
47 if nested < 0 {
49 return Err(Error::InvalidName(name.to_owned()));
50 }
51 else if name[last_item..pos].is_empty() {
54 last_item = pos + 1;
55 }
56 else if nested == 0 {
58 let sub = &name[last_item..pos];
60 let subtype = Reader::read(sub)?;
61 subtypes.push(subtype);
62 last_item = pos + 1;
63 }
64 else if nested > 0 {
66 loop {
68 match chars.clone().next() {
69 Some((_, ',')) | Some((_, ')')) | None => break,
70 _ => {
71 chars.next();
73 pos += 1;
74 }
75 }
76 }
77
78 let inner_tuple = &name[top_level_paren_open..=pos];
80 let subtype = Reader::read(inner_tuple)?;
81
82 if nested > 1 {
83 subtuples[(nested - 2) as usize].push(subtype);
84 subtypes.push(ParamType::Tuple(std::mem::replace(
85 &mut subtuples[(nested - 2) as usize],
86 Vec::new(),
87 )));
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 = usize::from_str_radix(&num, 10)?;
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 = usize::from_str_radix(&s[3..], 10)?;
152 ParamType::Int(len)
153 }
154 s if s.starts_with("uint") => {
155 let len = usize::from_str_radix(&s[4..], 10)?;
156 ParamType::Uint(len)
157 }
158 s if s.starts_with("bytes") => {
159 let len = usize::from_str_radix(&s[5..], 10)?;
160 ParamType::FixedBytes(len)
161 }
162 _ => {
163 return Err(Error::InvalidName(name.to_owned()));
164 }
165 };
166
167 Ok(result)
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::Reader;
174 use crate::ParamType;
175
176 #[test]
177 fn test_read_param() {
178 assert_eq!(Reader::read("address").unwrap(), ParamType::Address);
179 assert_eq!(Reader::read("bytes").unwrap(), ParamType::Bytes);
180 assert_eq!(Reader::read("bytes32").unwrap(), ParamType::FixedBytes(32));
181 assert_eq!(Reader::read("bool").unwrap(), ParamType::Bool);
182 assert_eq!(Reader::read("string").unwrap(), ParamType::String);
183 assert_eq!(Reader::read("int").unwrap(), ParamType::Int(256));
184 assert_eq!(Reader::read("uint").unwrap(), ParamType::Uint(256));
185 assert_eq!(Reader::read("int32").unwrap(), ParamType::Int(32));
186 assert_eq!(Reader::read("uint32").unwrap(), ParamType::Uint(32));
187 }
188
189 #[test]
190 fn test_read_array_param() {
191 assert_eq!(Reader::read("address[]").unwrap(), ParamType::Array(Box::new(ParamType::Address)));
192 assert_eq!(Reader::read("uint[]").unwrap(), ParamType::Array(Box::new(ParamType::Uint(256))));
193 assert_eq!(Reader::read("bytes[]").unwrap(), ParamType::Array(Box::new(ParamType::Bytes)));
194 assert_eq!(
195 Reader::read("bool[][]").unwrap(),
196 ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bool))))
197 );
198 }
199
200 #[test]
201 fn test_read_fixed_array_param() {
202 assert_eq!(Reader::read("address[2]").unwrap(), ParamType::FixedArray(Box::new(ParamType::Address), 2));
203 assert_eq!(Reader::read("bool[17]").unwrap(), ParamType::FixedArray(Box::new(ParamType::Bool), 17));
204 assert_eq!(
205 Reader::read("bytes[45][3]").unwrap(),
206 ParamType::FixedArray(Box::new(ParamType::FixedArray(Box::new(ParamType::Bytes), 45)), 3)
207 );
208 }
209
210 #[test]
211 fn test_read_mixed_arrays() {
212 assert_eq!(
213 Reader::read("bool[][3]").unwrap(),
214 ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 3)
215 );
216 assert_eq!(
217 Reader::read("bool[3][]").unwrap(),
218 ParamType::Array(Box::new(ParamType::FixedArray(Box::new(ParamType::Bool), 3)))
219 );
220 }
221
222 #[test]
223 fn test_read_struct_param() {
224 assert_eq!(
225 Reader::read("(address,bool)").unwrap(),
226 ParamType::Tuple(vec![ParamType::Address, ParamType::Bool])
227 );
228 assert_eq!(
229 Reader::read("(bool[3],uint256)").unwrap(),
230 ParamType::Tuple(vec![ParamType::FixedArray(Box::new(ParamType::Bool), 3), ParamType::Uint(256)])
231 );
232 }
233
234 #[test]
235 fn test_read_nested_struct_param() {
236 assert_eq!(
237 Reader::read("(address,bool,(bool,uint256))").unwrap(),
238 ParamType::Tuple(vec![
239 ParamType::Address,
240 ParamType::Bool,
241 ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
242 ])
243 );
244 }
245
246 #[test]
247 fn test_read_complex_nested_struct_param() {
248 assert_eq!(
249 Reader::read("(address,bool,(bool,uint256,(bool,uint256)),(bool,uint256))").unwrap(),
250 ParamType::Tuple(vec![
251 ParamType::Address,
252 ParamType::Bool,
253 ParamType::Tuple(vec![
254 ParamType::Bool,
255 ParamType::Uint(256),
256 ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
257 ]),
258 ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
259 ])
260 );
261 }
262
263 #[test]
264 fn test_read_nested_tuple_array_param() {
265 assert_eq!(
266 Reader::read("(uint256,bytes32)[]").unwrap(),
267 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Uint(256), ParamType::FixedBytes(32)])))
268 )
269 }
270
271 #[test]
272 fn test_read_inner_tuple_array_param() {
273 use crate::param_type::Writer;
274 let abi = "((uint256,bytes32)[],address)";
275 let read = Reader::read(abi).unwrap();
276
277 let param = ParamType::Tuple(vec![
278 ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Uint(256), ParamType::FixedBytes(32)]))),
279 ParamType::Address,
280 ]);
281
282 assert_eq!(read, param);
283
284 assert_eq!(abi, Writer::write(¶m));
285 }
286}