pub const ALPHABET: &str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub enum Error {
UnknownSymbol(usize),
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match self {
Error::UnknownSymbol(idx) => write!(f, "Unknown symbol at byte index {}", idx),
}
}
}
impl ::std::error::Error for Error {}
pub type Result<T> = ::std::result::Result<T, Error>;
pub fn encode(input: &[u8]) -> String {
String::from_utf8(base_encode(ALPHABET, input)).unwrap()
}
pub fn decode(input: &str) -> Result<Vec<u8>> {
base_decode(ALPHABET, input.as_bytes())
}
#[cfg(test)]
mod tests {
fn encode(input: &[u8], expected: &str) {
let encoded = super::encode(input);
assert_eq!(encoded, expected);
}
fn decode(expected: &[u8], input: &str) {
let decoded = super::decode(input).unwrap();
assert_eq!(decoded.as_slice(), expected);
}
#[test]
fn test_vector_1() {
encode(b"\0\0\0\0", "11111");
decode(b"\0\0\0\0", "11111");
}
#[test]
fn test_vector_2() {
encode(b"This is awesome!", "BRY7dK2V98Sgi7CFWiZbap");
decode(b"This is awesome!", "BRY7dK2V98Sgi7CFWiZbap");
}
#[test]
fn test_vector_3() {
encode(b"Hello World...", "TcgsE5dzphUWfjcb9i5");
decode(b"Hello World...", "TcgsE5dzphUWfjcb9i5");
}
#[test]
fn test_vector_4() {
encode(b"\0abc", "1ZiCa");
decode(b"\0abc", "1ZiCa");
}
#[test]
fn test_vector_5() {
encode(b"\0\0abc", "11ZiCa");
decode(b"\0\0abc", "11ZiCa");
}
#[test]
fn test_vector_6() {
encode(b"\0\0\0abc", "111ZiCa");
decode(b"\0\0\0abc", "111ZiCa");
}
#[test]
fn test_vector_7() {
encode(b"\0\0\0\0abc", "1111ZiCa");
decode(b"\0\0\0\0abc", "1111ZiCa");
}
#[test]
fn test_vector_8() {
encode(
b"abcdefghijklmnopqrstuvwxyz",
"3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f",
);
decode(
b"abcdefghijklmnopqrstuvwxyz",
"3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f",
);
}
}
fn base_encode(alphabet_s: &str, input: &[u8]) -> Vec<u8> {
let alphabet = alphabet_s.as_bytes();
let base = alphabet.len() as u32;
let mut digits = vec![0u8];
for input in input.iter() {
let mut carry = *input as u32;
for digit in digits.iter_mut() {
carry += (*digit as u32) << 8;
*digit = (carry % base) as u8;
carry /= base;
}
while carry > 0 {
digits.push((carry % base) as u8);
carry /= base;
}
}
let mut string = vec![];
let mut k = 0;
while (k < input.len()) && (input[k] == 0) {
string.push(alphabet[0]);
k += 1;
}
for digit in digits.iter().rev() {
string.push(alphabet[*digit as usize]);
}
string
}
fn base_decode(alphabet_s: &str, input: &[u8]) -> Result<Vec<u8>> {
let alphabet = alphabet_s.as_bytes();
let base = alphabet.len() as u32;
let mut bytes: Vec<u8> = vec![0];
let zcount = input.iter().take_while(|x| **x == alphabet[0]).count();
for (i, input) in input[zcount..].iter().enumerate() {
let value = match alphabet.iter().position(|&x| x == *input) {
Some(idx) => idx,
None => return Err(Error::UnknownSymbol(i)),
};
let mut carry = value as u32;
for byte in bytes.iter_mut() {
carry += (*byte as u32) * base;
*byte = carry as u8;
carry >>= 8;
}
while carry > 0 {
bytes.push(carry as u8);
carry >>= 8;
}
}
let leading_zeros = bytes.iter().rev().take_while(|x| **x == 0).count();
if zcount > leading_zeros {
let unpad = if leading_zeros > 0 {
leading_zeros + 1
} else {
0
};
bytes.resize(bytes.len() + zcount - unpad, 0);
}
bytes.reverse();
Ok(bytes)
}