1use crate::errors::{ErrorKind, Result};
2
3pub const NAME_LENGTH: usize = 13;
4
5pub struct ABIName {
6 pub value: u64,
7}
8
9impl ABIName {
10 pub fn from_str(string: &str) -> Result<ABIName> {
11 let mut value: u64 = 0;
12 let chars = string.as_bytes();
13 let length = chars.len();
14 if length > NAME_LENGTH {
15 return Err(ErrorKind::InvalidABINameLength.into());
16 }
17 let mut i: usize = 0;
19
20 while i < 12 && i < length {
21 let shift: u32 = 64 - 5 * (i + 1) as u32;
22 let symbol = char_to_symbol(chars[i]) & 0x1f;
23 value |= symbol.checked_shl(shift).unwrap_or(0);
24 i += 1;
25 }
26 if i > 12 {
27 value |= char_to_symbol(chars[12]) & 0x0F;
28 }
29 Ok(ABIName { value })
30 }
31
32 pub fn to_str(&self) -> Result<String> {
33 const CHARMAP: [char; 32] = [
34 '.', '1', '2', '3', '4', '5', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
35 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
36 ];
37
38 let mut result: Vec<u8> = Vec::with_capacity(13);
39 for _x in 0..=12 {
40 result.push(b'.');
41 }
42
43 let mut tmp: u64 = self.value;
44 let mut i: usize = 0;
45
46 while i <= 12 {
47 if i == 0 {
48 let c = CHARMAP[(tmp & 0x0f) as usize];
49 result[12 - i] = c as u8;
50 tmp = tmp.checked_shr(4).unwrap_or(0);
51 } else {
52 let c = CHARMAP[(tmp & 0x1f) as usize];
53 result[12 - i] = c as u8;
54 tmp = tmp.checked_shr(5).unwrap_or(0);
55 }
56 i += 1;
57 }
58 i = 12;
59 while i > 0 && result[i] == b'.' {
60 result.pop();
61 i -= 1;
62 }
63
64 Ok(String::from_utf8(result)?)
65 }
66}
67
68fn char_to_symbol(c: u8) -> u64 {
69 if c >= b'a' && c <= b'z' {
70 let v: u8 = (c - b'a') + 6;
71 return v as u64;
72 }
73 if c >= b'1' && c <= b'5' {
74 let v = (c - b'1') + 1;
75 return v as u64;
76 }
77 0
78}
79
80#[cfg(test)]
81mod test {
82 use super::*;
83 #[test]
84 fn name_to_str_test() {
85 let v = ABIName {
86 value: 0x5f2936be6a5cab80,
87 };
88 assert_eq!(v.to_str().unwrap(), "fwonhjnefmps");
89 let value = 0;
90 assert_eq!((ABIName { value }).to_str().unwrap(), ".");
91
92 let value = 3589368903014285312;
93 assert_eq!((ABIName { value }).to_str().unwrap(), "abc");
94
95 let value = 614178399182651392;
96 assert_eq!((ABIName { value }).to_str().unwrap(), "123");
97
98 let value = 108209673814966326;
99 assert_eq!((ABIName { value }).to_str().unwrap(), ".a.b.c.1.2.3a");
100
101 let value = 3589369488740450304;
102 assert_eq!((ABIName { value }).to_str().unwrap(), "abc.123");
103
104 let value = 614251623682315983;
105 assert_eq!((ABIName { value }).to_str().unwrap(), "12345abcdefgj");
106
107 let value = 7754926748989239183;
108 assert_eq!((ABIName { value }).to_str().unwrap(), "hijklmnopqrsj");
109
110 let value = 576460752303423488;
111 assert_eq!((ABIName { value }).to_str().unwrap(), "1");
112
113 let value = 3458764513820540928;
114 assert_eq!((ABIName { value }).to_str().unwrap(), "a");
115 }
116
117 #[test]
118 fn str_to_name_test() {
119 match ABIName::from_str("fwonhjnefmps") {
120 Err(_) => assert!(false),
121 Ok(val) => assert_eq!(val.value, 0x5f2936be6a5cab80),
122 }
123 }
124}