use crate::constants::ALPHABET;
pub fn decode(input: &str) -> Result<Vec<u8>, String> {
if input.is_empty() {
return Ok(Vec::new());
}
if !input.len().is_multiple_of(4) {
return Err("Invalid input length".to_string());
}
let input_bytes = input.as_bytes();
let mut output = Vec::with_capacity(input.len() * 3 / 4);
for chunk in input_bytes.chunks(4) {
let c0 = chunk[0];
let c1 = chunk[1];
let c2 = chunk[2];
let c3 = chunk[3];
if c2 == b'=' && c3 == b'=' {
let idx0 = decode_char(c0)?;
let idx1 = decode_char(c1)?;
let val = (idx0 as u32) * 67 + (idx1 as u32);
output.push((val & 0xFF) as u8);
} else if c3 == b'=' {
let idx0 = decode_char(c0)?;
let idx1 = decode_char(c1)?;
let idx2 = decode_char(c2)?;
let val = (idx0 as u32) * 67u32.pow(2) + (idx1 as u32) * 67 + (idx2 as u32);
output.push(((val >> 8) & 0xFF) as u8);
output.push((val & 0xFF) as u8);
} else {
let idx0 = decode_char(c0)?;
let idx1 = decode_char(c1)?;
let idx2 = decode_char(c2)?;
let idx3 = decode_char(c3)?;
let val = (idx0 as u32) * 67u32.pow(3)
+ (idx1 as u32) * 67u32.pow(2)
+ (idx2 as u32) * 67
+ (idx3 as u32);
output.push(((val >> 16) & 0xFF) as u8);
output.push(((val >> 8) & 0xFF) as u8);
output.push((val & 0xFF) as u8);
}
}
Ok(output)
}
fn decode_char(c: u8) -> Result<u8, String> {
ALPHABET
.iter()
.position(|&x| x == c)
.map(|i| i as u8)
.ok_or_else(|| format!("Invalid character: {}", c as char))
}