rust-bakery / nom

Rust parser combinator framework
MIT License
9.22k stars 794 forks source link

Add support varint #1567

Open ikrivosheev opened 1 year ago

ikrivosheev commented 1 year ago

Hello! Thank you for the great library! I I want to add support for varint.

Link: https://en.wikipedia.org/wiki/Variable-length_quantity

hackaugusto commented 7 months ago

It would be nice to have both variants for little and big endian encodings, and maybe also zig-zag encoding.

hackaugusto commented 7 months ago

If there is any interest, this is the big-ending version w/ overflow handling that I'm using:

#[inline]
pub fn be_varint_u64<I, E: ParseError<I>>(mut i: I) -> IResult<I, u64, E>
where
    I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
{
    let mut result = 0;

    'end: {
        let mut byte;
        for _ in 0..(u64::BITS / 8) {
            (i, byte) = be_u8(i)?;
            result = (result << 7) + u64::from(byte & 0x7F);
            if byte < 0x80 {
                break 'end;
            }
        }
        (i, byte) = be_u8(i)?;
        result = (result << 8) + u64::from(byte);
    }

    Ok((i, result))
}

Because of the BITS associated constants this can't be a generic function, but should be easy enough to write a macro for it.