1use std::borrow::Borrow;
5use std::fmt;
6
7use anyhow::Result;
8use frc42_dispatch::hash::MethodResolver;
9use serde::de::SeqAccess;
10
11use crate::abi::blake2b::Blake2bHasher;
12use crate::error::{self, Error};
13
14mod blake2b;
15
16pub fn pascal_case_split(s: &str) -> Vec<&str> {
19 let mut split = vec![];
20 let mut chars = s.char_indices();
22
23 let mut beg = match chars.next() {
25 Some((i, c)) if c.is_uppercase() => i,
26 _ => return split,
27 };
28
29 for (i, c) in chars {
31 if c.is_uppercase() || c.is_numeric() {
32 split.push(&s[beg..i]);
33 beg = i;
34 }
35 }
36
37 split.push(&s[beg..s.len()]);
40 split
41}
42
43#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
46pub struct Abi {
47 pub constructor: Option<Method>,
48 pub set_up: Option<Method>,
49 pub methods: Vec<Method>,
50}
51
52impl Abi {
53 pub fn constructor(&self) -> Option<&Method> {
55 self.constructor.as_ref()
56 }
57
58 pub fn set_up(&self) -> Option<&Method> {
60 self.set_up.as_ref()
61 }
62
63 pub fn methods(&self) -> &[Method] {
64 &self.methods
65 }
66}
67
68impl serde::Serialize for Abi {
71 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
72 where
73 S: serde::Serializer,
74 {
75 let mut s = vec![];
76 if let Some(constructor) = &self.constructor {
77 s.push(vec![constructor.name()]);
78 }
79 if let Some(constructor) = &self.set_up {
80 s.push(vec![constructor.name()]);
81 }
82 let methods = self.methods.iter().map(|m| vec![m.name()]);
83 s.extend(methods);
84
85 serde::Serialize::serialize(&vec![s], serializer)
86 }
87}
88
89impl<'de> serde::Deserialize<'de> for Abi {
92 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
93 where
94 D: serde::Deserializer<'de>,
95 {
96 struct AbiVisitor;
97
98 impl<'de> serde::de::Visitor<'de> for AbiVisitor {
99 type Value = Abi;
100
101 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
102 formatter.write_str("Abi")
103 }
104
105 fn visit_seq<A>(self, mut seq: A) -> std::result::Result<Self::Value, A::Error>
106 where
107 A: SeqAccess<'de>,
108 {
109 let mut constructor = None;
110 let mut set_up = None;
111
112 let mut methods = vec![];
113 let seq_methods = seq
114 .next_element::<Vec<Method>>()?
115 .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
116
117 for method in seq_methods {
120 match (constructor.is_some(), set_up.is_some(), &method.r#type()) {
121 (false, _, MethodType::Constructor) => constructor = Some(method),
122 (_, false, MethodType::Setup) => set_up = Some(method),
123 (true, _, MethodType::Constructor) | (_, true, MethodType::Setup) => {
124 return Err(serde::de::Error::custom(
125 "Abi can only have one Constructor and one SetUp function",
126 ))
127 }
128 (_, _, _) => methods.push(method),
129 }
130 }
131
132 Ok(Abi {
133 constructor,
134 set_up,
135 methods,
136 })
137 }
138 }
139 deserializer.deserialize_seq(AbiVisitor)
140 }
141}
142
143pub type MethodNum = u64;
145
146#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
148pub struct Method {
149 number: MethodNum,
150 name: String,
151 r#type: MethodType,
152}
153
154impl fmt::Display for Method {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "{}", self.name())
157 }
158}
159
160impl Borrow<u64> for Method {
161 fn borrow(&self) -> &u64 {
162 &self.number
163 }
164}
165
166#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
168pub enum MethodType {
169 Constructor,
170 Entrypoint,
171 Setup,
172 Test,
173 TestFail,
174}
175
176impl Method {
177 pub fn number(&self) -> MethodNum {
179 self.number
180 }
181
182 pub fn name(&self) -> &str {
184 &self.name
185 }
186
187 pub fn r#type(&self) -> MethodType {
189 self.r#type
190 }
191}
192
193impl Method {
194 pub fn new_from_name(name: &str) -> Result<Self, Error> {
195 let number = derive_method_num(name)?;
196 let name = name.to_string();
197
198 let split = pascal_case_split(&name);
199 let r#type = match &split[..] {
200 ["Constructor", ..] => MethodType::Constructor,
201 ["Setup", ..] => MethodType::Setup,
202 ["Test", "Fail", ..] => MethodType::TestFail,
203 ["Test", ..] => MethodType::Test,
204 _ => MethodType::Entrypoint,
205 };
206
207 Ok(Method {
208 number,
209 name,
210 r#type,
211 })
212 }
213}
214
215impl<'de> serde::de::Deserialize<'de> for Method {
218 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
219 where
220 D: serde::de::Deserializer<'de>,
221 {
222 struct MethodVisitor;
223
224 impl<'de> serde::de::Visitor<'de> for MethodVisitor {
225 type Value = Method;
226
227 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
228 formatter.write_str("Method")
229 }
230
231 fn visit_seq<A>(self, mut seq: A) -> std::result::Result<Self::Value, A::Error>
232 where
233 A: SeqAccess<'de>,
234 {
235 let name = seq
236 .next_element::<String>()?
237 .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
238
239 Self::Value::new_from_name(&name).map_err(|_| {
240 serde::de::Error::custom(format!("Couldn't deserialize method: {}", &name))
241 })
242 }
243 }
244
245 deserializer.deserialize_seq(MethodVisitor)
246 }
247}
248
249pub fn derive_method_num(name: &str) -> Result<MethodNum, error::Error> {
252 let resolver = MethodResolver::new(Blake2bHasher {});
253
254 match resolver.method_number(name) {
255 Ok(method_number) => Ok(method_number),
256 Err(err) => Err(Error::MethodNumberGeneration {
257 name: name.into(),
258 source: err.into(),
259 }),
260 }
261}
262
263#[cfg(test)]
264mod test {
265 use super::{derive_method_num, pascal_case_split};
266 use crate::abi::{Abi, Method, MethodType};
267
268 #[test]
269 fn test_method_derivation() {
270 let method_name = String::from("TestTransfer");
271
272 match derive_method_num(&method_name) {
273 Ok(method_num) => {
274 assert_eq!(method_num, 3760293944);
275 }
276 Err(_) => {
277 panic!("derive_method_num failed for {}", method_name);
278 }
279 }
280 }
281
282 #[test]
283 fn test_fail_method_derivation() {
284 let method_name = String::from("test_transfer");
286
287 match derive_method_num(&method_name) {
288 Ok(_) => {
289 panic!("derive_method_num success for {}", method_name);
290 }
291 Err(err) => {
292 assert_eq!(
293 format!("Could not generate method number for `{}`", method_name),
294 err.to_string()
295 )
296 }
297 }
298 }
299
300 #[test]
301 fn test_pascal_case() {
302 assert_eq!(pascal_case_split("TestOne"), vec!["Test", "One"]);
303 assert_eq!(
304 pascal_case_split("TestFailWithMultipleWords"),
305 vec!["Test", "Fail", "With", "Multiple", "Words"]
306 );
307 assert_eq!(pascal_case_split("Test1"), vec!["Test", "1"]);
308 assert_eq!(pascal_case_split("testOne"), Vec::<&str>::new());
309 }
310
311 #[test]
312 fn test_tuple_serde() {
313 let test_transfer_name = String::from("TestTransfer");
315 let test_transfer_fail_name = String::from("TestFailTransfer");
316
317 let abi = Abi {
318 constructor: None,
319 set_up: None,
320 methods: vec![
321 Method {
322 number: derive_method_num(&test_transfer_name).unwrap(),
323 name: test_transfer_name,
324 r#type: MethodType::Test,
325 },
326 Method {
327 number: derive_method_num(&test_transfer_fail_name).unwrap(),
328 name: test_transfer_fail_name,
329 r#type: MethodType::TestFail,
330 },
331 ],
332 };
333
334 let serialized_abi: Vec<u8> = vec![
335 129, 130, 129, 108, 84, 101, 115, 116, 84, 114, 97, 110, 115, 102, 101, 114, 129, 112,
336 84, 101, 115, 116, 70, 97, 105, 108, 84, 114, 97, 110, 115, 102, 101, 114,
337 ];
338
339 let abi_vec = crate::to_vec(&abi).unwrap();
341 assert_eq!(abi_vec, serialized_abi);
342
343 let deserialized_abi: Abi = crate::from_slice(&serialized_abi).unwrap();
345 assert_eq!(deserialized_abi, abi);
346 }
347
348 #[test]
349 fn test_fail_tuple_serde() {
350 let test_transfer_name = String::from("TestTransfer");
352 let test_transfer_fail_name = String::from("testFailTransfer");
353
354 let abi = Abi {
355 constructor: None,
356 set_up: None,
357 methods: vec![
358 Method {
359 number: derive_method_num(&test_transfer_name).unwrap(),
360 name: test_transfer_name,
361 r#type: MethodType::Test,
362 },
363 Method {
364 number: 3280706483,
365 name: test_transfer_fail_name,
366 r#type: MethodType::TestFail,
367 },
368 ],
369 };
370
371 let serialized_abi: Vec<u8> = vec![
372 129, 130, 129, 108, 84, 101, 115, 116, 84, 114, 97, 110, 115, 102, 101, 114, 129, 112,
373 116, 101, 115, 116, 70, 97, 105, 108, 84, 114, 97, 110, 115, 102, 101, 114,
374 ];
375
376 let abi_vec = crate::to_vec(&abi).unwrap();
378 assert_eq!(abi_vec, serialized_abi);
379
380 match crate::from_slice::<Abi>(&serialized_abi) {
382 Ok(_) => panic!("Deserialization should fail"),
383 Err(err) => {
384 assert!(err
385 .to_string()
386 .contains("Couldn't deserialize method: testFailTransfer"));
387 }
388 };
389 }
390
391 #[test]
392 fn test_method_constructor() {
393 assert_eq!(
394 Method::new_from_name("TestOne").unwrap().r#type,
395 MethodType::Test
396 );
397 assert_eq!(
398 Method::new_from_name("TestFailOne").unwrap().r#type,
399 MethodType::TestFail
400 );
401 assert_eq!(
402 Method::new_from_name("Constructor").unwrap().r#type,
403 MethodType::Constructor
404 );
405 assert_eq!(
406 Method::new_from_name("Setup").unwrap().r#type,
407 MethodType::Setup
408 );
409
410 assert!(Method::new_from_name("testOne").is_err());
411 assert!(Method::new_from_name("").is_err());
412 }
413}