1use crate::{Address, ParamKind, U256};
12
13use crate::std::Vec;
14
15#[derive(Debug, PartialEq, Clone)]
17pub enum Token {
18 Address(Address),
23 FixedBytes(Vec<u8>),
28 Bytes(Vec<u8>),
35 Int(U256),
39 Uint(U256),
43 Bool(bool),
48 String(Vec<u8>),
53 FixedArray(Vec<Token>),
58 Array(Vec<Token>),
62 Tuple(Vec<Token>),
66}
67
68impl Token {
69 pub fn type_check(&self, param_type: &ParamKind) -> bool {
74 match *self {
75 Token::Address(_) => *param_type == ParamKind::Address,
76 Token::Bytes(_) => *param_type == ParamKind::Bytes,
77 Token::Int(_) => {
78 if let ParamKind::Int(_) = *param_type {
79 true
80 } else {
81 false
82 }
83 }
84 Token::Uint(_) => {
85 if let ParamKind::Uint(_) = *param_type {
86 true
87 } else {
88 false
89 }
90 }
91 Token::Bool(_) => *param_type == ParamKind::Bool,
92 Token::String(_) => *param_type == ParamKind::String,
93 Token::FixedBytes(ref bytes) => {
94 if let ParamKind::FixedBytes(size) = *param_type {
95 size >= bytes.len()
96 } else {
97 false
98 }
99 }
100 Token::Array(ref tokens) => {
101 if let ParamKind::Array(ref param_type) = *param_type {
102 tokens.iter().all(|t| t.type_check(param_type))
103 } else {
104 false
105 }
106 }
107 Token::FixedArray(ref tokens) => {
108 if let ParamKind::FixedArray(ref param_type, size) = *param_type {
109 size == tokens.len() && tokens.iter().all(|t| t.type_check(param_type))
110 } else {
111 false
112 }
113 }
114 Token::Tuple(ref tokens) => {
115 if let ParamKind::Tuple(ref param_type) = *param_type {
116 tokens.iter().enumerate().all(|(i, t)| t.type_check(¶m_type[i]))
117 } else {
118 false
119 }
120 }
121 }
122 }
123
124 pub fn to_address(self) -> Option<Address> {
126 match self {
127 Token::Address(address) => Some(address),
128 _ => None,
129 }
130 }
131
132 pub fn to_fixed_bytes(self) -> Option<Vec<u8>> {
134 match self {
135 Token::FixedBytes(bytes) => Some(bytes),
136 _ => None,
137 }
138 }
139
140 pub fn to_bytes(self) -> Option<Vec<u8>> {
142 match self {
143 Token::Bytes(bytes) => Some(bytes),
144 _ => None,
145 }
146 }
147
148 pub fn to_int(self) -> Option<U256> {
150 match self {
151 Token::Int(int) => Some(int),
152 _ => None,
153 }
154 }
155
156 pub fn to_uint(self) -> Option<U256> {
158 match self {
159 Token::Uint(uint) => Some(uint),
160 _ => None,
161 }
162 }
163
164 pub fn to_bool(self) -> Option<bool> {
166 match self {
167 Token::Bool(b) => Some(b),
168 _ => None,
169 }
170 }
171
172 pub fn to_string(self) -> Option<Vec<u8>> {
174 match self {
175 Token::String(s) => Some(s),
176 _ => None,
177 }
178 }
179
180 pub fn to_fixed_array(self) -> Option<Vec<Token>> {
182 match self {
183 Token::FixedArray(arr) => Some(arr),
184 _ => None,
185 }
186 }
187
188 pub fn to_array(self) -> Option<Vec<Token>> {
190 match self {
191 Token::Array(arr) => Some(arr),
192 _ => None,
193 }
194 }
195
196 pub fn types_check(tokens: &[Token], param_types: &[ParamKind]) -> bool {
198 param_types.len() == tokens.len() && {
199 param_types.iter().zip(tokens).all(|(param_type, token)| token.type_check(param_type))
200 }
201 }
202
203 pub fn is_dynamic(&self) -> bool {
205 match self {
206 Token::Bytes(_) | Token::String(_) | Token::Array(_) => true,
207 Token::FixedArray(tokens) => tokens.iter().any(|token| token.is_dynamic()),
208 Token::Tuple(tokens) => tokens.iter().any(|token| token.is_dynamic()),
209 _ => false,
210 }
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use crate::{ParamKind, Token};
217
218 #[test]
219 fn test_type_check() {
220 fn assert_type_check(tokens: Vec<Token>, param_types: Vec<ParamKind>) {
221 assert!(Token::types_check(&tokens, ¶m_types))
222 }
223
224 fn assert_not_type_check(tokens: Vec<Token>, param_types: Vec<ParamKind>) {
225 assert!(!Token::types_check(&tokens, ¶m_types))
226 }
227
228 assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamKind::Uint(256), ParamKind::Bool]);
229 assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamKind::Uint(32), ParamKind::Bool]);
230
231 assert_not_type_check(vec![Token::Uint(0.into())], vec![ParamKind::Uint(32), ParamKind::Bool]);
232 assert_not_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamKind::Uint(32)]);
233 assert_not_type_check(
234 vec![Token::Bool(false), Token::Uint(0.into())],
235 vec![ParamKind::Uint(32), ParamKind::Bool],
236 );
237
238 assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamKind::FixedBytes(4)]);
239 assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0])], vec![ParamKind::FixedBytes(4)]);
240 assert_not_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamKind::FixedBytes(3)]);
241
242 assert_type_check(
243 vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])],
244 vec![ParamKind::Array(Box::new(ParamKind::Bool))],
245 );
246 assert_not_type_check(
247 vec![Token::Array(vec![Token::Bool(false), Token::Uint(0.into())])],
248 vec![ParamKind::Array(Box::new(ParamKind::Bool))],
249 );
250 assert_not_type_check(
251 vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])],
252 vec![ParamKind::Array(Box::new(ParamKind::Address))],
253 );
254
255 assert_type_check(
256 vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
257 vec![ParamKind::FixedArray(Box::new(ParamKind::Bool), 2)],
258 );
259 assert_not_type_check(
260 vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
261 vec![ParamKind::FixedArray(Box::new(ParamKind::Bool), 3)],
262 );
263 assert_not_type_check(
264 vec![Token::FixedArray(vec![Token::Bool(false), Token::Uint(0.into())])],
265 vec![ParamKind::FixedArray(Box::new(ParamKind::Bool), 2)],
266 );
267 assert_not_type_check(
268 vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
269 vec![ParamKind::FixedArray(Box::new(ParamKind::Address), 2)],
270 );
271 }
272
273 #[test]
274 fn test_is_dynamic() {
275 assert_eq!(Token::Address("0000000000000000000000000000000000000000".parse().unwrap()).is_dynamic(), false);
276 assert_eq!(Token::Bytes(vec![0, 0, 0, 0]).is_dynamic(), true);
277 assert_eq!(Token::FixedBytes(vec![0, 0, 0, 0]).is_dynamic(), false);
278 assert_eq!(Token::Uint(0.into()).is_dynamic(), false);
279 assert_eq!(Token::Int(0.into()).is_dynamic(), false);
280 assert_eq!(Token::Bool(false).is_dynamic(), false);
281 assert_eq!(Token::String("".into()).is_dynamic(), true);
282 assert_eq!(Token::Array(vec![Token::Bool(false)]).is_dynamic(), true);
283 assert_eq!(Token::FixedArray(vec![Token::Uint(0.into())]).is_dynamic(), false);
284 assert_eq!(Token::FixedArray(vec![Token::String("".into())]).is_dynamic(), true);
285 assert_eq!(Token::FixedArray(vec![Token::Array(vec![Token::Bool(false)])]).is_dynamic(), true);
286 }
287}