pub mod utils;
pub fn encode(buf: &[u8], base: u8) -> Vec<u8> {
let mut num = utils::from_bytes_be(buf);
let mut digits = Vec::new();
while num.len() > 1 || num[0] != 0 {
digits.push(utils::div_rem(&mut num, base as utils::DoubleDigit) as u8);
}
let zeros = buf.iter().take_while(|&x| *x == 0).count();
digits.resize(digits.len() + zeros, 0);
digits.reverse();
digits
}
pub fn decode(buf: &[u8], base: u8) -> Option<Vec<u8>> {
let mut num = vec![0];
let zeros = buf.iter().take_while(|&x| *x == 0).count();
if zeros == buf.len() {
return Some(vec![0; zeros]);
}
for &digit in buf {
if digit >= base {
return None;
}
utils::mul(&mut num, base as utils::DoubleDigit);
utils::add(&mut num, digit.into());
}
let mut bytes = vec![0; zeros];
bytes.append(&mut utils::to_bytes_be(&num));
Some(bytes)
}
pub fn to_string(buf: &[u8], base: u8, chars: &[u8]) -> Option<String> {
encode(buf, base)
.iter()
.map(|&x| chars.get(x as usize).map(|&c| c as char))
.collect()
}
pub fn from_str(string: &str, base: u8, chars: &[u8]) -> Option<Vec<u8>> {
decode(
&string
.chars()
.map(|c| chars.iter().position(|&a| a == c as u8).map(|x| x as u8))
.collect::<Option<Vec<_>>>()?,
base,
)
}