1use super::Error;
2
3static CHARACTERS: [u8; 83] = [
4 b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
5 b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V',
6 b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l',
7 b'm', b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x', b'y', b'z', b'#', b'$',
8 b'%', b'*', b'+', b',', b'-', b'.', b':', b';', b'=', b'?', b'@', b'[', b']', b'^', b'_', b'{',
9 b'|', b'}', b'~',
10];
11
12#[inline(always)]
13pub fn encode(value: u32, length: u32) -> String {
14 let mut result = String::new();
15
16 for i in 1..=length {
17 let digit: u32 = (value / u32::pow(83, length - i)) % 83;
18
19 result.push(CHARACTERS[digit as usize] as char);
20 }
21
22 result
23}
24
25#[inline(always)]
26pub fn decode(str: &str) -> Result<usize, Error> {
27 let mut value = 0;
28
29 for byte in str.as_bytes() {
30 let digit: usize = CHARACTERS
31 .iter()
32 .position(|r| r == byte)
33 .ok_or_else(|| Error::InvalidBase83(*byte))?;
34 value = value * 83 + digit;
35 }
36
37 Ok(value)
38}
39
40#[cfg(test)]
41mod tests {
42 use super::{decode, encode};
43
44 #[test]
45 fn encode83() {
46 let str = encode(6869, 2);
47 assert_eq!(str, "~$");
48 }
49
50 #[test]
51 fn decode83() {
52 let v = decode("~$").unwrap();
53 assert_eq!(v, 6869);
54 }
55}