base_d/
encoding.rs

1use crate::alphabet::Alphabet;
2use num_traits::Zero;
3
4/// Errors that can occur during decoding.
5#[derive(Debug, PartialEq, Eq)]
6pub enum DecodeError {
7    /// The input contains a character not in the alphabet
8    InvalidCharacter(char),
9    /// The input string is empty
10    EmptyInput,
11    /// The padding is malformed or incorrect
12    InvalidPadding,
13}
14
15impl std::fmt::Display for DecodeError {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            DecodeError::InvalidCharacter(c) => write!(f, "Invalid character in input: {}", c),
19            DecodeError::EmptyInput => write!(f, "Cannot decode empty input"),
20            DecodeError::InvalidPadding => write!(f, "Invalid padding"),
21        }
22    }
23}
24
25impl std::error::Error for DecodeError {}
26
27pub fn encode(data: &[u8], alphabet: &Alphabet) -> String {
28    if data.is_empty() {
29        return String::new();
30    }
31    
32    // Count leading zeros
33    let leading_zeros = data.iter().take_while(|&&b| b == 0).count();
34    
35    // If all zeros, just return the zero character repeated
36    if leading_zeros == data.len() {
37        return alphabet.encode_digit(0).unwrap().to_string().repeat(data.len());
38    }
39    
40    let base = alphabet.base();
41    let mut num = num_bigint::BigUint::from_bytes_be(&data[leading_zeros..]);
42    let mut result = Vec::new();
43    let base_big = num_bigint::BigUint::from(base);
44    
45    while !num.is_zero() {
46        let remainder = &num % &base_big;
47        let digit = remainder.to_u64_digits();
48        let digit_val = if digit.is_empty() { 0 } else { digit[0] as usize };
49        result.push(alphabet.encode_digit(digit_val).unwrap());
50        num /= &base_big;
51    }
52    
53    // Add leading zeros
54    for _ in 0..leading_zeros {
55        result.push(alphabet.encode_digit(0).unwrap());
56    }
57    
58    result.reverse();
59    result.into_iter().collect()
60}
61
62pub fn decode(encoded: &str, alphabet: &Alphabet) -> Result<Vec<u8>, DecodeError> {
63    if encoded.is_empty() {
64        return Err(DecodeError::EmptyInput);
65    }
66    
67    let base = alphabet.base();
68    let mut num = num_bigint::BigUint::from(0u8);
69    let base_big = num_bigint::BigUint::from(base);
70    
71    let chars: Vec<char> = encoded.chars().collect();
72    let mut leading_zeros = 0;
73    
74    for &c in &chars {
75        let digit = alphabet.decode_char(c)
76            .ok_or(DecodeError::InvalidCharacter(c))?;
77        
78        if num.is_zero() && digit == 0 {
79            leading_zeros += 1;
80        } else {
81            num = num * &base_big + num_bigint::BigUint::from(digit);
82        }
83    }
84    
85    let bytes = num.to_bytes_be();
86    
87    if num.is_zero() && leading_zeros > 0 {
88        return Ok(vec![0u8; leading_zeros]);
89    }
90    
91    // Add leading zero bytes
92    let mut result = vec![0u8; leading_zeros];
93    result.extend_from_slice(&bytes);
94    
95    Ok(result)
96}