vunsigned-varint 0.1.0

no_std compatible implementation of the unsigned-varint format
use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Unsigned};

/// Encode a unsigned integer into an unsigned varint and write it into the buffer.
/// Returns the number of bytes written.
///
/// # Panics
///
/// Panics if the buffers size is not enough for the encoded value.
/// Make sure you check it with [`encoded_len`]
///
/// # Example
/// ```
/// # use vunsigned_varint::encode;
/// let mut buf= [0; 3];
/// let len = encode(0x4000_u16, &mut buf);
/// assert_eq!(buf.as_slice(), &[0x80, 0x80, 0x01]);
/// assert_eq!(len, 3);
/// ```
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")
}

/// Get the number of bytes needed to encode `num`
///
/// # Example
/// ```
/// # use vunsigned_varint::encoded_len;
/// let len = encoded_len(0x4000_u16);
/// assert_eq!(len, 3);
/// ```
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]);
    }
}