1use std::{convert::TryInto, fmt};
9
10use bytes::{Buf, BufMut};
11use thiserror::Error;
12
13use crate::coding::{self, Codec, UnexpectedEnd};
14
15#[cfg(feature = "arbitrary")]
16use arbitrary::Arbitrary;
17
18#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
24pub struct VarInt(pub(crate) u64);
25
26impl VarInt {
27 pub const MAX: Self = Self((1 << 62) - 1);
29 pub const MAX_SIZE: usize = 8;
31
32 #[inline]
37 pub(crate) fn from_u64_bounded(x: u64) -> Self {
38 debug_assert!(x < 2u64.pow(62), "VarInt value {} exceeds maximum", x);
39 unsafe { Self::from_u64_unchecked(x) }
41 }
42
43 pub const fn from_u32(x: u32) -> Self {
45 Self(x as u64)
46 }
47
48 pub fn from_u64(x: u64) -> Result<Self, VarIntBoundsExceeded> {
50 if x < 2u64.pow(62) {
51 Ok(Self(x))
52 } else {
53 Err(VarIntBoundsExceeded)
54 }
55 }
56
57 pub const unsafe fn from_u64_unchecked(x: u64) -> Self {
63 Self(x)
64 }
65
66 pub const fn into_inner(self) -> u64 {
68 self.0
69 }
70
71 pub(crate) const fn size(self) -> usize {
73 let x = self.0;
74 if x < 2u64.pow(6) {
75 1
76 } else if x < 2u64.pow(14) {
77 2
78 } else if x < 2u64.pow(30) {
79 4
80 } else if x < 2u64.pow(62) {
81 8
82 } else {
83 Self::MAX_SIZE
84 }
85 }
86
87 pub(crate) fn encode_checked<B: BufMut>(x: u64, w: &mut B) -> Result<(), VarIntBoundsExceeded> {
88 if x < 2u64.pow(6) {
89 w.put_u8(x as u8);
90 Ok(())
91 } else if x < 2u64.pow(14) {
92 w.put_u16((0b01 << 14) | x as u16);
93 Ok(())
94 } else if x < 2u64.pow(30) {
95 w.put_u32((0b10 << 30) | x as u32);
96 Ok(())
97 } else if x < 2u64.pow(62) {
98 w.put_u64((0b11 << 62) | x);
99 Ok(())
100 } else {
101 Err(VarIntBoundsExceeded)
102 }
103 }
104}
105
106impl From<VarInt> for u64 {
107 fn from(x: VarInt) -> Self {
108 x.0
109 }
110}
111
112impl From<u8> for VarInt {
113 fn from(x: u8) -> Self {
114 Self(x.into())
115 }
116}
117
118impl From<u16> for VarInt {
119 fn from(x: u16) -> Self {
120 Self(x.into())
121 }
122}
123
124impl From<u32> for VarInt {
125 fn from(x: u32) -> Self {
126 Self(x.into())
127 }
128}
129
130impl std::convert::TryFrom<u64> for VarInt {
131 type Error = VarIntBoundsExceeded;
132 fn try_from(x: u64) -> Result<Self, VarIntBoundsExceeded> {
134 Self::from_u64(x)
135 }
136}
137
138impl std::convert::TryFrom<u128> for VarInt {
139 type Error = VarIntBoundsExceeded;
140 fn try_from(x: u128) -> Result<Self, VarIntBoundsExceeded> {
142 Self::from_u64(x.try_into().map_err(|_| VarIntBoundsExceeded)?)
143 }
144}
145
146impl std::convert::TryFrom<usize> for VarInt {
147 type Error = VarIntBoundsExceeded;
148 fn try_from(x: usize) -> Result<Self, VarIntBoundsExceeded> {
150 Self::try_from(x as u64)
151 }
152}
153
154impl fmt::Debug for VarInt {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 self.0.fmt(f)
157 }
158}
159
160impl fmt::Display for VarInt {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 self.0.fmt(f)
163 }
164}
165
166#[cfg(feature = "arbitrary")]
167impl<'arbitrary> Arbitrary<'arbitrary> for VarInt {
168 fn arbitrary(u: &mut arbitrary::Unstructured<'arbitrary>) -> arbitrary::Result<Self> {
169 Ok(Self(u.int_in_range(0..=Self::MAX.0)?))
170 }
171}
172
173#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
175#[error("value too large for varint encoding")]
176pub struct VarIntBoundsExceeded;
177
178#[cfg(test)]
179#[allow(clippy::items_after_test_module)]
180mod tests {
181 use super::*;
182 use bytes::BytesMut;
183
184 #[test]
187 fn varint_max_value() {
188 assert_eq!(VarInt::MAX.into_inner(), (1 << 62) - 1);
189 }
190
191 #[test]
192 fn varint_max_size() {
193 assert_eq!(VarInt::MAX_SIZE, 8);
194 }
195
196 #[test]
199 fn from_u32_zero() {
200 let v = VarInt::from_u32(0);
201 assert_eq!(v.into_inner(), 0);
202 }
203
204 #[test]
205 fn from_u32_max_u32() {
206 let v = VarInt::from_u32(u32::MAX);
207 assert_eq!(v.into_inner(), u32::MAX as u64);
208 }
209
210 #[test]
211 fn from_u32_is_infallible() {
212 let v = VarInt::from_u32(0xFFFF_FFFF);
214 assert_eq!(v.into_inner(), 0xFFFF_FFFF);
215 }
216
217 #[test]
220 fn from_u64_zero() {
221 let v = VarInt::from_u64(0).unwrap();
222 assert_eq!(v.into_inner(), 0);
223 }
224
225 #[test]
226 fn from_u64_max_valid() {
227 let v = VarInt::from_u64(VarInt::MAX.into_inner()).unwrap();
228 assert_eq!(v, VarInt::MAX);
229 }
230
231 #[test]
232 fn from_u64_too_large() {
233 let result = VarInt::from_u64(1u64 << 62);
234 assert_eq!(result.unwrap_err(), VarIntBoundsExceeded);
235 }
236
237 #[test]
238 fn from_u64_just_beyond_max() {
239 let result = VarInt::from_u64(VarInt::MAX.into_inner() + 1);
240 assert!(result.is_err());
241 }
242
243 #[test]
246 fn from_u64_bounded_works_for_valid_values() {
247 let v = VarInt::from_u64_bounded(42);
248 assert_eq!(v.into_inner(), 42);
249 }
250
251 #[test]
252 fn from_u64_bounded_zero() {
253 let v = VarInt::from_u64_bounded(0);
254 assert_eq!(v.into_inner(), 0);
255 }
256
257 #[test]
258 fn from_u64_bounded_max_valid() {
259 let v = VarInt::from_u64_bounded(VarInt::MAX.into_inner());
260 assert_eq!(v, VarInt::MAX);
261 }
262
263 #[test]
266 fn from_u64_unchecked_safe_when_used_correctly() {
267 let v = unsafe { VarInt::from_u64_unchecked(42) };
269 assert_eq!(v.into_inner(), 42);
270 }
271
272 #[test]
273 fn from_u64_unchecked_with_max() {
274 let v = unsafe { VarInt::from_u64_unchecked(VarInt::MAX.into_inner()) };
276 assert_eq!(v, VarInt::MAX);
277 }
278
279 #[test]
282 fn size_1_byte_boundaries() {
283 assert_eq!(VarInt::from_u32(0).size(), 1);
284 assert_eq!(VarInt::from_u32(63).size(), 1);
285 }
286
287 #[test]
288 fn size_2_byte_boundaries() {
289 assert_eq!(VarInt::from_u32(64).size(), 2);
290 assert_eq!(VarInt::from_u32(16383).size(), 2);
291 }
292
293 #[test]
294 fn size_4_byte_boundaries() {
295 assert_eq!(VarInt::from_u32(16384).size(), 4);
296 assert_eq!(VarInt::from_u32(1_073_741_823).size(), 4);
297 }
298
299 #[test]
300 fn size_8_byte_boundaries() {
301 let v = VarInt::from_u64(1_073_741_824).unwrap();
302 assert_eq!(v.size(), 8);
303 assert_eq!(VarInt::MAX.size(), 8);
304 }
305
306 #[test]
309 fn encode_checked_1_byte_tag() {
310 let mut buf = BytesMut::new();
311 VarInt::encode_checked(0, &mut buf).unwrap();
312 assert_eq!(&buf[..], &[0x00]);
313
314 let mut buf = BytesMut::new();
315 VarInt::encode_checked(63, &mut buf).unwrap();
316 assert_eq!(&buf[..], &[0x3F]);
317 }
318
319 #[test]
320 fn encode_checked_2_byte_tag() {
321 let mut buf = BytesMut::new();
322 VarInt::encode_checked(64, &mut buf).unwrap();
323 assert_eq!(buf[0] >> 6, 0b01);
325 assert_eq!(buf.len(), 2);
326
327 let mut buf = BytesMut::new();
328 VarInt::encode_checked(16383, &mut buf).unwrap();
329 assert_eq!(&buf[..], &[0x7F, 0xFF]);
331 }
332
333 #[test]
334 fn encode_checked_4_byte_tag() {
335 let mut buf = BytesMut::new();
336 VarInt::encode_checked(16384, &mut buf).unwrap();
337 assert_eq!(buf[0] >> 6, 0b10);
338 assert_eq!(buf.len(), 4);
339
340 let mut buf = BytesMut::new();
341 VarInt::encode_checked(1_073_741_823, &mut buf).unwrap();
342 assert_eq!(buf.len(), 4);
343 }
344
345 #[test]
346 fn encode_checked_8_byte_tag() {
347 let mut buf = BytesMut::new();
348 VarInt::encode_checked(1_073_741_824, &mut buf).unwrap();
349 assert_eq!(buf[0] >> 6, 0b11);
350 assert_eq!(buf.len(), 8);
351
352 let mut buf = BytesMut::new();
353 VarInt::encode_checked(VarInt::MAX.into_inner(), &mut buf).unwrap();
354 assert_eq!(buf.len(), 8);
355 }
356
357 #[test]
358 fn encode_checked_overflow() {
359 let mut buf = BytesMut::new();
360 let result = VarInt::encode_checked(1u64 << 62, &mut buf);
361 assert_eq!(result.unwrap_err(), VarIntBoundsExceeded);
362 }
363
364 #[test]
365 fn encode_checked_overflow_near_max() {
366 let mut buf = BytesMut::new();
367 let result = VarInt::encode_checked(u64::MAX, &mut buf);
368 assert_eq!(result.unwrap_err(), VarIntBoundsExceeded);
369 }
370
371 #[test]
374 fn encode_checked_and_decode_roundtrip_small() {
375 let mut buf = BytesMut::new();
376 VarInt::encode_checked(42, &mut buf).unwrap();
377 let mut read = buf.freeze();
378 let decoded = VarInt::decode(&mut read).unwrap();
379 assert_eq!(decoded.into_inner(), 42);
380 }
381
382 #[test]
383 fn encode_checked_and_decode_roundtrip_each_size() {
384 let values = [
385 0u64,
386 63,
387 64,
388 16383,
389 16384,
390 1_073_741_823,
391 1_073_741_824,
392 VarInt::MAX.into_inner(),
393 ];
394 for &v in &values {
395 let mut buf = BytesMut::new();
396 VarInt::encode_checked(v, &mut buf).unwrap();
397 let mut read = buf.freeze();
398 let decoded = VarInt::decode(&mut read).unwrap();
399 assert_eq!(decoded.into_inner(), v, "failed for value {v}");
400 }
401 }
402
403 #[test]
406 fn varint_encode_correct_tag_pattern() {
407 let mut buf = BytesMut::new();
409 VarInt::from_u32(42).encode(&mut buf);
410 assert_eq!(buf[0] >> 6, 0b00);
411
412 let mut buf2 = BytesMut::new();
414 VarInt::from_u32(16383).encode(&mut buf2);
415 assert_eq!(buf2[0] >> 6, 0b01);
416
417 let mut buf4 = BytesMut::new();
419 VarInt::from_u32(1_073_741_823).encode(&mut buf4);
420 assert_eq!(buf4[0] >> 6, 0b10);
421
422 let mut buf8 = BytesMut::new();
424 VarInt::from_u64(1_073_741_824).unwrap().encode(&mut buf8);
425 assert_eq!(buf8[0] >> 6, 0b11);
426 }
427
428 #[test]
431 fn into_u64() {
432 let v = VarInt::from_u32(42);
433 let val: u64 = v.into();
434 assert_eq!(val, 42);
435 }
436
437 #[test]
438 fn from_u8_into_varint() {
439 let v: VarInt = 42u8.into();
440 assert_eq!(v.into_inner(), 42);
441 }
442
443 #[test]
444 fn from_u8_max() {
445 let v: VarInt = u8::MAX.into();
446 assert_eq!(v.into_inner(), u8::MAX as u64);
447 }
448
449 #[test]
450 fn from_u16_into_varint() {
451 let v: VarInt = 16383u16.into();
452 assert_eq!(v.into_inner(), 16383);
453 }
454
455 #[test]
456 fn from_u16_max() {
457 let v: VarInt = u16::MAX.into();
458 assert_eq!(v.into_inner(), u16::MAX as u64);
459 }
460
461 #[test]
462 fn from_u32_into_varint() {
463 let v: VarInt = 42u32.into();
464 assert_eq!(v.into_inner(), 42);
465 }
466
467 #[test]
468 fn from_u32_max() {
469 let v: VarInt = u32::MAX.into();
470 assert_eq!(v.into_inner(), u32::MAX as u64);
471 }
472
473 #[test]
476 fn try_from_u64_valid() {
477 let v = VarInt::try_from(42u64).unwrap();
478 assert_eq!(v.into_inner(), 42);
479 }
480
481 #[test]
482 fn try_from_u64_too_large() {
483 let result = VarInt::try_from(1u64 << 62);
484 assert!(result.is_err());
485 assert_eq!(result.unwrap_err(), VarIntBoundsExceeded);
486 }
487
488 #[test]
489 fn try_from_u128_valid() {
490 use std::convert::TryFrom;
491 let v = VarInt::try_from(42u128).unwrap();
492 assert_eq!(v.into_inner(), 42);
493 }
494
495 #[test]
496 fn try_from_u128_too_large() {
497 use std::convert::TryFrom;
498 let result = VarInt::try_from((1u128 << 62) + 1);
499 assert!(result.is_err());
500 }
501
502 #[test]
503 fn try_from_u128_overflow_u64() {
504 use std::convert::TryFrom;
505 let result = VarInt::try_from(u128::MAX);
506 assert!(result.is_err());
507 }
508
509 #[test]
510 fn try_from_usize_valid() {
511 use std::convert::TryFrom;
512 let v = VarInt::try_from(42usize).unwrap();
513 assert_eq!(v.into_inner(), 42);
514 }
515
516 #[test]
517 fn try_from_usize_large() {
518 use std::convert::TryFrom;
519 let result = VarInt::try_from(usize::try_from(1u128 << 62).unwrap_or(usize::MAX));
521 if usize::BITS >= 62 {
522 assert!(result.is_err());
523 }
524 }
525
526 #[test]
529 fn varint_default_is_zero() {
530 let v = VarInt::default();
531 assert_eq!(v.into_inner(), 0);
532 }
533
534 #[test]
537 fn display_works() {
538 let v = VarInt::from_u32(42);
539 assert_eq!(format!("{v}"), "42");
540 }
541
542 #[test]
543 fn display_large_value() {
544 let v = VarInt::from_u64(1_000_000_000_000).unwrap();
545 assert_eq!(format!("{v}"), "1000000000000");
546 }
547
548 #[test]
549 fn debug_works() {
550 let v = VarInt::from_u32(42);
551 assert_eq!(format!("{v:?}"), "42");
552 }
553
554 #[test]
557 fn ordering_less() {
558 let a = VarInt::from_u32(10);
559 let b = VarInt::from_u32(20);
560 assert!(a < b);
561 assert!(b > a);
562 assert_eq!(a.min(b), a);
563 assert_eq!(a.max(b), b);
564 }
565
566 #[test]
567 fn ordering_equal() {
568 let a = VarInt::from_u32(10);
569 let b = VarInt::from_u32(10);
570 assert_eq!(a, b);
571 assert!(a >= b);
572 }
573
574 #[test]
575 fn ordering_zero_vs_nonzero() {
576 assert!(VarInt::from_u32(0) < VarInt::from_u32(1));
577 }
578
579 #[test]
582 fn hash_consistent() {
583 use std::collections::hash_map::DefaultHasher;
584 use std::hash::{Hash, Hasher};
585
586 let a = VarInt::from_u32(42);
587 let b = VarInt::from_u32(42);
588 let mut ha = DefaultHasher::new();
589 let mut hb = DefaultHasher::new();
590 a.hash(&mut ha);
591 b.hash(&mut hb);
592 assert_eq!(ha.finish(), hb.finish());
593 }
594
595 #[test]
596 fn hash_different_values_different() {
597 use std::collections::hash_map::DefaultHasher;
598 use std::hash::{Hash, Hasher};
599
600 let a = VarInt::from_u32(1);
603 let b = VarInt::from_u32(2);
604 let mut ha = DefaultHasher::new();
605 let mut hb = DefaultHasher::new();
606 a.hash(&mut ha);
607 b.hash(&mut hb);
608 let _ = ha.finish();
610 let _ = hb.finish();
611 }
612
613 #[test]
616 fn bounds_exceeded_display() {
617 assert_eq!(
618 format!("{}", VarIntBoundsExceeded),
619 "value too large for varint encoding"
620 );
621 }
622
623 #[test]
624 fn bounds_exceeded_debug() {
625 let debug = format!("{:?}", VarIntBoundsExceeded);
626 assert!(debug.contains("VarIntBoundsExceeded"));
627 }
628
629 #[test]
630 fn bounds_exceeded_clone() {
631 let a = VarIntBoundsExceeded;
632 let b = a;
633 assert_eq!(a, b);
634 }
635
636 #[test]
637 fn bounds_exceeded_equality() {
638 assert_eq!(VarIntBoundsExceeded, VarIntBoundsExceeded);
639 }
640
641 #[test]
644 fn varint_copy() {
645 let a = VarInt::from_u32(42);
646 let b = a; assert_eq!(a, b); }
649
650 #[test]
651 fn varint_clone_is_copy() {
652 let a = VarInt::from_u32(42);
653 let b = a;
654 assert_eq!(a, b);
655 }
656
657 #[test]
660 fn varint_max_is_below_threshold() {
661 assert!(VarInt::MAX.into_inner() < (1u64 << 62));
663 assert!(VarInt::MAX.into_inner() + 1 >= (1u64 << 62));
665 }
666
667 #[test]
668 fn varint_from_u64_max_valid_is_max() {
669 let v = VarInt::from_u64(VarInt::MAX.into_inner()).unwrap();
670 assert_eq!(v, VarInt::MAX);
671 }
672
673 #[test]
674 fn varint_from_u64_min_invalid_is_plus_one() {
675 let min_invalid = VarInt::MAX.into_inner() + 1;
676 assert!(min_invalid >= (1u64 << 62));
677 assert!(VarInt::from_u64(min_invalid).is_err());
678 }
679
680 #[test]
683 fn decode_known_1_byte_wire_format() {
684 let buf = [0x2A];
686 let mut read = &buf[..];
687 let decoded = VarInt::decode(&mut read).unwrap();
688 assert_eq!(decoded.into_inner(), 42);
689 }
690
691 #[test]
692 fn decode_known_2_byte_wire_format() {
693 let buf = [0x40, 0x01];
696 let mut read = &buf[..];
697 let decoded = VarInt::decode(&mut read).unwrap();
698 assert_eq!(decoded.into_inner(), 1);
699 }
700
701 #[test]
702 fn decode_known_4_byte_wire_format() {
703 let buf = [0x80, 0x00, 0x40, 0x00];
705 let mut read = &buf[..];
706 let decoded = VarInt::decode(&mut read).unwrap();
707 assert_eq!(decoded.into_inner(), 16384);
708 }
709
710 #[test]
711 fn decode_known_8_byte_wire_format() {
712 let buf = [0xC0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00];
714 let mut read = &buf[..];
715 let decoded = VarInt::decode(&mut read).unwrap();
716 assert_eq!(decoded.into_inner(), 1_073_741_824);
717 }
718}
719
720impl Codec for VarInt {
721 fn decode<B: Buf>(r: &mut B) -> coding::Result<Self> {
722 if !r.has_remaining() {
723 return Err(UnexpectedEnd);
724 }
725 let mut buf = [0; 8];
726 buf[0] = r.get_u8();
727 let tag = buf[0] >> 6;
728 buf[0] &= 0b0011_1111;
729 let x = match tag {
730 0b00 => u64::from(buf[0]),
731 0b01 => {
732 if r.remaining() < 1 {
733 return Err(UnexpectedEnd);
734 }
735 r.copy_to_slice(&mut buf[1..2]);
736 u64::from(u16::from_be_bytes([buf[0], buf[1]]))
738 }
739 0b10 => {
740 if r.remaining() < 3 {
741 return Err(UnexpectedEnd);
742 }
743 r.copy_to_slice(&mut buf[1..4]);
744 u64::from(u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]))
746 }
747 0b11 => {
748 if r.remaining() < 7 {
749 return Err(UnexpectedEnd);
750 }
751 r.copy_to_slice(&mut buf[1..8]);
752 u64::from_be_bytes(buf)
753 }
754 _ => unreachable!(),
755 };
756 Ok(Self(x))
757 }
758
759 fn encode<B: BufMut>(&self, w: &mut B) {
760 if let Err(_) = Self::encode_checked(self.0, w) {
761 tracing::error!("VarInt overflow: {} exceeds maximum", self.0);
762 debug_assert!(false, "VarInt overflow: {}", self.0);
763 }
764 }
765}