pub fn read(name: &str) -> Result<ParamType, Error> {
		match name.chars().last() {
			// check if it is a struct
			Some(')') => {
				if !name.starts_with('(') {
					return Err(Error::InvalidName(name.to_owned()));
				};

				let mut subtypes = Vec::new();
				let mut subtuples = Vec::new();
				let mut nested = 0isize;
				let mut top_level_paren_open = 0usize;
				let mut last_item = 1;
				let mut chars = name.chars().enumerate();

				// Iterate over name and build the nested tuple structure
				while let Some((mut pos, c)) = chars.next() {
					match c {
						'(' => {
							top_level_paren_open = pos;
							nested += 1;
							// If an '(' is encountered within the tuple
							// insert an empty subtuples vector to be filled
							if nested > 1 {
								subtuples.push(vec![]);
								last_item = pos + 1;
							}
						}
						')' => {
							nested -= 1;

							// End parsing and return an error if parentheses aren't symmetrical
							if nested < 0 {
								return Err(Error::InvalidName(name.to_owned()));
							}
							// If there have not been any characters since the last item
							// increment position without inserting any subtypes
							else if name[last_item..pos].is_empty() {
								last_item = pos + 1;
							}
							// If the item is in the top level of the tuple insert it into subtypes
							else if nested == 0 {
								// check for trailing brackets that indicate array of tuples
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtypes.push(subtype);
								last_item = pos + 1;
							}
							// If the item is in a sublevel of the tuple
							else if nested > 0 {
								// this makes sure trailing brackets are included for the next step
								loop {
									match chars.clone().next() {
										Some((_, ',')) | Some((_, ')')) | None => break,
										_ => {
											// consume the char and shift position
											chars.next();
											pos += 1;
										}
									}
								}

								// parse the nested tuple
								let inner_tuple = &name[top_level_paren_open..=pos];
								let subtype = Reader::read(inner_tuple)?;

								if nested > 1 {
									let mut subtuple = std::mem::take(&mut subtuples[(nested - 2) as usize]);
									subtuple.push(subtype);
									subtypes.push(ParamType::Tuple(subtuple));
								} else {
									subtypes.push(subtype);
								}
								last_item = pos + 1;
							}
						}
						',' => {
							// If there have not been any characters since the last item
							// increment position without inserting any subtypes
							if name[last_item..pos].is_empty() {
								last_item = pos + 1
							}
							// If the item is in the top level of the tuple insert it into subtypes
							else if nested == 1 {
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtypes.push(subtype);
								last_item = pos + 1;
							}
							// If the item is in a sublevel of the tuple
							// insert it into the subtuple vector for the current depth level
							else if nested > 1 {
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtuples[(nested - 2) as usize].push(subtype);
								last_item = pos + 1;
							}
						}
						_ => (),
					}
				}
				return Ok(ParamType::Tuple(subtypes));
			}
			// check if it is a fixed or dynamic array.
			Some(']') => {
				// take number part
				let num: String =
					name.chars().rev().skip(1).take_while(|c| *c != '[').collect::<String>().chars().rev().collect();

				let count = name.chars().count();
				return if num.is_empty() {
					// we already know it's a dynamic array!
					let subtype = Reader::read(&name[..count - 2])?;
					Ok(ParamType::Array(Box::new(subtype)))
				} else {
					// it's a fixed array.
					let len = num.parse()?;
					let subtype = Reader::read(&name[..count - num.len() - 2])?;
					Ok(ParamType::FixedArray(Box::new(subtype), len))
				};
			}
			_ => (),
		}

		let result = match name {
			"address" => ParamType::Address,
			"bytes" => ParamType::Bytes,
			"bool" => ParamType::Bool,
			"string" => ParamType::String,
			"int" => ParamType::Int(256),
			"tuple" => ParamType::Tuple(vec![]),
			"uint" => ParamType::Uint(256),
			s if s.starts_with("int") => {
				let len = s[3..].parse()?;
				ParamType::Int(len)
			}
			s if s.starts_with("uint") => {
				let len = s[4..].parse()?;
				ParamType::Uint(len)
			}
			s if s.starts_with("bytes") => {
				let len = s[5..].parse()?;
				ParamType::FixedBytes(len)
			}
			// As discussed in https://github.com/rust-ethereum/ethabi/issues/254,
			// any type that does not fit the above corresponds to a Solidity
			// `enum`, and as a result we treat it as a `uint8`. This is a unique
			// case which occurs in libraries with exported (`public`) Solidity
			// functions with `enum` parameters.
			_ => ParamType::Uint(8),
		};

		Ok(result)
	}
