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