umsh_ulcp/
uint.rs

1//! Minimal-width unsigned little-endian integers. Zero occupies one octet.
2pub use crate::sint::Error;
3pub const MAX_LEN: usize = 4;
4
5pub const fn encoded_len(value: u32) -> usize {
6    if value == 0 {
7        1
8    } else {
9        ((32 - value.leading_zeros()) as usize).div_ceil(8)
10    }
11}
12
13pub fn encode(value: u32, out: &mut [u8]) -> Result<usize, Error> {
14    let len = encoded_len(value);
15    out.get_mut(..len)
16        .ok_or(Error::BufferTooSmall)?
17        .copy_from_slice(&value.to_le_bytes()[..len]);
18    Ok(len)
19}
20
21pub fn decode(input: &[u8]) -> Result<u32, Error> {
22    if input.is_empty() || input.len() > MAX_LEN {
23        return Err(Error::Malformed);
24    }
25    let mut bytes = [0; MAX_LEN];
26    bytes[..input.len()].copy_from_slice(input);
27    Ok(u32::from_le_bytes(bytes))
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    #[test]
34    fn boundaries_padding_and_invalid_lengths() {
35        for (value, len) in [
36            (0, 1),
37            (255, 1),
38            (256, 2),
39            (65535, 2),
40            (65536, 3),
41            (16777215, 3),
42            (16777216, 4),
43            (u32::MAX, 4),
44        ] {
45            let mut bytes = [0; 4];
46            assert_eq!(encode(value, &mut bytes), Ok(len));
47            assert_eq!(decode(&bytes[..len]), Ok(value));
48            assert_eq!(decode(&bytes), Ok(value));
49        }
50        assert_eq!(decode(&[]), Err(Error::Malformed));
51        assert_eq!(decode(&[0; 5]), Err(Error::Malformed));
52        assert_eq!(encode(256, &mut [0]), Err(Error::BufferTooSmall));
53    }
54}