use crate::{crc::checksum, error::DecodeError};
pub fn encode(ver: u8, payload: &[u8]) -> String {
let mut d: Vec<u8> = Vec::with_capacity(1 + payload.len() + 2);
d.push(ver);
d.extend_from_slice(payload);
d.extend_from_slice(&checksum(&d));
base32::encode(base32::Alphabet::RFC4648 { padding: false }, &d)
}
pub fn decode(s: &str) -> Result<(u8, Vec<u8>), DecodeError> {
let data = base32::decode(base32::Alphabet::RFC4648 { padding: false }, s);
if let Some(data) = data {
let s_canonical_len = (data.len() * 8 + 4) / 5;
if s.len() != s_canonical_len {
return Err(DecodeError::Invalid);
}
if data.len() < 3 {
return Err(DecodeError::Invalid);
}
let ver = data[0];
let (data_without_crc, crc_actual) = data.split_at(data.len() - 2);
let crc_expect = checksum(data_without_crc);
if crc_actual != crc_expect {
return Err(DecodeError::Invalid);
}
let payload = &data_without_crc[1..];
Ok((ver, payload.to_vec()))
} else {
Err(DecodeError::Invalid)
}
}