1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum Error {
3 TooLarge,
4 Underflow,
5}
6
7pub struct VarInt;
8
9impl VarInt {
10 pub const MAX: u64 = (1u64 << 62) - 1;
11
12 pub fn size_for(value: u64) -> Result<usize, Error> {
13 match value {
14 0..=63 => Ok(1),
15 64..=16_383 => Ok(2),
16 16_384..=1_073_741_823 => Ok(4),
17 v if v <= Self::MAX => Ok(8),
18 _ => Err(Error::TooLarge),
19 }
20 }
21
22 pub fn encode(value: u64, out: &mut Vec<u8>) -> Result<(), Error> {
23 match value {
24 0..=63 => out.push(value as u8),
25 64..=16_383 => {
26 let v = (value as u16) | 0x4000;
27 out.extend_from_slice(&v.to_be_bytes());
28 }
29 16_384..=1_073_741_823 => {
30 let v = (value as u32) | 0x8000_0000;
31 out.extend_from_slice(&v.to_be_bytes());
32 }
33 v if v <= Self::MAX => {
34 let w = v | 0xC000_0000_0000_0000;
35 out.extend_from_slice(&w.to_be_bytes());
36 }
37 _ => return Err(Error::TooLarge),
38 }
39 Ok(())
40 }
41
42 pub fn decode(input: &[u8]) -> Result<(u64, usize), Error> {
43 let first = *input.first().ok_or(Error::Underflow)?;
44 let len = 1usize << (first >> 6);
45 if input.len() < len {
46 return Err(Error::Underflow);
47 }
48 let mut buf = [0u8; 8];
49 buf[8 - len..].copy_from_slice(&input[..len]);
50 let mut value = u64::from_be_bytes(buf);
51 value &= (1u64 << (len * 8 - 2)) - 1;
52 Ok((value, len))
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn round_trips_boundaries() {
62 for value in [0, 63, 64, 16_383, 16_384, 1_073_741_823, VarInt::MAX] {
63 let mut out = Vec::new();
64 VarInt::encode(value, &mut out).unwrap();
65 assert_eq!(VarInt::decode(&out), Ok((value, out.len())));
66 }
67 }
68}