1use crate::errors::AvroError;
19
20#[derive(Debug, Default)]
26pub struct VLQDecoder {
27 in_progress: u64,
29 shift: u32,
30}
31
32impl VLQDecoder {
33 pub fn long(&mut self, buf: &mut &[u8]) -> Result<Option<i64>, AvroError> {
38 while let Some(byte) = buf.first().copied() {
39 if self.shift == 63 && byte >= 0x02 {
40 self.in_progress = 0;
41 self.shift = 0;
42 return Err(AvroError::ParseError(
43 "Malformed Avro varint: too many continuation bytes".to_string(),
44 ));
45 }
46 *buf = &buf[1..];
47 self.in_progress |= ((byte & 0x7F) as u64) << self.shift;
48 self.shift += 7;
49 if byte & 0x80 == 0 {
50 let val = self.in_progress;
51 self.in_progress = 0;
52 self.shift = 0;
53 return Ok(Some((val >> 1) as i64 ^ -((val & 1) as i64)));
54 }
55 }
56 Ok(None)
57 }
58}
59
60#[inline]
62pub(crate) fn read_varint(buf: &[u8]) -> Option<(u64, usize)> {
63 let first = *buf.first()?;
64 if first < 0x80 {
65 return Some((first as u64, 1));
66 }
67
68 if let Some(array) = buf.get(..10) {
69 return read_varint_array(array.try_into().unwrap());
70 }
71
72 read_varint_slow(buf)
73}
74
75#[inline]
80fn read_varint_array(buf: [u8; 10]) -> Option<(u64, usize)> {
81 let mut in_progress = 0_u64;
82 for (idx, b) in buf.into_iter().take(9).enumerate() {
83 in_progress += (b as u64) << (7 * idx);
84 if b < 0x80 {
85 return Some((in_progress, idx + 1));
86 }
87 in_progress -= 0x80 << (7 * idx);
88 }
89
90 let b = buf[9] as u64;
91 in_progress += b << (7 * 9);
92 (b < 0x02).then_some((in_progress, 10))
93}
94
95#[inline(never)]
96#[cold]
97fn read_varint_slow(buf: &[u8]) -> Option<(u64, usize)> {
98 let mut value = 0;
99 for (count, _byte) in buf.iter().take(10).enumerate() {
100 let byte = buf[count];
101 value |= u64::from(byte & 0x7F) << (count * 7);
102 if byte <= 0x7F {
103 return (count != 9 || byte < 2).then_some((value, count + 1));
106 }
107 }
108
109 None
110}
111
112pub(crate) fn skip_varint(buf: &[u8]) -> Option<usize> {
113 if let Some(array) = buf.get(..10) {
114 return skip_varint_array(array.try_into().unwrap());
115 }
116 skip_varint_slow(buf)
117}
118
119fn skip_varint_array(buf: [u8; 10]) -> Option<usize> {
120 #[allow(clippy::needless_range_loop)]
122 for idx in 0..9 {
123 if buf[idx] < 0x80 {
124 return Some(idx + 1);
125 }
126 }
127 (buf[9] < 0x02).then_some(10)
128}
129
130#[cold]
131fn skip_varint_slow(buf: &[u8]) -> Option<usize> {
132 debug_assert!(
133 buf.len() < 10,
134 "should be only called on buffers too short for the fast path"
135 );
136 for (idx, &byte) in buf.iter().enumerate() {
137 if byte < 0x80 {
138 return Some(idx + 1);
139 }
140 }
141 None
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 fn encode_var(mut n: u64, dst: &mut [u8]) -> usize {
149 let mut i = 0;
150
151 while n >= 0x80 {
152 dst[i] = 0x80 | (n as u8);
153 i += 1;
154 n >>= 7;
155 }
156
157 dst[i] = n as u8;
158 i + 1
159 }
160
161 fn varint_test(a: u64) {
162 let mut buf = [0_u8; 10];
163 let len = encode_var(a, &mut buf);
164 assert_eq!(read_varint(&buf[..len]).unwrap(), (a, len));
165 assert_eq!(read_varint(&buf).unwrap(), (a, len));
166 }
167
168 #[test]
169 fn test_varint() {
170 varint_test(0);
171 varint_test(4395932);
172 varint_test(u64::MAX);
173
174 for _ in 0..1000 {
175 varint_test(rand::random());
176 }
177 }
178
179 fn zigzag_encode(n: i64) -> u64 {
180 ((n << 1) ^ (n >> 63)) as u64
181 }
182
183 fn long_test(n: i64) {
184 let mut buf = [0_u8; 10];
185 let len = encode_var(zigzag_encode(n), &mut buf);
186 let mut decoder = VLQDecoder::default();
187 let mut slice = &buf[..len];
188 assert_eq!(decoder.long(&mut slice).unwrap(), Some(n));
189 assert!(slice.is_empty());
190 }
191
192 #[test]
193 fn test_long_roundtrip() {
194 long_test(0);
195 long_test(1);
196 long_test(-1);
197 long_test(4395932);
198 long_test(-4395932);
199 long_test(i64::MAX);
200 long_test(i64::MIN);
201
202 for _ in 0..1000 {
203 long_test(rand::random());
204 }
205 }
206
207 #[test]
208 fn test_long_overlong_varint_returns_error() {
209 let overlong = [0xFFu8; 13];
213 let mut decoder = VLQDecoder::default();
214 let mut buf = &overlong[..];
215 assert!(decoder.long(&mut buf).is_err());
216
217 let mut fresh = &[0x02u8][..]; assert_eq!(decoder.long(&mut fresh).unwrap(), Some(1));
221 }
222}