1use crate::bitstream::{BitReader, BitWriter};
8use crate::error::Error;
9
10pub fn write_varint(writer: &mut BitWriter, value: u32) -> Result<(), Error> {
16 let bits_needed = if value == 0 {
18 0
19 } else {
20 32 - value.leading_zeros() as usize
21 };
22
23 if bits_needed <= 14 {
24 writer.write_bits(bits_needed as u64, 4);
25 writer.write_bits(value as u64, bits_needed);
26 Ok(())
27 } else {
28 let l_high = bits_needed - 14;
30 if l_high > 15 {
31 return Err(Error::VarintOverflow { value });
32 }
33 writer.write_bits(15, 4);
34 writer.write_bits(l_high as u64, 4);
35 let low_mask = (1u64 << 14) - 1;
36 let payload_low = (value as u64) & low_mask;
37 let payload_high = (value as u64) >> 14;
38 writer.write_bits(payload_low, 14);
39 writer.write_bits(payload_high, l_high);
40 Ok(())
41 }
42}
43
44pub fn read_varint(reader: &mut BitReader) -> Result<u32, Error> {
46 let l = reader.read_bits(4)? as usize;
47 if l < 15 {
48 let value = reader.read_bits(l)? as u32;
49 Ok(value)
50 } else {
51 let l_high = reader.read_bits(4)? as usize;
52 let payload_low = reader.read_bits(14)? as u32;
53 let payload_high = reader.read_bits(l_high)? as u32;
54 Ok((payload_high << 14) | payload_low)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 fn round_trip(value: u32) {
63 let mut w = BitWriter::new();
64 write_varint(&mut w, value).unwrap();
65 let bytes = w.into_bytes();
66 let mut r = BitReader::new(&bytes);
67 assert_eq!(read_varint(&mut r).unwrap(), value);
68 }
69
70 #[test]
71 fn varint_zero() {
72 round_trip(0);
73 }
74
75 #[test]
76 fn varint_one() {
77 round_trip(1);
78 }
79
80 #[test]
81 fn varint_84() {
82 round_trip(84);
83 }
84
85 #[test]
86 fn varint_1024() {
87 round_trip(1024);
88 }
89
90 #[test]
91 fn varint_16383_no_extension() {
92 round_trip(16383);
94 }
95
96 #[test]
97 fn varint_16384_uses_extension() {
98 round_trip(16384);
99 }
100
101 #[test]
102 fn varint_max_u31() {
103 round_trip((1u32 << 29) - 1);
107 }
108
109 #[test]
110 fn varint_zero_costs_4_bits() {
111 let mut w = BitWriter::new();
112 write_varint(&mut w, 0).unwrap();
113 assert_eq!(w.bit_len(), 4);
114 }
115
116 #[test]
117 fn varint_one_costs_5_bits() {
118 let mut w = BitWriter::new();
119 write_varint(&mut w, 1).unwrap();
120 assert_eq!(w.bit_len(), 5);
121 }
122
123 #[test]
124 fn varint_84_costs_11_bits() {
125 let mut w = BitWriter::new();
126 write_varint(&mut w, 84).unwrap();
127 assert_eq!(w.bit_len(), 11);
128 }
129
130 #[test]
131 fn varint_overflow_returns_error_instead_of_panicking() {
132 let mut w = BitWriter::new();
134 let result = write_varint(&mut w, 1u32 << 30);
135 assert!(matches!(result, Err(Error::VarintOverflow { value }) if value == 1u32 << 30));
136 }
137
138 #[test]
139 fn varint_max_single_extension_succeeds() {
140 let mut w = BitWriter::new();
142 write_varint(&mut w, (1u32 << 29) - 1).unwrap();
143 }
144
145 #[test]
146 fn varint_l_zero_decodes_to_zero_directly() {
147 let mut w = BitWriter::new();
150 w.write_bits(0b0000, 4); w.write_bits(0b1010, 4); let bytes = w.into_bytes();
153 let mut r = BitReader::new(&bytes);
154 assert_eq!(read_varint(&mut r).unwrap(), 0);
155 assert_eq!(r.read_bits(4).unwrap(), 0b1010);
157 }
158}