use alloc::vec;
use alloc::vec::Vec;
#[must_use]
pub(crate) fn encode_varint(value: u64) -> Vec<u8> {
if value < 128 {
return vec![u8::try_from(value).unwrap()];
}
let mut temp = Vec::new();
let mut v = value;
while v > 0 {
temp.push((v & 0x7f) as u8);
v >>= 7;
}
let mut result = Vec::with_capacity(temp.len());
for (i, &byte) in temp.iter().rev().enumerate() {
if i == temp.len() - 1 {
result.push(byte);
} else {
result.push(byte | 0x80);
}
}
result
}
#[inline]
#[must_use]
pub(crate) fn encode_varint_simple(value: u64) -> Vec<u8> {
encode_varint(value)
}
#[must_use]
pub(crate) fn decode_varint(data: &[u8]) -> Option<(u64, usize)> {
if data.is_empty() {
return None;
}
let mut value = 0u64;
let mut i = 0;
loop {
if i >= data.len() {
return None; }
if i >= 10 {
return None; }
let byte = data[i];
value = (value << 7) | u64::from(byte & 0x7f);
i += 1;
if byte & 0x80 == 0 {
break;
}
}
Some((value, i))
}
#[must_use]
#[allow(dead_code)]
pub(crate) fn varint_len(value: u64) -> usize {
if value < 128 {
1
} else if value < 16384 {
2
} else if value < 2_097_152 {
3
} else if value < 268_435_456 {
4
} else if value < 34_359_738_368 {
5
} else if value < 4_398_046_511_104 {
6
} else if value < 562_949_953_421_312 {
7
} else if value < 72_057_594_037_927_936 {
8
} else if value < 9_223_372_036_854_775_808 {
9
} else {
10
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_varint_roundtrip_small() {
for v in 0..128 {
let encoded = encode_varint(v);
let (decoded, len) = decode_varint(&encoded).unwrap();
assert_eq!(decoded, v);
assert_eq!(len, encoded.len());
assert_eq!(len, 1);
}
}
#[test]
fn test_varint_roundtrip_medium() {
for v in [128, 255, 256, 300, 1000, 16383, 16384, 100_000, 2_097_151] {
let encoded = encode_varint(v);
let (decoded, len) = decode_varint(&encoded).unwrap();
assert_eq!(decoded, v, "Failed for value {v}");
assert_eq!(len, encoded.len());
}
}
#[test]
fn test_varint_roundtrip_large() {
for v in [
0xFF_FFFF,
0xFFFF_FFFF,
0xFF_FFFF_FFFF,
0xFFFF_FFFF_FFFF,
0xFF_FFFF_FFFF_FFFF,
u64::MAX,
] {
let encoded = encode_varint(v);
let (decoded, len) = decode_varint(&encoded).unwrap();
assert_eq!(decoded, v, "Failed for value {v}");
assert_eq!(len, encoded.len());
}
}
#[test]
fn test_varint_len() {
assert_eq!(varint_len(0), 1);
assert_eq!(varint_len(127), 1);
assert_eq!(varint_len(128), 2);
assert_eq!(varint_len(16383), 2);
assert_eq!(varint_len(16384), 3);
assert_eq!(varint_len(2_097_151), 3);
assert_eq!(varint_len(2_097_152), 4);
assert_eq!(varint_len(268_435_455), 4);
assert_eq!(varint_len(268_435_456), 5);
assert_eq!(varint_len(34_359_738_367), 5);
assert_eq!(varint_len(34_359_738_368), 6);
assert_eq!(varint_len(4_398_046_511_103), 6);
assert_eq!(varint_len(4_398_046_511_104), 7);
assert_eq!(varint_len(562_949_953_421_311), 7);
assert_eq!(varint_len(562_949_953_421_312), 8);
assert_eq!(varint_len(72_057_594_037_927_935), 8);
assert_eq!(varint_len(72_057_594_037_927_936), 9);
assert_eq!(varint_len(9_223_372_036_854_775_807), 9);
assert_eq!(varint_len(9_223_372_036_854_775_808), 10);
assert_eq!(varint_len(u64::MAX), 10);
}
#[test]
fn test_decode_varint_empty() {
assert_eq!(decode_varint(&[]), None);
}
#[test]
fn test_decode_varint_too_long() {
let too_long = [0x80u8; 11];
assert_eq!(decode_varint(&too_long), None);
}
#[test]
fn test_decode_varint_truncated() {
let truncated = [0x80u8];
assert_eq!(decode_varint(&truncated), None);
}
#[test]
fn test_varint_300() {
let encoded = encode_varint(300);
assert_eq!(encoded, vec![0x82, 0x2c]);
let (decoded, len) = decode_varint(&encoded).unwrap();
assert_eq!(decoded, 300);
assert_eq!(len, 2);
}
}