eosio_client_api/
abi.rs

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 lc = string.to_ascii_lowercase();
18        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}