1use crate::{Address, Bytes, FixedBytes, ParamType, Uint};
11use std::fmt;
12
13#[derive(Debug, PartialEq, Clone)]
15pub enum Token {
16 Address(Address),
21 FixedBytes(FixedBytes),
26 Bytes(Bytes),
33 Int(Uint),
37 Uint(Uint),
41 Bool(bool),
46 String(String),
51 FixedArray(Vec<Token>),
56 Array(Vec<Token>),
60 Tuple(Vec<Token>),
64}
65
66impl fmt::Display for Token {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 match *self {
69 Token::Bool(b) => write!(f, "{}", b),
70 Token::String(ref s) => write!(f, "{}", s),
71 Token::Address(ref a) => write!(f, "{:x}", a),
72 Token::Bytes(ref bytes) | Token::FixedBytes(ref bytes) => write!(f, "{}", hex::encode(&bytes)),
73 Token::Uint(ref i) | Token::Int(ref i) => write!(f, "{:x}", i),
74 Token::Array(ref arr) | Token::FixedArray(ref arr) => {
75 let s = arr.iter().map(|ref t| format!("{}", t)).collect::<Vec<String>>().join(",");
76
77 write!(f, "[{}]", s)
78 }
79 Token::Tuple(ref s) => {
80 let s = s.iter().map(|ref t| format!("{}", t)).collect::<Vec<String>>().join(",");
81
82 write!(f, "({})", s)
83 }
84 }
85 }
86}
87
88impl Token {
89 pub fn type_check(&self, param_type: &ParamType) -> bool {
94 match *self {
95 Token::Address(_) => *param_type == ParamType::Address,
96 Token::Bytes(_) => *param_type == ParamType::Bytes,
97 Token::Int(_) => {
98 matches!(*param_type, ParamType::Int(_))
99 }
100 Token::Uint(_) => {
101 matches!(*param_type, ParamType::Uint(_))
102 }
103 Token::Bool(_) => *param_type == ParamType::Bool,
104 Token::String(_) => *param_type == ParamType::String,
105 Token::FixedBytes(ref bytes) => {
106 if let ParamType::FixedBytes(size) = *param_type {
107 size >= bytes.len()
108 } else {
109 false
110 }
111 }
112 Token::Array(ref tokens) => {
113 if let ParamType::Array(ref param_type) = *param_type {
114 tokens.iter().all(|t| t.type_check(param_type))
115 } else {
116 false
117 }
118 }
119 Token::FixedArray(ref tokens) => {
120 if let ParamType::FixedArray(ref param_type, size) = *param_type {
121 size == tokens.len() && tokens.iter().all(|t| t.type_check(param_type))
122 } else {
123 false
124 }
125 }
126 Token::Tuple(ref tokens) => {
127 if let ParamType::Tuple(ref param_type) = *param_type {
128 tokens.iter().enumerate().all(|(i, t)| t.type_check(¶m_type[i]))
129 } else {
130 false
131 }
132 }
133 }
134 }
135
136 pub fn into_address(self) -> Option<Address> {
138 match self {
139 Token::Address(address) => Some(address),
140 _ => None,
141 }
142 }
143
144 pub fn into_fixed_bytes(self) -> Option<Vec<u8>> {
146 match self {
147 Token::FixedBytes(bytes) => Some(bytes),
148 _ => None,
149 }
150 }
151
152 pub fn into_bytes(self) -> Option<Vec<u8>> {
154 match self {
155 Token::Bytes(bytes) => Some(bytes),
156 _ => None,
157 }
158 }
159
160 pub fn into_int(self) -> Option<Uint> {
162 match self {
163 Token::Int(int) => Some(int),
164 _ => None,
165 }
166 }
167
168 pub fn into_uint(self) -> Option<Uint> {
170 match self {
171 Token::Uint(uint) => Some(uint),
172 _ => None,
173 }
174 }
175
176 pub fn into_bool(self) -> Option<bool> {
178 match self {
179 Token::Bool(b) => Some(b),
180 _ => None,
181 }
182 }
183
184 pub fn into_string(self) -> Option<String> {
186 match self {
187 Token::String(s) => Some(s),
188 _ => None,
189 }
190 }
191
192 pub fn into_fixed_array(self) -> Option<Vec<Token>> {
194 match self {
195 Token::FixedArray(arr) => Some(arr),
196 _ => None,
197 }
198 }
199
200 pub fn into_array(self) -> Option<Vec<Token>> {
202 match self {
203 Token::Array(arr) => Some(arr),
204 _ => None,
205 }
206 }
207
208 pub fn types_check(tokens: &[Token], param_types: &[ParamType]) -> bool {
210 param_types.len() == tokens.len() && {
211 param_types.iter().zip(tokens).all(|(param_type, token)| token.type_check(param_type))
212 }
213 }
214
215 pub fn is_dynamic(&self) -> bool {
217 match self {
218 Token::Bytes(_) | Token::String(_) | Token::Array(_) => true,
219 Token::FixedArray(tokens) => tokens.iter().any(|token| token.is_dynamic()),
220 Token::Tuple(tokens) => tokens.iter().any(|token| token.is_dynamic()),
221 _ => false,
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use crate::{ParamType, Token};
229
230 #[test]
231 fn test_type_check() {
232 fn assert_type_check(tokens: Vec<Token>, param_types: Vec<ParamType>) {
233 assert!(Token::types_check(&tokens, ¶m_types))
234 }
235
236 fn assert_not_type_check(tokens: Vec<Token>, param_types: Vec<ParamType>) {
237 assert!(!Token::types_check(&tokens, ¶m_types))
238 }
239
240 assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(256), ParamType::Bool]);
241 assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(32), ParamType::Bool]);
242
243 assert_not_type_check(vec![Token::Uint(0.into())], vec![ParamType::Uint(32), ParamType::Bool]);
244 assert_not_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(32)]);
245 assert_not_type_check(
246 vec![Token::Bool(false), Token::Uint(0.into())],
247 vec![ParamType::Uint(32), ParamType::Bool],
248 );
249
250 assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamType::FixedBytes(4)]);
251 assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0])], vec![ParamType::FixedBytes(4)]);
252 assert_not_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamType::FixedBytes(3)]);
253
254 assert_type_check(
255 vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])],
256 vec![ParamType::Array(Box::new(ParamType::Bool))],
257 );
258 assert_not_type_check(
259 vec![Token::Array(vec![Token::Bool(false), Token::Uint(0.into())])],
260 vec![ParamType::Array(Box::new(ParamType::Bool))],
261 );
262 assert_not_type_check(
263 vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])],
264 vec![ParamType::Array(Box::new(ParamType::Address))],
265 );
266
267 assert_type_check(
268 vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
269 vec![ParamType::FixedArray(Box::new(ParamType::Bool), 2)],
270 );
271 assert_not_type_check(
272 vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
273 vec![ParamType::FixedArray(Box::new(ParamType::Bool), 3)],
274 );
275 assert_not_type_check(
276 vec![Token::FixedArray(vec![Token::Bool(false), Token::Uint(0.into())])],
277 vec![ParamType::FixedArray(Box::new(ParamType::Bool), 2)],
278 );
279 assert_not_type_check(
280 vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
281 vec![ParamType::FixedArray(Box::new(ParamType::Address), 2)],
282 );
283 }
284
285 #[test]
286 fn test_is_dynamic() {
287 assert_eq!(Token::Address("0000000000000000000000000000000000000000".parse().unwrap()).is_dynamic(), false);
288 assert_eq!(Token::Bytes(vec![0, 0, 0, 0]).is_dynamic(), true);
289 assert_eq!(Token::FixedBytes(vec![0, 0, 0, 0]).is_dynamic(), false);
290 assert_eq!(Token::Uint(0.into()).is_dynamic(), false);
291 assert_eq!(Token::Int(0.into()).is_dynamic(), false);
292 assert_eq!(Token::Bool(false).is_dynamic(), false);
293 assert_eq!(Token::String("".into()).is_dynamic(), true);
294 assert_eq!(Token::Array(vec![Token::Bool(false)]).is_dynamic(), true);
295 assert_eq!(Token::FixedArray(vec![Token::Uint(0.into())]).is_dynamic(), false);
296 assert_eq!(Token::FixedArray(vec![Token::String("".into())]).is_dynamic(), true);
297 assert_eq!(Token::FixedArray(vec![Token::Array(vec![Token::Bool(false)])]).is_dynamic(), true);
298 }
299}