#[inline(always)]
pub fn encode_varint(mut value: usize) -> Vec<u8> {
if value < 128 {
return vec![value as u8];
}
let capacity = if value == 0 {
1
} else {
(usize::BITS - value.leading_zeros()).div_ceil(7) as usize
};
let mut bytes = Vec::with_capacity(capacity);
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80; }
bytes.push(byte);
if value == 0 {
break;
}
}
bytes
}
#[inline(always)]
pub fn decode_varint(bytes: &[u8]) -> (usize, usize) {
if bytes[0] < 128 {
return (bytes[0] as usize, 1);
}
let mut result = 0usize;
let mut shift = 0;
result |= ((bytes[0] & 0x7F) as usize) << shift;
if bytes[0] & 0x80 == 0 {
return (result, 1);
}
shift += 7;
if 1 >= bytes.len() {
return (result, 1);
}
result |= ((bytes[1] & 0x7F) as usize) << shift;
if bytes[1] & 0x80 == 0 {
return (result, 2);
}
shift += 7;
if 2 >= bytes.len() {
return (result, 2);
}
result |= ((bytes[2] & 0x7F) as usize) << shift;
if bytes[2] & 0x80 == 0 {
return (result, 3);
}
shift += 7;
if 3 >= bytes.len() {
return (result, 3);
}
result |= ((bytes[3] & 0x7F) as usize) << shift;
if bytes[3] & 0x80 == 0 {
return (result, 4);
}
shift += 7;
let mut i = 4;
while i < bytes.len() {
let byte = bytes[i];
result |= ((byte & 0x7F) as usize) << shift;
i += 1;
if byte & 0x80 == 0 {
break;
}
shift += 7;
}
(result, i)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_decode_zero() {
let encoded = encode_varint(0);
assert_eq!(encoded, vec![0]);
assert_eq!(decode_varint(&encoded[..]), (0, 1));
}
#[test]
fn test_encode_decode_small_values() {
for i in 0..128 {
let encoded = encode_varint(i);
assert_eq!(encoded.len(), 1);
assert_eq!(encoded[0], i as u8);
assert_eq!(decode_varint(&encoded[..]), (i, 1));
}
}
#[test]
fn test_encode_decode_medium_values() {
let test_cases = vec![
(128, vec![0x80, 0x01]),
(300, vec![0xAC, 0x02]),
(16384, vec![0x80, 0x80, 0x01]),
];
for (value, expected) in test_cases {
let encoded = encode_varint(value);
assert_eq!(encoded, expected);
assert_eq!(decode_varint(&encoded[..]), (value, encoded.len()));
}
}
#[test]
fn test_encode_decode_large_values() {
let test_values = vec![1_000_000, 10_000_000, 100_000_000, usize::MAX / 2];
for value in test_values {
let encoded = encode_varint(value);
let (decoded, bytes_consumed) = decode_varint(&encoded[..]);
assert_eq!(decoded, value);
assert_eq!(bytes_consumed, encoded.len());
}
}
#[test]
fn test_encode_max_value() {
let value = usize::MAX;
let encoded = encode_varint(value);
let (decoded, bytes_consumed) = decode_varint(&encoded[..]);
assert_eq!(decoded, value);
assert_eq!(bytes_consumed, encoded.len());
}
#[test]
fn test_roundtrip_random_values() {
let test_values = [
1, 10, 100, 127, 128, 255, 256, 1000, 10000, 65535, 65536, 100000, 1000000, 16777215,
16777216,
];
for &value in &test_values {
let encoded = encode_varint(value);
let (decoded, bytes_consumed) = decode_varint(&encoded[..]);
assert_eq!(decoded, value, "Failed roundtrip for value {}", value);
assert_eq!(bytes_consumed, encoded.len());
}
}
#[test]
fn test_decode_partial_buffer() {
let mut buffer = encode_varint(12345);
buffer.extend_from_slice(&[0xFF, 0xFF, 0xFF]);
let (decoded, bytes_consumed) = decode_varint(&buffer[..]);
assert_eq!(decoded, 12345);
assert!(bytes_consumed < buffer.len());
}
#[test]
fn test_continuation_bits() {
let encoded = encode_varint(128);
assert!(
encoded[0] & 0x80 != 0,
"First byte should have continuation bit"
);
assert!(
encoded[1] & 0x80 == 0,
"Last byte should not have continuation bit"
);
}
#[test]
fn test_size_efficiency() {
assert_eq!(encode_varint(0).len(), 1);
assert_eq!(encode_varint(127).len(), 1);
assert_eq!(encode_varint(128).len(), 2);
assert_eq!(encode_varint(16383).len(), 2);
assert_eq!(encode_varint(16384).len(), 3);
}
#[test]
fn test_encode_capacity_optimization() {
for value in [0, 127, 128, 16384, 1_000_000] {
let encoded = encode_varint(value);
assert_eq!(
encoded.capacity(),
encoded.len(),
"Over-allocated for value {}",
value
);
}
}
}