use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Unsigned};
pub fn encode<N>(mut num: N, buffer: &mut [u8]) -> usize
where
N: PrimInt + Unsigned + FromPrimitive + ToPrimitive,
{
let mask = N::from_u8(0x7F).expect("Anything should be able to represent 7 bits");
for (index, buffer) in buffer.iter_mut().enumerate() {
let byte = (num & mask).to_u8().expect("Mask made sure it fits");
num = num >> 7;
let byte = if !num.is_zero() { byte | 0x80 } else { byte };
*buffer = byte;
if num.is_zero() {
return index + 1;
}
}
panic!("Buffer size too small")
}
pub fn encoded_len<N>(num: N) -> usize
where
N: PrimInt + Unsigned,
{
if num.is_zero() {
1
} else {
(core::mem::size_of::<N>() * 8 - num.leading_zeros() as usize).div_ceil(7)
}
}
#[cfg(test)]
mod test {
use crate::encode;
#[test]
fn e1() {
let mut buf = [0; 1];
encode(0x01_u8, &mut buf);
assert_eq!(buf.as_slice(), &[0x01]);
}
#[test]
fn e7f() {
let mut buf = [0; 1];
encode(0x7f_u8, &mut buf);
assert_eq!(buf.as_slice(), &[0x7f]);
}
#[test]
fn e80() {
let mut buf = [0; 2];
encode(0x80_u8, &mut buf);
assert_eq!(buf.as_slice(), &[0x80, 0x01]);
}
#[test]
fn eff() {
let mut buf = [0; 2];
encode(0xff_u8, &mut buf);
assert_eq!(buf.as_slice(), &[0xff, 0x01]);
}
#[test]
fn e12c() {
let mut buf = [0; 2];
encode(0x12c_u16, &mut buf);
assert_eq!(buf.as_slice(), &[0xac, 0x02]);
}
#[test]
fn e4000() {
let mut buf = [0; 3];
encode(0x4000_u16, &mut buf);
assert_eq!(buf.as_slice(), &[0x80, 0x80, 0x01]);
}
}