1use std::fmt;
3use hex::ToHex;
4use {ParamType, Address, FixedBytes, Bytes, Uint};
5
6#[derive(Debug, PartialEq, Clone)]
8pub enum Token {
9 Address(Address),
14 FixedBytes(FixedBytes),
19 Bytes(Bytes),
26 Int(Uint),
30 Uint(Uint),
34 Bool(bool),
39 String(String),
44 FixedArray(Vec<Token>),
49 Array(Vec<Token>),
53}
54
55impl fmt::Display for Token {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 match *self {
58 Token::Bool(b) => write!(f, "{}", b),
59 Token::String(ref s) => write!(f, "{}", s),
60 Token::Address(ref a) => write!(f, "{:x}", a),
61 Token::Bytes(ref bytes) | Token::FixedBytes(ref bytes) => write!(f, "{}", bytes.to_hex::<String>()),
62 Token::Uint(ref i) | Token::Int(ref i) => write!(f, "{:x}", i),
63 Token::Array(ref arr) | Token::FixedArray(ref arr) => {
64 let s = arr.iter()
65 .map(|ref t| format!("{}", t))
66 .collect::<Vec<String>>()
67 .join(",");
68
69 write!(f, "[{}]", s)
70 }
71 }
72 }
73}
74
75impl Token {
76 pub fn type_check(&self, param_type: &ParamType) -> bool {
81 match *self {
82 Token::Address(_) => *param_type == ParamType::Address,
83 Token::Bytes(_) => *param_type == ParamType::Bytes,
84 Token::Int(_) =>
85 if let ParamType::Int(_) = *param_type {
86 true
87 } else {
88 false
89 },
90 Token::Uint(_) =>
91 if let ParamType::Uint(_) = *param_type {
92 true
93 } else {
94 false
95 },
96 Token::Bool(_) => *param_type == ParamType::Bool,
97 Token::String(_) => *param_type == ParamType::String,
98 Token::FixedBytes(ref bytes) =>
99 if let ParamType::FixedBytes(size) = *param_type {
100 size >= bytes.len()
101 } else {
102 false
103 },
104 Token::Array(ref tokens) =>
105 if let ParamType::Array(ref param_type) = *param_type {
106 tokens.iter().all(|t| t.type_check(param_type))
107 } else {
108 false
109 },
110 Token::FixedArray(ref tokens) =>
111 if let ParamType::FixedArray(ref param_type, size) = *param_type {
112 size == tokens.len() && tokens.iter().all(|t| t.type_check(param_type))
113 } else {
114 false
115 },
116 }
117 }
118
119 pub fn to_address(self) -> Option<Address> {
121 match self {
122 Token::Address(address) => Some(address),
123 _ => None,
124 }
125 }
126
127 pub fn to_fixed_bytes(self) -> Option<Vec<u8>> {
129 match self {
130 Token::FixedBytes(bytes) => Some(bytes),
131 _ => None,
132 }
133 }
134
135 pub fn to_bytes(self) -> Option<Vec<u8>> {
137 match self {
138 Token::Bytes(bytes) => Some(bytes),
139 _ => None,
140 }
141 }
142
143 pub fn to_int(self) -> Option<Uint> {
145 match self {
146 Token::Int(int) => Some(int),
147 _ => None,
148 }
149 }
150
151 pub fn to_uint(self) -> Option<Uint> {
153 match self {
154 Token::Uint(uint) => Some(uint),
155 _ => None,
156 }
157 }
158
159 pub fn to_bool(self) -> Option<bool> {
161 match self {
162 Token::Bool(b) => Some(b),
163 _ => None,
164 }
165 }
166
167 pub fn to_string(self) -> Option<String> {
169 match self {
170 Token::String(s) => Some(s),
171 _ => None,
172 }
173 }
174
175 pub fn to_fixed_array(self) -> Option<Vec<Token>> {
177 match self {
178 Token::FixedArray(arr) => Some(arr),
179 _ => None,
180 }
181 }
182
183 pub fn to_array(self) -> Option<Vec<Token>> {
185 match self {
186 Token::Array(arr) => Some(arr),
187 _ => None,
188 }
189 }
190
191 pub fn types_check(tokens: &[Token], param_types: &[ParamType]) -> bool {
193 param_types.len() == tokens.len() && {
194 param_types.iter().zip(tokens).all(|(param_type, token)| {
195 token.type_check(param_type)
196 })
197 }
198 }
199}
200
201
202#[cfg(test)]
203mod tests {
204 use {Token, ParamType};
205
206 #[test]
207 fn test_type_check() {
208 fn assert_type_check(tokens: Vec<Token>, param_types: Vec<ParamType>) {
209 assert!(Token::types_check(&tokens, ¶m_types))
210 }
211
212 fn assert_not_type_check(tokens: Vec<Token>, param_types: Vec<ParamType>) {
213 assert!(!Token::types_check(&tokens, ¶m_types))
214 }
215
216 assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(256), ParamType::Bool]);
217 assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(32), ParamType::Bool]);
218
219 assert_not_type_check(vec![Token::Uint(0.into())], vec![ParamType::Uint(32), ParamType::Bool]);
220 assert_not_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(32)]);
221 assert_not_type_check(vec![Token::Bool(false), Token::Uint(0.into())], vec![ParamType::Uint(32), ParamType::Bool]);
222
223 assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamType::FixedBytes(4)]);
224 assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0])], vec![ParamType::FixedBytes(4)]);
225 assert_not_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamType::FixedBytes(3)]);
226
227 assert_type_check(vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])], vec![ParamType::Array(Box::new(ParamType::Bool))]);
228 assert_not_type_check(vec![Token::Array(vec![Token::Bool(false), Token::Uint(0.into())])], vec![ParamType::Array(Box::new(ParamType::Bool))]);
229 assert_not_type_check(vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])], vec![ParamType::Array(Box::new(ParamType::Address))]);
230
231 assert_type_check(vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])], vec![ParamType::FixedArray(Box::new(ParamType::Bool), 2)]);
232 assert_not_type_check(vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])], vec![ParamType::FixedArray(Box::new(ParamType::Bool), 3)]);
233 assert_not_type_check(vec![Token::FixedArray(vec![Token::Bool(false), Token::Uint(0.into())])], vec![ParamType::FixedArray(Box::new(ParamType::Bool), 2)]);
234 assert_not_type_check(vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])], vec![ParamType::FixedArray(Box::new(ParamType::Address), 2)]);
235 }
236}