/// Converts string to param type.
Converts string to param type.
Converts string to param type .
pub fn read(name: &str) -> Result<ParamType, Error> {
		match name.chars().last() {
			// check if it is a struct
			Some(')') => {
				if !name.starts_with('(') {
					return Err(Error::InvalidName(name.to_owned()));
				};
				let mut subtypes = Vec::new();
				let mut subtuples = Vec::new();
				let mut nested = 0isize;
				let mut top_level_paren_open = 0usize;
				let mut last_item = 1;
				let mut chars = name.chars().enumerate();
				// Iterate over name and build the nested tuple structure
				while let Some((mut pos, c)) = chars.next() {
					match c {
						'(' => {
							top_level_paren_open = pos;
							nested += 1;
							// If an '(' is encountered within the tuple
							// insert an empty subtuples vector to be filled
							if nested > 1 {
								subtuples.push(vec![]);
								last_item = pos + 1;
							}
						}
						')' => {
							nested -= 1;
							// End parsing and return an error if parentheses aren't symmetrical
							if nested < 0 {
								return Err(Error::InvalidName(name.to_owned()));
							}
							// If there have not been any characters since the last item
							// increment position without inserting any subtypes
							else if name[last_item..pos].is_empty() {
								last_item = pos + 1;
							}
							// If the item is in the top level of the tuple insert it into subtypes
							else if nested == 0 {
								// check for trailing brackets that indicate array of tuples
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtypes.push(subtype);
								last_item = pos + 1;
							}
							// If the item is in a sublevel of the tuple
							else if nested > 0 {
								// this makes sure trailing brackets are included for the next step
								loop {
									match chars.clone().next() {
										Some((_, ',')) | Some((_, ')')) | None => break,
										_ => {
											// consume the char and shift position
											chars.next();
											pos += 1;
										}
									}
								}
								// parse the nested tuple
								let inner_tuple = &name[top_level_paren_open..=pos];
								let subtype = Reader::read(inner_tuple)?;
								if nested > 1 {
									let mut subtuple = std::mem::take(&mut subtuples[(nested - 2) as usize]);
									subtuple.push(subtype);
									subtypes.push(ParamType::Tuple(subtuple));
								} else {
									subtypes.push(subtype);
								}
								last_item = pos + 1;
							}
						}
						',' => {
							// If there have not been any characters since the last item
							// increment position without inserting any subtypes
							if name[last_item..pos].is_empty() {
								last_item = pos + 1
							}
							// If the item is in the top level of the tuple insert it into subtypes
							else if nested == 1 {
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtypes.push(subtype);
								last_item = pos + 1;
							}
							// If the item is in a sublevel of the tuple
							// insert it into the subtuple vector for the current depth level
							else if nested > 1 {
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtuples[(nested - 2) as usize].push(subtype);
								last_item = pos + 1;
							}
						}
						_ => (),
					}
				}
				return Ok(ParamType::Tuple(subtypes));
			}
			// check if it is a fixed or dynamic array.
			Some(']') => {
				// take number part
				let num: String =
					name.chars().rev().skip(1).take_while(|c| *c != '[').collect::<String>().chars().rev().collect();
				let count = name.chars().count();
				return if num.is_empty() {
					// we already know it's a dynamic array!
					let subtype = Reader::read(&name[..count - 2])?;
					Ok(ParamType::Array(Box::new(subtype)))
				} else {
					// it's a fixed array.
					let len = num.parse()?;
					let subtype = Reader::read(&name[..count - num.len() - 2])?;
					Ok(ParamType::FixedArray(Box::new(subtype), len))
				};
			}
			_ => (),
		}
		let result = match name {
			"address" => ParamType::Address,
			"bytes" => ParamType::Bytes,
			"bool" => ParamType::Bool,
			"string" => ParamType::String,
			"int" => ParamType::Int(256),
			"tuple" => ParamType::Tuple(vec![]),
			"uint" => ParamType::Uint(256),
			s if s.starts_with("int") => {
				let len = s[3..].parse()?;
				ParamType::Int(len)
			}
			s if s.starts_with("uint") => {
				let len = s[4..].parse()?;
				ParamType::Uint(len)
			}
			s if s.starts_with("bytes") => {
				let len = s[5..].parse()?;
				ParamType::FixedBytes(len)
			}
			// As discussed in https://github.com/rust-ethereum/ethabi/issues/254,
			// any type that does not fit the above corresponds to a Solidity
			// `enum`, and as a result we treat it as a `uint8`. This is a unique
			// case which occurs in libraries with exported (`public`) Solidity
			// functions with `enum` parameters.
			_ => ParamType::Uint(8),
		};
		Ok(result)
	}
