const ALPHABET: &[u8; 58] =
b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const DECODE: [u8; 128] = {
let mut table = [255u8; 128];
let mut i = 0;
while i < 58 {
table[ALPHABET[i] as usize] = i as u8;
i += 1;
}
table
};
pub fn encode(input: &[u8]) -> String {
if input.is_empty() {
return String::new();
}
let leading_zeros = input.iter().take_while(|&&b| b == 0).count();
let mut digits: Vec<u8> = Vec::with_capacity(input.len() * 2);
for &byte in input {
let mut carry = byte as u32;
for d in &mut digits {
carry += (*d as u32) << 8;
*d = (carry % 58) as u8;
carry /= 58;
}
while carry > 0 {
digits.push((carry % 58) as u8);
carry /= 58;
}
}
let mut result = String::with_capacity(leading_zeros + digits.len());
for _ in 0..leading_zeros {
result.push('1');
}
for &d in digits.iter().rev() {
result.push(ALPHABET[d as usize] as char);
}
result
}
pub fn decode(input: &str) -> Option<Vec<u8>> {
if input.is_empty() {
return Some(Vec::new());
}
let leading_ones = input.chars().take_while(|&c| c == '1').count();
let mut bytes: Vec<u8> = Vec::with_capacity(input.len());
for c in input.chars() {
let c = c as usize;
if c >= 128 {
return None;
}
let val = DECODE[c];
if val == 255 {
return None;
}
let mut carry = val as u32;
for b in &mut bytes {
carry += (*b as u32) * 58;
*b = (carry & 0xFF) as u8;
carry >>= 8;
}
while carry > 0 {
bytes.push((carry & 0xFF) as u8);
carry >>= 8;
}
}
let mut result = vec![0; leading_ones];
result.extend(bytes.iter().rev());
Some(result)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encode_empty() {
assert_eq!(encode(b""), "");
}
#[test]
fn encode_hello() {
assert_eq!(encode(b"Hello World"), "JxF12TrwUP45BMd");
}
#[test]
fn roundtrip() {
let data = b"tesseras-paste test data";
let encoded = encode(data);
let decoded = decode(&encoded).unwrap();
assert_eq!(decoded, data);
}
#[test]
fn roundtrip_binary() {
let data: Vec<u8> = (0..=255).collect();
let encoded = encode(&data);
let decoded = decode(&encoded).unwrap();
assert_eq!(decoded, data);
}
#[test]
fn leading_zeros() {
let data = [0, 0, 0, 1, 2, 3];
let encoded = encode(&data);
assert!(encoded.starts_with("111"));
let decoded = decode(&encoded).unwrap();
assert_eq!(decoded, data);
}
#[test]
fn decode_invalid_char() {
assert!(decode("invalid0char").is_none());
}
#[test]
fn decode_empty() {
assert_eq!(decode("").unwrap(), Vec::<u8>::new());
}
#[test]
fn known_vector() {
let hash: [u8; 32] = {
use tesseras_dht::sha2::{Digest, Sha256};
let mut h = Sha256::new();
h.update(b"test");
h.finalize().into()
};
let encoded = encode(&hash);
let decoded = decode(&encoded).unwrap();
assert_eq!(decoded, hash);
}
}