1#![no_std]
6
7use core::convert::TryInto;
8use core::u32;
9use nom::bytes::complete::take;
10use nom::error::{ErrorKind, ParseError};
11use nom::Err::*;
12use nom::Needed::Unknown;
13
14pub fn take_varint<'a, E>(i: &'a [u8]) -> nom::IResult<&'a [u8], usize, E>
22where
23 E: ParseError<&'a [u8]>,
24{
25 let mut res: usize = 0;
26 let mut count: usize = 0;
27 let mut remainder = i;
28 loop {
29 let byte = match take::<usize, &[u8], ()>(1)(remainder) {
30 Ok((rest, bytes)) => {
31 remainder = rest;
32 bytes[0]
33 }
34 Err(_) => return Err(Incomplete(Unknown)),
35 };
36 res += ((byte as usize) & 127)
37 .checked_shl((count * 7).try_into().unwrap_or(u32::MAX))
38 .ok_or_else(|| Error(E::from_error_kind(remainder, ErrorKind::MapOpt)))?;
39 count += 1;
40 if (byte >> 7) == 0 {
41 return Ok((remainder, res));
42 }
43 }
44}
45
46#[cfg(test)]
47mod test {
48 #[test]
49 fn parse_varint_simple() {
50 assert_eq!(
51 super::take_varint::<()>(&[0x0b, 0x01, 0x02, 0x03]),
52 Ok((b"\x01\x02\x03" as &[u8], 11))
53 );
54 }
55
56 #[test]
57 fn parse_varint_twobyte() {
58 assert_eq!(
59 super::take_varint::<()>(&[0x84, 0x02, 0x04, 0x05, 0x06]),
60 Ok((b"\x04\x05\x06" as &[u8], 260))
61 );
62 }
63}