From 4b2feb70398e76ceec5395e7f1d4ca81578a3f9d Mon Sep 17 00:00:00 2001 From: Ivan Krivosheev Date: Fri, 28 Oct 2022 13:07:41 +0300 Subject: [PATCH] issues-1567 Add varint parsing --- src/number/streaming.rs | 73 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/number/streaming.rs b/src/number/streaming.rs index 0fa512586..b4e8ae8b9 100644 --- a/src/number/streaming.rs +++ b/src/number/streaming.rs @@ -1538,6 +1538,79 @@ where } } +#[inline] +#[doc(hidden)] +pub fn varint, R>(i: I) -> IResult +where + I: Slice> + InputIter + InputLength + Copy, + R: std::ops::AddAssign + std::ops::Shl + Default + From, +{ + let mut result = R::default(); + let mut ofs: usize = 0; + let mut remainder = i; + loop { + let (i, byte) = le_u8(remainder)?; + result += (>::from(byte & 0x7F)) << ofs; + if byte < 0x80 { + return Ok((i, result)); + } + remainder = i; + ofs += 7; + } +} + +/// Recognizes a variable-length quantity. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::varint_u128; +/// +/// let parser = |s| { +/// varint_u128(s) +/// }; +/// +/// assert_eq!(parser(&[0x7F][..]), Ok((b"", 127))); +/// assert_eq!(parser(&[0x80][..]), Ok((b"", 128))); +/// assert_eq!(parser(&[0x20, 0x00][..]), Ok((b"", 8192))); +/// assert_eq!(parser(&[0x20, 0x00, 0x00][..]), Ok((b"", 2_097_152))); +/// ``` +#[inline] +pub fn varint_u64>(i: I) -> IResult +where + I: Slice> + InputIter + InputLength + Copy, +{ + varint::(i) +} + +/// Recognizes a variable-length quantity. +/// +/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::number::streaming::varint_u128; +/// +/// let parser = |s| { +/// varint_u128(s) +/// }; +/// +/// assert_eq!(parser(&[0x7F][..]), Ok((b"", 127))); +/// assert_eq!(parser(&[0x80][..]), Ok((b"", 128))); +/// assert_eq!(parser(&[0x20, 0x00][..]), Ok((b"", 8192))); +/// assert_eq!(parser(&[0x20, 0x00, 0x00][..]), Ok((b"", 2_097_152))); +/// ``` +#[inline] +pub fn varint_u128>(i: I) -> IResult +where + I: Slice> + InputIter + InputLength + Copy, +{ + varint::(i) +} + #[cfg(test)] mod tests { use super::*;