use nom::{IResult, number::complete::be_u8};
#[must_use]
#[allow(clippy::cast_possible_truncation)]
pub fn encode_varint(i: u64) -> Vec<u8> {
let mut buf = Vec::with_capacity(varint_len(i));
encode_varint_into(i, &mut buf);
buf
}
#[must_use]
pub const fn varint_len(i: u64) -> usize {
if i < 240 {
1
} else {
let mut len = 2;
let mut value = (i - 240) >> 4;
while value >= 128 {
len += 1;
value = (value - 128) >> 7;
}
len
}
}
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn encode_varint_into(i: u64, buf: &mut Vec<u8>) {
buf.reserve(varint_len(i));
if i < 240 {
buf.push(i as u8);
} else {
buf.push((i | 0b1111_0000) as u8);
let mut i = (i - 240) >> 4;
while i >= 128 {
buf.push((i | 0b1000_0000) as u8);
i = (i - 128) >> 7;
}
buf.push(i as u8);
}
}
pub fn decode_varint(input: &[u8]) -> IResult<&[u8], u64> {
let (mut input, first_byte) = be_u8(input)?;
if first_byte < 240 {
return Ok((input, u64::from(first_byte)));
}
let mut value = u64::from(first_byte);
let mut shift = 4;
loop {
let (new_input, next_byte) = be_u8(input)?;
input = new_input;
value += u64::from(next_byte) << shift;
shift += 7;
if next_byte < 128 {
break;
}
}
Ok((input, value))
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used, clippy::unreadable_literal)]
mod tests {
use super::*;
#[test]
fn test_decode_varint() {
assert_eq!(decode_varint(&[0x00]), Ok((&[][..], 0)));
assert_eq!(decode_varint(&[0x01]), Ok((&[][..], 1)));
assert_eq!(decode_varint(&[0x0F]), Ok((&[][..], 15)));
assert_eq!(decode_varint(&[0xEF, 0x01]), Ok((&[0x01][..], 239)));
assert_eq!(decode_varint(&[0xF0, 0x00]), Ok((&[][..], 240)));
assert_eq!(decode_varint(&[0xF1, 0x00]), Ok((&[][..], 241)));
assert_eq!(decode_varint(&[0xFC, 0x03]), Ok((&[][..], 300)));
assert_eq!(decode_varint(&[0xFF, 0x7F]), Ok((&[][..], 2287)));
assert_eq!(decode_varint(&[0xF0, 0x80, 0x00]), Ok((&[][..], 2288)));
assert_eq!(decode_varint(&[0xF4, 0x88, 0x00]), Ok((&[][..], 2420)));
assert_eq!(
decode_varint(&[0xF0, 0x80, 0x80, 0x0]),
Ok((&[][..], 264432))
);
assert_eq!(
decode_varint(&[0xF0, 0x80, 0x80, 0x80, 0x0]),
Ok((&[][..], 33818864))
);
}
#[test]
fn test_varint_1_byte() {
let data = [0x10]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 16);
let data = [0xEF]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 239);
assert_eq!(decode_varint(&[239]), Ok((&[][..], 239))); }
#[test]
fn test_varint_2_bytes() {
let data = [0xF0, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 240);
let data = [0xF1, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 241);
let data = [0xFC, 0x03]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 300);
let data = [0xFF, 0x7F]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 2287);
assert_eq!(decode_varint(&[250, 0]), Ok((&[][..], 250))); assert_eq!(decode_varint(&[255, 127]), Ok((&[][..], 2287))); }
#[test]
fn test_varint_3_bytes() {
assert_eq!(decode_varint(&[240, 128, 0]), Ok((&[][..], 2288)));
let data = [0xF0, 0x80, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 2288);
let data = [0xF4, 0x88, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 2420);
let data = [0xFF, 0xFF, 0x7F]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 264431);
assert_eq!(decode_varint(&[244, 136, 0]), Ok((&[][..], 2420))); assert_eq!(decode_varint(&[255, 0xFF, 0x7F]), Ok((&[][..], 264431))); }
#[test]
fn test_varint_4_bytes() {
let data = [0xF0, 0x80, 0x80, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 264432);
let data = [0xF0, 0xF4, 0xFE, 0x04]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 1572912);
let data = [0xFF, 0xFF, 0xFF, 0x7F]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 33818863);
}
#[test]
fn test_varint_5_bytes() {
let data = [0xF0, 0x80, 0x80, 0x80, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 33818864);
let data = [0xF0, 0xDC, 0xAC, 0xB0, 0x07]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 281374384);
let data = [0xFF, 0xFF, 0xFF, 0xFF, 0x7F]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 4328786159);
}
#[test]
fn test_varint_6_bytes() {
let data = [0xF0, 0x80, 0x80, 0x80, 0x80, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 4328786160);
let data = [0xF1, 0x80, 0x80, 0x80, 0x80, 0x00]; let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 4328786161);
let data = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F];
let (_, value) = decode_varint(&data).expect("Failed to decode varint");
assert_eq!(value, 554084600047);
}
#[test]
fn test_encode_decode_varint() {
let test_values: Vec<u64> = vec![
0, 239, 240, 2287, 2288, 264432, 4328786160, 10000000000, ];
for &value in &test_values {
let encoded = encode_varint(value);
let (remaining_input, decoded) =
decode_varint(&encoded).expect("Failed to decode varint");
assert_eq!(value, decoded);
assert!(
remaining_input.is_empty(),
"Remaining input should be empty"
);
}
}
#[test]
fn test_encode_decode_varint_loop() {
for i in 0..300000 {
let encoded = encode_varint(i);
let (remaining_input, decoded) =
decode_varint(&encoded).expect("Failed to decode varint");
assert_eq!(i, decoded, "Failed for value: {i}");
assert!(remaining_input.is_empty());
}
}
}