Skip to main content

vunsigned_varint/
encode.rs

1use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Unsigned};
2
3/// Encode a unsigned integer into an unsigned varint and write it into the buffer.
4/// Returns the number of bytes written.
5///
6/// # Panics
7///
8/// Panics if the buffers size is not enough for the encoded value.
9/// Make sure you check it with [`encoded_len`]
10///
11/// # Example
12/// ```
13/// # use vunsigned_varint::encode;
14/// let mut buf= [0; 3];
15/// let len = encode(0x4000_u16, &mut buf);
16/// assert_eq!(buf.as_slice(), &[0x80, 0x80, 0x01]);
17/// assert_eq!(len, 3);
18/// ```
19pub fn encode<N>(mut num: N, buffer: &mut [u8]) -> usize
20where
21    N: PrimInt + Unsigned + FromPrimitive + ToPrimitive,
22{
23    let mask = N::from_u8(0x7F).expect("Anything should be able to represent 7 bits");
24    for (index, buffer) in buffer.iter_mut().enumerate() {
25        let byte = (num & mask).to_u8().expect("Mask made sure it fits");
26        num = num >> 7;
27        let byte = if !num.is_zero() { byte | 0x80 } else { byte };
28        *buffer = byte;
29        if num.is_zero() {
30            return index + 1;
31        }
32    }
33    panic!("Buffer size too small")
34}
35
36/// Get the number of bytes needed to encode `num`
37///
38/// # Example
39/// ```
40/// # use vunsigned_varint::encoded_len;
41/// let len = encoded_len(0x4000_u16);
42/// assert_eq!(len, 3);
43/// ```
44pub fn encoded_len<N>(num: N) -> usize
45where
46    N: PrimInt + Unsigned,
47{
48    if num.is_zero() {
49        1
50    } else {
51        (core::mem::size_of::<N>() * 8 - num.leading_zeros() as usize).div_ceil(7)
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use crate::encode;
58
59    #[test]
60    fn e1() {
61        let mut buf = [0; 1];
62        encode(0x01_u8, &mut buf);
63        assert_eq!(buf.as_slice(), &[0x01]);
64    }
65
66    #[test]
67    fn e7f() {
68        let mut buf = [0; 1];
69        encode(0x7f_u8, &mut buf);
70        assert_eq!(buf.as_slice(), &[0x7f]);
71    }
72
73    #[test]
74    fn e80() {
75        let mut buf = [0; 2];
76        encode(0x80_u8, &mut buf);
77        assert_eq!(buf.as_slice(), &[0x80, 0x01]);
78    }
79
80    #[test]
81    fn eff() {
82        let mut buf = [0; 2];
83        encode(0xff_u8, &mut buf);
84        assert_eq!(buf.as_slice(), &[0xff, 0x01]);
85    }
86
87    #[test]
88    fn e12c() {
89        let mut buf = [0; 2];
90        encode(0x12c_u16, &mut buf);
91        assert_eq!(buf.as_slice(), &[0xac, 0x02]);
92    }
93
94    #[test]
95    fn e4000() {
96        let mut buf = [0; 3];
97        encode(0x4000_u16, &mut buf);
98        assert_eq!(buf.as_slice(), &[0x80, 0x80, 0x01]);
99    }
100}