1use crate::alphabet::Alphabet;
2use num_traits::Zero;
3use num_integer::Integer;
4
5#[derive(Debug, PartialEq, Eq)]
7pub enum DecodeError {
8 InvalidCharacter(char),
10 EmptyInput,
12 InvalidPadding,
14}
15
16impl std::fmt::Display for DecodeError {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 DecodeError::InvalidCharacter(c) => write!(f, "Invalid character in input: {}", c),
20 DecodeError::EmptyInput => write!(f, "Cannot decode empty input"),
21 DecodeError::InvalidPadding => write!(f, "Invalid padding"),
22 }
23 }
24}
25
26impl std::error::Error for DecodeError {}
27
28pub fn encode(data: &[u8], alphabet: &Alphabet) -> String {
29 if data.is_empty() {
30 return String::new();
31 }
32
33 let leading_zeros = data.iter().take_while(|&&b| b == 0).count();
35
36 if leading_zeros == data.len() {
38 return alphabet.encode_digit(0).unwrap().to_string().repeat(data.len());
39 }
40
41 let base = alphabet.base();
42 let mut num = num_bigint::BigUint::from_bytes_be(&data[leading_zeros..]);
43
44 let max_digits = ((data.len() - leading_zeros) * 8 * 1000) / (base as f64).log2() as usize / 1000 + 1;
46 let mut result = Vec::with_capacity(max_digits + leading_zeros);
47
48 let base_big = num_bigint::BigUint::from(base);
49
50 while !num.is_zero() {
51 let (quotient, remainder) = num.div_rem(&base_big);
52 let digit = remainder.to_u64_digits();
53 let digit_val = if digit.is_empty() { 0 } else { digit[0] as usize };
54 result.push(alphabet.encode_digit(digit_val).unwrap());
55 num = quotient;
56 }
57
58 for _ in 0..leading_zeros {
60 result.push(alphabet.encode_digit(0).unwrap());
61 }
62
63 result.reverse();
64 result.into_iter().collect()
65}
66
67pub fn decode(encoded: &str, alphabet: &Alphabet) -> Result<Vec<u8>, DecodeError> {
68 if encoded.is_empty() {
69 return Err(DecodeError::EmptyInput);
70 }
71
72 let base = alphabet.base();
73 let mut num = num_bigint::BigUint::from(0u8);
74 let base_big = num_bigint::BigUint::from(base);
75
76 let chars: Vec<char> = encoded.chars().collect();
78 let mut leading_zeros = 0;
79
80 for &c in &chars {
82 let digit = alphabet.decode_char(c)
83 .ok_or(DecodeError::InvalidCharacter(c))?;
84
85 if num.is_zero() && digit == 0 {
86 leading_zeros += 1;
87 } else {
88 num *= &base_big;
89 num += num_bigint::BigUint::from(digit);
90 }
91 }
92
93 if num.is_zero() && leading_zeros > 0 {
95 return Ok(vec![0u8; leading_zeros]);
96 }
97
98 let bytes = num.to_bytes_be();
99
100 let mut result = Vec::with_capacity(leading_zeros + bytes.len());
102 result.resize(leading_zeros, 0u8);
103 result.extend_from_slice(&bytes);
104
105 Ok(result)
106}