ethabi_fork_ethcontract/token/
lenient.rs

1// Copyright 2015-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
9use crate::{
10	errors::Error,
11	token::{StrictTokenizer, Tokenizer},
12	Uint,
13};
14use anyhow::anyhow;
15
16/// Tries to parse string as a token. Does not require string to clearly represent the value.
17pub struct LenientTokenizer;
18
19impl Tokenizer for LenientTokenizer {
20	fn tokenize_address(value: &str) -> Result<[u8; 20], Error> {
21		StrictTokenizer::tokenize_address(value)
22	}
23
24	fn tokenize_string(value: &str) -> Result<String, Error> {
25		StrictTokenizer::tokenize_string(value)
26	}
27
28	fn tokenize_bool(value: &str) -> Result<bool, Error> {
29		StrictTokenizer::tokenize_bool(value)
30	}
31
32	fn tokenize_bytes(value: &str) -> Result<Vec<u8>, Error> {
33		StrictTokenizer::tokenize_bytes(value)
34	}
35
36	fn tokenize_fixed_bytes(value: &str, len: usize) -> Result<Vec<u8>, Error> {
37		StrictTokenizer::tokenize_fixed_bytes(value, len)
38	}
39
40	fn tokenize_uint(value: &str) -> Result<[u8; 32], Error> {
41		let result = StrictTokenizer::tokenize_uint(value);
42		if result.is_ok() {
43			return result;
44		}
45
46		let uint = Uint::from_dec_str(value)?;
47		Ok(uint.into())
48	}
49
50	// We don't have a proper signed int 256-bit long type, so here we're cheating. We build a U256
51	// out of it and check that it's within the lower/upper bound of a hypothetical I256 type: half
52	// the `U256::max_value().
53	fn tokenize_int(value: &str) -> Result<[u8; 32], Error> {
54		let result = StrictTokenizer::tokenize_int(value);
55		if result.is_ok() {
56			return result;
57		}
58
59		let abs = Uint::from_dec_str(value.trim_start_matches('-'))?;
60		let max = Uint::max_value() / 2;
61		let int = if value.starts_with('-') {
62			if abs.is_zero() {
63				return Ok(abs.into());
64			} else if abs > max + 1 {
65				return Err(anyhow!("int256 parse error: Underflow").into());
66			}
67			!abs + 1 // two's complement
68		} else {
69			if abs > max {
70				return Err(anyhow!("int256 parse error: Overflow").into());
71			}
72			abs
73		};
74		Ok(int.into())
75	}
76}