1use crate::{Decode, DecodeError, Encode};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct VarI64(pub i64);
5
6impl Encode for VarI64 {
7 fn encode(&self, buf: &mut Vec<u8>) {
8 let mut value = self.0 as u64;
9 loop {
10 let mut byte = (value & 0x7F) as u8;
11 value >>= 7;
12
13 if value != 0 {
14 byte |= 0x80;
15 }
16
17 buf.push(byte);
18
19 if value == 0 {
20 break;
21 }
22 }
23 }
24}
25
26impl Decode for VarI64 {
27 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
28 let mut value: u64 = 0;
29 let mut shift = 0;
30
31 for _ in 0..10 {
32 if buf.is_empty() {
33 return Err(DecodeError::UnexpectedEof);
34 }
35
36 let byte = buf[0];
37 *buf = &buf[1..];
38
39 value |= ((byte & 0x7F) as u64) << shift;
40
41 if byte & 0x80 == 0 {
42 return Ok(VarI64(value as i64));
43 }
44
45 shift += 7;
46 }
47
48 Err(DecodeError::InvalidVarintLength)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_vari64_zero() {
58 let value = VarI64(0);
59 let mut buf = Vec::new();
60 value.encode(&mut buf);
61 assert_eq!(buf, vec![0x00]);
62
63 let mut slice = buf.as_slice();
64 let decoded = VarI64::decode(&mut slice).unwrap();
65 assert_eq!(decoded.0, 0);
66 }
67
68 #[test]
69 fn test_vari64_small_positive() {
70 let value = VarI64(127);
71 let mut buf = Vec::new();
72 value.encode(&mut buf);
73 assert_eq!(buf, vec![0x7F]);
74
75 let mut slice = buf.as_slice();
76 let decoded = VarI64::decode(&mut slice).unwrap();
77 assert_eq!(decoded.0, 127);
78 }
79
80 #[test]
81 fn test_vari64_128() {
82 let value = VarI64(128);
83 let mut buf = Vec::new();
84 value.encode(&mut buf);
85 assert_eq!(buf, vec![0x80, 0x01]);
86
87 let mut slice = buf.as_slice();
88 let decoded = VarI64::decode(&mut slice).unwrap();
89 assert_eq!(decoded.0, 128);
90 }
91
92 #[test]
93 fn test_vari64_negative() {
94 let value = VarI64(-1);
95 let mut buf = Vec::new();
96 value.encode(&mut buf);
97
98 let mut slice = buf.as_slice();
99 let decoded = VarI64::decode(&mut slice).unwrap();
100 assert_eq!(decoded.0, -1);
101 }
102
103 #[test]
104 fn test_vari64_max() {
105 let value = VarI64(i64::MAX);
106 let mut buf = Vec::new();
107 value.encode(&mut buf);
108
109 let mut slice = buf.as_slice();
110 let decoded = VarI64::decode(&mut slice).unwrap();
111 assert_eq!(decoded.0, i64::MAX);
112 }
113
114 #[test]
115 fn test_vari64_min() {
116 let value = VarI64(i64::MIN);
117 let mut buf = Vec::new();
118 value.encode(&mut buf);
119
120 let mut slice = buf.as_slice();
121 let decoded = VarI64::decode(&mut slice).unwrap();
122 assert_eq!(decoded.0, i64::MIN);
123 }
124
125 #[test]
126 fn test_vari64_truncated() {
127 let mut slice = &[0x80][..];
128 let result = VarI64::decode(&mut slice);
129 assert_eq!(result, Err(DecodeError::UnexpectedEof));
130 }
131
132 #[test]
133 fn test_vari64_too_long() {
134 let bytes = vec![
135 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
136 ];
137 let mut slice = bytes.as_slice();
138 let result = VarI64::decode(&mut slice);
139 assert_eq!(result, Err(DecodeError::InvalidVarintLength));
140 }
141
142 #[test]
143 fn test_vari64_exact_bytes_zero() {
144 let value = VarI64(0);
145 let mut buf = Vec::new();
146 value.encode(&mut buf);
147 assert_eq!(buf, vec![0x00]);
148 }
149
150 #[test]
151 fn test_vari64_exact_bytes_one() {
152 let value = VarI64(1);
153 let mut buf = Vec::new();
154 value.encode(&mut buf);
155 assert_eq!(buf, vec![0x01]);
156 }
157
158 #[test]
159 fn test_vari64_exact_bytes_127() {
160 let value = VarI64(127);
161 let mut buf = Vec::new();
162 value.encode(&mut buf);
163 assert_eq!(buf, vec![0x7F]);
164 }
165
166 #[test]
167 fn test_vari64_exact_bytes_128() {
168 let value = VarI64(128);
169 let mut buf = Vec::new();
170 value.encode(&mut buf);
171 assert_eq!(buf, vec![0x80, 0x01]);
172 }
173
174 #[test]
175 fn test_vari64_exact_bytes_16384() {
176 let value = VarI64(16384);
177 let mut buf = Vec::new();
178 value.encode(&mut buf);
179 assert_eq!(buf, vec![0x80, 0x80, 0x01]);
180 }
181
182 #[test]
183 fn test_vari64_negative_exact_bytes() {
184 let value = VarI64(-1);
185 let mut buf = Vec::new();
186 value.encode(&mut buf);
187 assert_eq!(
188 buf,
189 vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]
190 );
191 }
192
193 #[test]
194 fn test_vari64_negative_two() {
195 let value = VarI64(-2);
196 let mut buf = Vec::new();
197 value.encode(&mut buf);
198 assert_eq!(
199 buf,
200 vec![0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]
201 );
202 }
203
204 #[test]
205 fn test_vari64_100() {
206 let value = VarI64(100);
207 let mut buf = Vec::new();
208 value.encode(&mut buf);
209 assert_eq!(buf.len(), 1);
210 assert_eq!(buf, vec![100]);
211 }
212
213 #[test]
214 fn test_vari64_1000() {
215 let value = VarI64(1000);
216 let mut buf = Vec::new();
217 value.encode(&mut buf);
218 assert_eq!(buf.len(), 2);
219 assert_eq!(buf, vec![0xE8, 0x07]);
220 }
221
222 #[test]
223 fn test_vari64_serialization_efficiency() {
224 struct TestCase {
225 value: i64,
226 expected_len: usize,
227 }
228
229 let cases = [
230 TestCase {
231 value: 0,
232 expected_len: 1,
233 },
234 TestCase {
235 value: 127,
236 expected_len: 1,
237 },
238 TestCase {
239 value: 128,
240 expected_len: 2,
241 },
242 TestCase {
243 value: 16383,
244 expected_len: 2,
245 },
246 TestCase {
247 value: 16384,
248 expected_len: 3,
249 },
250 TestCase {
251 value: 2097151,
252 expected_len: 3,
253 },
254 TestCase {
255 value: 2097152,
256 expected_len: 4,
257 },
258 TestCase {
259 value: i64::MAX,
260 expected_len: 9,
261 },
262 TestCase {
263 value: i64::MIN,
264 expected_len: 10,
265 },
266 ];
267
268 for case in &cases {
269 let mut buf = Vec::new();
270 VarI64(case.value).encode(&mut buf);
271 assert_eq!(
272 buf.len(),
273 case.expected_len,
274 "VarI64({}) should encode to {} bytes, got {}",
275 case.value,
276 case.expected_len,
277 buf.len()
278 );
279 }
280 }
281
282 #[test]
283 fn test_vari64_java_compliance_roundtrip() {
284 let test_values = [
285 0i64,
286 1,
287 127,
288 128,
289 255,
290 256,
291 16383,
292 16384,
293 2097151,
294 2097152,
295 -1,
296 -2,
297 -128,
298 -32768,
299 i64::MAX,
300 i64::MIN,
301 ];
302
303 for value in &test_values {
304 let vi64 = VarI64(*value);
305 let mut buf = Vec::new();
306 vi64.encode(&mut buf);
307
308 let mut slice = buf.as_slice();
309 let decoded = VarI64::decode(&mut slice).unwrap();
310 assert_eq!(
311 decoded.0, *value,
312 "VarI64 roundtrip failed for value {}",
313 value
314 );
315 assert_eq!(
316 slice.len(),
317 0,
318 "VarI64 decode didn't consume all bytes for value {}",
319 value
320 );
321 }
322 }
323
324 #[test]
325 fn test_vari64_max_bytes_limit() {
326 let mut buf = Vec::new();
327 (i64::MAX).encode(&mut buf);
328 assert!(
329 buf.len() <= 10,
330 "VarI64 should encode to at most 10 bytes, got {}",
331 buf.len()
332 );
333 }
334
335 #[test]
336 fn test_vari64_more_than_ten_bytes_rejected() {
337 let bytes = vec![
338 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
339 ];
340 let mut slice = bytes.as_slice();
341 let result = VarI64::decode(&mut slice);
342 assert!(
343 result.is_err(),
344 "VarI64 with 11 bytes should be rejected like Java's position >= 64 check"
345 );
346 }
347
348 #[test]
349 fn test_vari64_java_segment_and_continue_bits() {
350 let value = VarI64(300);
351 let mut buf = Vec::new();
352 value.encode(&mut buf);
353
354 assert_eq!(buf.len(), 2);
355 assert_eq!(buf[0] & 0x80, 0x80, "First byte should have continue bit");
356 assert_eq!(
357 buf[1] & 0x80,
358 0x00,
359 "Last byte should NOT have continue bit"
360 );
361
362 let segment_bits = 0x7F;
363
364 assert_eq!(
365 buf[0] & segment_bits,
366 300u64 as u8 & segment_bits,
367 "First byte segment bits should match"
368 );
369 }
370
371 #[test]
372 fn test_vari64_java_logic_equivalence() {
373 let test_values = [
374 0i64, 1, 63, 64, 127, 128, 255, 256, 16383, 16384, 2097151, 2097152,
375 ];
376
377 for &value in &test_values {
378 let vi64 = VarI64(value);
379 let mut buf = Vec::new();
380 vi64.encode(&mut buf);
381
382 assert!(!buf.is_empty(), "VarI64 should encode to at least 1 byte");
383 assert!(buf.len() <= 10, "VarI64 should encode to at most 10 bytes");
384
385 let mut decoded_value = 0u64;
386 for (i, &byte) in buf.iter().enumerate() {
387 decoded_value |= ((byte & 0x7F) as u64) << (i * 7);
388
389 if byte & 0x80 == 0 {
390 assert_eq!(
391 i + 1,
392 buf.len(),
393 "No-continue-bit should be on the last byte"
394 );
395 break;
396 }
397 }
398
399 assert_eq!(
400 decoded_value, value as u64,
401 "Manual decode should match encoded value for {}: bytes = {:?}",
402 value, buf
403 );
404 }
405 }
406
407 #[test]
408 fn test_vari64_large_values() {
409 let test_values = [
410 1000000i64,
411 10000000,
412 100000000,
413 1000000000,
414 10000000000,
415 100000000000,
416 ];
417
418 for value in &test_values {
419 let vi64 = VarI64(*value);
420 let mut buf = Vec::new();
421 vi64.encode(&mut buf);
422
423 let mut slice = buf.as_slice();
424 let decoded = VarI64::decode(&mut slice).unwrap();
425 assert_eq!(decoded.0, *value, "Failed for large value {}", value);
426 assert!(
427 buf.len() <= 10,
428 "Large value {} should encode to at most 10 bytes, got {}",
429 value,
430 buf.len()
431 );
432 }
433 }
434}