1use std::io::{self, Read, Write};
5
6pub fn write_varint<W: Write>(writer: &mut W, value: u64) -> io::Result<usize> {
10 let mut no_bytes = 0u8;
12 let mut tmp = value;
13 while tmp > 0 {
14 no_bytes += 1;
15 tmp >>= 8;
16 }
17
18 if no_bytes == 0 {
20 writer.write_all(&[0])?;
21 return Ok(1);
22 }
23
24 writer.write_all(&[no_bytes])?;
26
27 for i in (0..no_bytes).rev() {
29 let byte = ((value >> (i * 8)) & 0xff) as u8;
30 writer.write_all(&[byte])?;
31 }
32
33 Ok((no_bytes + 1) as usize)
34}
35
36pub fn read_varint<R: Read>(reader: &mut R) -> io::Result<(u64, usize)> {
39 let mut no_bytes_buf = [0u8; 1];
41 reader.read_exact(&mut no_bytes_buf)?;
42 let no_bytes = no_bytes_buf[0];
43
44 if no_bytes == 0 {
46 return Ok((0, 1));
47 }
48
49 let mut value = 0u64;
51 for _ in 0..no_bytes {
52 let mut byte_buf = [0u8; 1];
53 reader.read_exact(&mut byte_buf)?;
54 value <<= 8;
55 value += byte_buf[0] as u64;
56 }
57
58 Ok((value, (no_bytes + 1) as usize))
59}
60
61pub fn write_fixed_u64<W: Write>(writer: &mut W, value: u64) -> io::Result<usize> {
63 let bytes = value.to_le_bytes();
64 writer.write_all(&bytes)?;
65 Ok(8)
66}
67
68pub fn read_fixed_u64<R: Read>(reader: &mut R) -> io::Result<u64> {
70 let mut bytes = [0u8; 8];
71 reader.read_exact(&mut bytes)?;
72 Ok(u64::from_le_bytes(bytes))
73}
74
75pub fn encode_varint(value: u64) -> Vec<u8> {
77 let mut buf = Vec::new();
78 write_varint(&mut buf, value).expect("Writing to Vec should not fail");
79 buf
80}
81
82pub fn decode_varint(bytes: &[u8]) -> io::Result<(u64, usize)> {
84 let mut cursor = std::io::Cursor::new(bytes);
85 read_varint(&mut cursor)
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_varint_roundtrip() {
94 let test_values = vec![
95 0u64,
96 1,
97 127,
98 128,
99 255,
100 256,
101 65535,
102 65536,
103 0xFFFFFFFF,
104 0x1234567890ABCDEF,
105 u64::MAX,
106 ];
107
108 for value in test_values {
109 let encoded = encode_varint(value);
110 let (decoded, _) = decode_varint(&encoded).unwrap();
111 assert_eq!(value, decoded, "Roundtrip failed for value {value}");
112 }
113 }
114
115 #[test]
116 fn test_varint_encoding_lengths() {
117 assert_eq!(encode_varint(0).len(), 1); assert_eq!(encode_varint(1).len(), 2); assert_eq!(encode_varint(255).len(), 2); assert_eq!(encode_varint(256).len(), 3); assert_eq!(encode_varint(65535).len(), 3); assert_eq!(encode_varint(65536).len(), 4); }
124
125 #[test]
126 fn test_fixed_u64_roundtrip() {
127 let test_values = vec![0u64, 1, 42, 0xDEADBEEF, u64::MAX];
128
129 for value in test_values {
130 let mut buf = Vec::new();
131 write_fixed_u64(&mut buf, value).unwrap();
132 assert_eq!(buf.len(), 8);
133
134 let decoded = read_fixed_u64(&mut std::io::Cursor::new(&buf)).unwrap();
135 assert_eq!(value, decoded);
136 }
137 }
138}