pub fn read ( name : & str ) -> Result < ParamType , Error > { match name . chars ( ) . last ( ) { // check if it is a struct Some ( ')' ) => { if ! name . starts_with ( '(' ) { return Err ( Error :: InvalidName ( name . to_owned ( ) ) ) ; } ; let mut subtypes = Vec :: new ( ) ; let mut subtuples = Vec :: new ( ) ; let mut nested = 0isize ; let mut top_level_paren_open = 0usize ; let mut last_item = 1 ; let mut chars = name . chars ( ) . enumerate ( ) ; // Iterate over name and build the nested tuple structure while let Some ( ( mut pos , c ) ) = chars . next ( ) { match c { '(' => { top_level_paren_open = pos ; nested += 1 ; // If an '(' is encountered within the tuple // insert an empty subtuples vector to be filled if nested > 1 { subtuples . push ( vec ! [ ] ) ; last_item = pos + 1 ; } } ')' => { nested -= 1 ; // End parsing and return an error if parentheses aren't symmetrical if nested < 0 { return Err ( Error :: InvalidName ( name . to_owned ( ) ) ) ; } // If there have not been any characters since the last item // increment position without inserting any subtypes else if name [ last_item .. pos ] . is_empty ( ) { last_item = pos + 1 ; } // If the item is in the top level of the tuple insert it into subtypes else if nested == 0 { // check for trailing brackets that indicate array of tuples let sub = & name [ last_item .. pos ] ; let subtype = Reader :: read ( sub ) ? ; subtypes . push ( subtype ) ; last_item = pos + 1 ; } // If the item is in a sublevel of the tuple else if nested > 0 { // this makes sure trailing brackets are included for the next step loop { match chars . clone ( ) . next ( ) { Some ( ( _ , ',' ) ) | Some ( ( _ , ')' ) ) | None => break , _ => { // consume the char and shift position chars . next ( ) ; pos += 1 ; } } } // parse the nested tuple let inner_tuple = & name [ top_level_paren_open ..= pos ] ; let subtype = Reader :: read ( inner_tuple ) ? ; if nested > 1 { let mut subtuple = std :: mem :: take ( & mut subtuples [ ( nested - 2 ) as usize ] ) ; subtuple . push ( subtype ) ; subtypes . push ( ParamType :: Tuple ( subtuple ) ) ; } else { subtypes . push ( subtype ) ; } last_item = pos + 1 ; } } ',' => { // If there have not been any characters since the last item // increment position without inserting any subtypes if name [ last_item .. pos ] . is_empty ( ) { last_item = pos + 1 } // If the item is in the top level of the tuple insert it into subtypes else if nested == 1 { let sub = & name [ last_item .. pos ] ; let subtype = Reader :: read ( sub ) ? ; subtypes . push ( subtype ) ; last_item = pos + 1 ; } // If the item is in a sublevel of the tuple // insert it into the subtuple vector for the current depth level else if nested > 1 { let sub = & name [ last_item .. pos ] ; let subtype = Reader :: read ( sub ) ? ; subtuples [ ( nested - 2 ) as usize ] . push ( subtype ) ; last_item = pos + 1 ; } } _ => ( ) , } } return Ok ( ParamType :: Tuple ( subtypes ) ) ; } // check if it is a fixed or dynamic array. Some ( ']' ) => { // take number part let num : String = name . chars ( ) . rev ( ) . skip ( 1 ) . take_while ( | c | * c != '[' ) . collect :: < String > ( ) . chars ( ) . rev ( ) . collect ( ) ; let count = name . chars ( ) . count ( ) ; return if num . is_empty ( ) { // we already know it's a dynamic array! let subtype = Reader :: read ( & name [ .. count - 2 ] ) ? ; Ok ( ParamType :: Array ( Box :: new ( subtype ) ) ) } else { // it's a fixed array. let len = num . parse ( ) ? ; let subtype = Reader :: read ( & name [ .. count - num . len ( ) - 2 ] ) ? ; Ok ( ParamType :: FixedArray ( Box :: new ( subtype ) , len ) ) } ; } _ => ( ) , } let result = match name { " " => ParamType :: Address , " " => ParamType :: Bytes , " " => ParamType :: Bool , " " => ParamType :: String , " " => ParamType :: Int ( 256 ) , " " => ParamType :: Tuple ( vec ! [ ] ) , " " => ParamType :: Uint ( 256 ) , s if s . starts_with ( " " ) => { let len = s [ 3 .. ] . parse ( ) ? ; ParamType :: Int ( len ) } s if s . starts_with ( " " ) => { let len = s [ 4 .. ] . parse ( ) ? ; ParamType :: Uint ( len ) } s if s . starts_with ( " " ) => { let len = s [ 5 .. ] . parse ( ) ? ; ParamType :: FixedBytes ( len ) } // As discussed in https://github.com/rust-ethereum/ethabi/issues/254, // any type that does not fit the above corresponds to a Solidity // `enum`, and as a result we treat it as a `uint8`. This is a unique // case which occurs in libraries with exported (`public`) Solidity // functions with `enum` parameters. _ => ParamType :: Uint ( 8 ) , } ; Ok ( result ) }
Converts string to param type.
Converts string to param type .
name
&str