vunsigned_varint/
decode.rs1use num_traits::{CheckedShl, FromPrimitive, PrimInt, Unsigned};
2use thiserror::Error;
3
4pub fn decode<N>(buffer: &[u8]) -> Result<(N, usize), Error>
20where
21 N: PrimInt + Unsigned + FromPrimitive + CheckedShl,
22{
23 let mut num = N::zero();
24 if buffer.is_empty() {
25 return Err(Error::EmptyBuffer);
26 }
27 let byte_num = (core::mem::size_of::<N>() * 8).div_ceil(7);
28 for (i, byte) in buffer.iter().take(byte_num).copied().enumerate() {
29 num = num
30 | N::from_u8(byte & 0x7F)
31 .expect("Anything should be able to represent a byte")
32 .checked_shl(7 * i as u32)
33 .ok_or(Error::Overflow)?;
34 if byte & 0x80 == 0 {
35 return Ok((num, i + 1));
36 }
37 }
38 Err(Error::UnexpectedEof)
39}
40
41#[derive(Debug, Error, PartialEq, Eq, Hash, Clone, Copy)]
43pub enum Error {
44 #[error("buffer is empty")]
46 EmptyBuffer,
47 #[error("unexpected end of buffer before end of varint")]
49 UnexpectedEof,
50 #[error("decoded value does not fit into the target integer type")]
52 Overflow,
53}
54
55impl Error {
56 #[cfg(feature = "std")]
58 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
59 #[must_use]
60 pub fn into_io_error(self) -> std::io::Error {
61 self.into()
62 }
63}
64
65#[cfg(feature = "std")]
66#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
67impl From<Error> for std::io::Error {
68 fn from(error: Error) -> Self {
69 let kind = match error {
70 Error::EmptyBuffer | Error::UnexpectedEof => std::io::ErrorKind::UnexpectedEof,
71 Error::Overflow => std::io::ErrorKind::InvalidData,
72 };
73 Self::new(kind, error)
74 }
75}
76
77#[cfg(test)]
78mod test {
79 use crate::decode;
80
81 #[test]
82 fn d1() {
83 let num: u8 = decode(&[0x01]).unwrap().0;
84 assert_eq!(num, 0x01_u8);
85 }
86
87 #[test]
88 fn d7f() {
89 let num: u8 = decode(&[0x7f]).unwrap().0;
90 assert_eq!(num, 0x7f_u8);
91 }
92
93 #[test]
94 fn d80() {
95 let num: u8 = decode(&[0x80, 0x01]).unwrap().0;
96 assert_eq!(num, 0x80_u8);
97 }
98
99 #[test]
100 fn dff() {
101 let num: u8 = decode(&[0xff, 0x01]).unwrap().0;
102 assert_eq!(num, 0xff_u8);
103 }
104
105 #[test]
106 fn d12c() {
107 let num: u16 = decode(&[0xac, 0x02]).unwrap().0;
108 assert_eq!(num, 0x12c_u16);
109 }
110
111 #[test]
112 fn d4000() {
113 let num: u16 = decode(&[0x80, 0x80, 0x01]).unwrap().0;
114 assert_eq!(num, 0x4000_u16);
115 }
116}