1use std::convert::{TryFrom, TryInto};
6use std::fmt;
7
8use thiserror::Error;
9
10use super::{Decode, DecodeError, Encode, EncodeError};
11
12#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
14#[error("value out of range")]
15pub struct BoundsExceeded;
16
17#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
23pub struct VarInt(u64);
24
25impl VarInt {
26 pub const MAX: Self = Self((1 << 62) - 1);
28
29 pub const ZERO: Self = Self(0);
31
32 pub const fn from_u32(x: u32) -> Self {
35 Self(x as u64)
36 }
37
38 pub const fn from_u64(x: u64) -> Option<Self> {
40 if x <= Self::MAX.0 { Some(Self(x)) } else { None }
41 }
42
43 pub const fn from_u128(x: u128) -> Option<Self> {
45 if x <= Self::MAX.0 as u128 {
46 Some(Self(x as u64))
47 } else {
48 None
49 }
50 }
51
52 pub const fn into_inner(self) -> u64 {
54 self.0
55 }
56
57 pub const fn from_zigzag(signed: i64) -> Result<Self, BoundsExceeded> {
63 const RANGE: i64 = 1 << 61;
64 if signed < -RANGE || signed >= RANGE {
65 return Err(BoundsExceeded);
66 }
67 Ok(Self(((signed << 1) ^ (signed >> 63)) as u64))
68 }
69
70 pub const fn to_zigzag(self) -> i64 {
72 let v = self.0;
73 ((v >> 1) as i64) ^ -((v & 1) as i64)
74 }
75}
76
77impl From<VarInt> for u64 {
78 fn from(x: VarInt) -> Self {
79 x.0
80 }
81}
82
83impl From<VarInt> for usize {
84 fn from(x: VarInt) -> Self {
85 x.0 as usize
86 }
87}
88
89impl From<VarInt> for u128 {
90 fn from(x: VarInt) -> Self {
91 x.0 as u128
92 }
93}
94
95impl From<u8> for VarInt {
96 fn from(x: u8) -> Self {
97 Self(x.into())
98 }
99}
100
101impl From<u16> for VarInt {
102 fn from(x: u16) -> Self {
103 Self(x.into())
104 }
105}
106
107impl From<u32> for VarInt {
108 fn from(x: u32) -> Self {
109 Self(x.into())
110 }
111}
112
113impl TryFrom<u64> for VarInt {
114 type Error = BoundsExceeded;
115
116 fn try_from(x: u64) -> Result<Self, BoundsExceeded> {
118 let x = Self(x);
119 if x <= Self::MAX { Ok(x) } else { Err(BoundsExceeded) }
120 }
121}
122
123impl TryFrom<u128> for VarInt {
124 type Error = BoundsExceeded;
125
126 fn try_from(x: u128) -> Result<Self, BoundsExceeded> {
128 if x <= Self::MAX.into() {
129 Ok(Self(x as u64))
130 } else {
131 Err(BoundsExceeded)
132 }
133 }
134}
135
136impl TryFrom<usize> for VarInt {
137 type Error = BoundsExceeded;
138
139 fn try_from(x: usize) -> Result<Self, BoundsExceeded> {
141 Self::try_from(x as u64)
142 }
143}
144
145impl TryFrom<VarInt> for u32 {
146 type Error = BoundsExceeded;
147
148 fn try_from(x: VarInt) -> Result<Self, BoundsExceeded> {
150 if x.0 <= u32::MAX.into() {
151 Ok(x.0 as u32)
152 } else {
153 Err(BoundsExceeded)
154 }
155 }
156}
157
158impl TryFrom<VarInt> for u16 {
159 type Error = BoundsExceeded;
160
161 fn try_from(x: VarInt) -> Result<Self, BoundsExceeded> {
163 if x.0 <= u16::MAX.into() {
164 Ok(x.0 as u16)
165 } else {
166 Err(BoundsExceeded)
167 }
168 }
169}
170
171impl TryFrom<VarInt> for u8 {
172 type Error = BoundsExceeded;
173
174 fn try_from(x: VarInt) -> Result<Self, BoundsExceeded> {
176 if x.0 <= u8::MAX.into() {
177 Ok(x.0 as u8)
178 } else {
179 Err(BoundsExceeded)
180 }
181 }
182}
183
184impl fmt::Display for VarInt {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 self.0.fmt(f)
187 }
188}
189
190impl VarInt {
191 pub fn decode_quic<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
193 if !r.has_remaining() {
194 return Err(DecodeError::Short);
195 }
196
197 let b = r.get_u8();
198 let tag = b >> 6;
199
200 let mut buf = [0u8; 8];
201 buf[0] = b & 0b0011_1111;
202
203 let x = match tag {
204 0b00 => u64::from(buf[0]),
205 0b01 => {
206 if !r.has_remaining() {
207 return Err(DecodeError::Short);
208 }
209 r.copy_to_slice(buf[1..2].as_mut());
210 u64::from(u16::from_be_bytes(buf[..2].try_into().unwrap()))
211 }
212 0b10 => {
213 if r.remaining() < 3 {
214 return Err(DecodeError::Short);
215 }
216 r.copy_to_slice(buf[1..4].as_mut());
217 u64::from(u32::from_be_bytes(buf[..4].try_into().unwrap()))
218 }
219 0b11 => {
220 if r.remaining() < 7 {
221 return Err(DecodeError::Short);
222 }
223 r.copy_to_slice(buf[1..8].as_mut());
224 u64::from_be_bytes(buf)
225 }
226 _ => unreachable!(),
227 };
228
229 Ok(Self(x))
230 }
231
232 pub fn encode_quic<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
234 let remaining = w.remaining_mut();
235 if self.0 < (1u64 << 6) {
236 if remaining < 1 {
237 return Err(EncodeError::Short);
238 }
239 w.put_u8(self.0 as u8);
240 } else if self.0 < (1u64 << 14) {
241 if remaining < 2 {
242 return Err(EncodeError::Short);
243 }
244 w.put_u16((0b01 << 14) | self.0 as u16);
245 } else if self.0 < (1u64 << 30) {
246 if remaining < 4 {
247 return Err(EncodeError::Short);
248 }
249 w.put_u32((0b10 << 30) | self.0 as u32);
250 } else if self.0 < (1u64 << 62) {
251 if remaining < 8 {
252 return Err(EncodeError::Short);
253 }
254 w.put_u64((0b11 << 62) | self.0);
255 } else {
256 return Err(BoundsExceeded.into());
257 }
258 Ok(())
259 }
260
261 fn decode_leading_ones<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
274 if !r.has_remaining() {
275 return Err(DecodeError::Short);
276 }
277
278 let b = r.get_u8();
279 let ones = b.leading_ones() as usize;
280
281 match ones {
282 0 => {
283 Ok(Self(u64::from(b)))
285 }
286 1 => {
287 if !r.has_remaining() {
289 return Err(DecodeError::Short);
290 }
291 let hi = u64::from(b & 0x3F);
292 let lo = u64::from(r.get_u8());
293 Ok(Self((hi << 8) | lo))
294 }
295 2 => {
296 if r.remaining() < 2 {
298 return Err(DecodeError::Short);
299 }
300 let hi = u64::from(b & 0x1F);
301 let mut buf = [0u8; 2];
302 r.copy_to_slice(&mut buf);
303 Ok(Self((hi << 16) | u64::from(u16::from_be_bytes(buf))))
304 }
305 3 => {
306 if r.remaining() < 3 {
308 return Err(DecodeError::Short);
309 }
310 let hi = u64::from(b & 0x0F);
311 let mut buf = [0u8; 3];
312 r.copy_to_slice(&mut buf);
313 Ok(Self(
314 (hi << 24) | u64::from(buf[0]) << 16 | u64::from(buf[1]) << 8 | u64::from(buf[2]),
315 ))
316 }
317 4 => {
318 if r.remaining() < 4 {
320 return Err(DecodeError::Short);
321 }
322 let hi = u64::from(b & 0x07);
323 let mut buf = [0u8; 4];
324 r.copy_to_slice(&mut buf);
325 Ok(Self((hi << 32) | u64::from(u32::from_be_bytes(buf))))
326 }
327 5 => {
328 if r.remaining() < 5 {
330 return Err(DecodeError::Short);
331 }
332 let hi = u64::from(b & 0x03);
333 let mut buf = [0u8; 5];
334 r.copy_to_slice(&mut buf);
335 let lo = u64::from(buf[0]) << 32
336 | u64::from(buf[1]) << 24
337 | u64::from(buf[2]) << 16
338 | u64::from(buf[3]) << 8
339 | u64::from(buf[4]);
340 Ok(Self((hi << 40) | lo))
341 }
342 6 => {
343 if r.remaining() < 6 {
345 return Err(DecodeError::Short);
346 }
347 let hi = u64::from(b & 0x01);
348 let mut buf = [0u8; 8];
349 r.copy_to_slice(&mut buf[2..]);
350 Ok(Self((hi << 48) | u64::from_be_bytes(buf)))
351 }
352 7 => {
353 if r.remaining() < 7 {
355 return Err(DecodeError::Short);
356 }
357 let mut buf = [0u8; 8];
358 buf[0] = 0;
359 r.copy_to_slice(&mut buf[1..]);
360 Ok(Self(u64::from_be_bytes(buf)))
361 }
362 8 => {
363 if r.remaining() < 8 {
365 return Err(DecodeError::Short);
366 }
367 let mut buf = [0u8; 8];
368 r.copy_to_slice(&mut buf);
369 Ok(Self(u64::from_be_bytes(buf)))
370 }
371 _ => unreachable!(),
372 }
373 }
374
375 fn encode_leading_ones<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
381 let x = self.0;
382 let remaining = w.remaining_mut();
383
384 if x < (1 << 7) {
385 if remaining < 1 {
387 return Err(EncodeError::Short);
388 }
389 w.put_u8(x as u8);
390 } else if x < (1 << 14) {
391 if remaining < 2 {
393 return Err(EncodeError::Short);
394 }
395 w.put_u8(0x80 | (x >> 8) as u8);
396 w.put_u8(x as u8);
397 } else if x < (1 << 21) {
398 if remaining < 3 {
400 return Err(EncodeError::Short);
401 }
402 w.put_u8(0xC0 | (x >> 16) as u8);
403 w.put_u16(x as u16);
404 } else if x < (1 << 28) {
405 if remaining < 4 {
407 return Err(EncodeError::Short);
408 }
409 w.put_u8(0xE0 | (x >> 24) as u8);
410 w.put_u8((x >> 16) as u8);
411 w.put_u16(x as u16);
412 } else if x < (1 << 35) {
413 if remaining < 5 {
415 return Err(EncodeError::Short);
416 }
417 w.put_u8(0xF0 | (x >> 32) as u8);
418 w.put_u32(x as u32);
419 } else if x < (1 << 42) {
420 if remaining < 6 {
422 return Err(EncodeError::Short);
423 }
424 w.put_u8(0xF8 | (x >> 40) as u8);
425 w.put_u8((x >> 32) as u8);
426 w.put_u32(x as u32);
427 } else if x < (1 << 56) {
428 if remaining < 8 {
430 return Err(EncodeError::Short);
431 }
432 w.put_u8(0xFE);
433 w.put_u8((x >> 48) as u8);
435 w.put_u16((x >> 32) as u16);
436 w.put_u32(x as u32);
437 } else {
438 if remaining < 9 {
440 return Err(EncodeError::Short);
441 }
442 w.put_u8(0xFF);
443 w.put_u64(x);
444 }
445
446 Ok(())
447 }
448}
449
450use crate::{Version, ietf, lite};
451
452impl Encode<lite::Version> for VarInt {
455 fn encode<W: bytes::BufMut>(&self, w: &mut W, version: lite::Version) -> Result<(), EncodeError> {
456 match version {
457 lite::Version::Lite01
458 | lite::Version::Lite02
459 | lite::Version::Lite03
460 | lite::Version::Lite04
461 | lite::Version::Lite05
462 | lite::Version::Lite06 => self.encode_quic(w),
463 _ => self.encode_leading_ones(w),
464 }
465 }
466}
467
468impl Decode<lite::Version> for VarInt {
469 fn decode<R: bytes::Buf>(r: &mut R, version: lite::Version) -> Result<Self, DecodeError> {
470 match version {
471 lite::Version::Lite01
472 | lite::Version::Lite02
473 | lite::Version::Lite03
474 | lite::Version::Lite04
475 | lite::Version::Lite05
476 | lite::Version::Lite06 => Self::decode_quic(r),
477 _ => match Self::decode_leading_ones(r)? {
481 x if x > Self::MAX => Err(DecodeError::BoundsExceeded),
482 x => Ok(x),
483 },
484 }
485 }
486}
487
488impl Encode<ietf::Version> for VarInt {
490 fn encode<W: bytes::BufMut>(&self, w: &mut W, version: ietf::Version) -> Result<(), EncodeError> {
491 match version {
492 ietf::Version::Draft14 | ietf::Version::Draft15 | ietf::Version::Draft16 => self.encode_quic(w),
493 _ => self.encode_leading_ones(w),
494 }
495 }
496}
497
498impl Decode<ietf::Version> for VarInt {
499 fn decode<R: bytes::Buf>(r: &mut R, version: ietf::Version) -> Result<Self, DecodeError> {
500 match version {
501 ietf::Version::Draft14 | ietf::Version::Draft15 | ietf::Version::Draft16 => Self::decode_quic(r),
502 ietf::Version::Draft17 if r.chunk().first().is_some_and(|b| b.leading_ones() == 6) => {
504 Err(DecodeError::InvalidValue)
505 }
506 _ => Self::decode_leading_ones(r),
507 }
508 }
509}
510
511impl Encode<Version> for VarInt {
513 fn encode<W: bytes::BufMut>(&self, w: &mut W, version: Version) -> Result<(), EncodeError> {
514 match version {
515 Version::Lite(v) => self.encode(w, v),
516 Version::Ietf(v) => self.encode(w, v),
517 }
518 }
519}
520
521impl Decode<Version> for VarInt {
522 fn decode<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
523 match version {
524 Version::Lite(v) => Self::decode(r, v),
525 Version::Ietf(v) => Self::decode(r, v),
526 }
527 }
528}
529
530impl<V: Copy> Encode<V> for u64
532where
533 VarInt: Encode<V>,
534{
535 fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
536 VarInt::try_from(*self)?.encode(w, version)
537 }
538}
539
540impl<V: Copy> Decode<V> for u64
541where
542 VarInt: Decode<V>,
543{
544 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
545 VarInt::decode(r, version).map(|v| v.into_inner())
546 }
547}
548
549impl<V: Copy> Encode<V> for usize
550where
551 VarInt: Encode<V>,
552{
553 fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
554 VarInt::try_from(*self)?.encode(w, version)
555 }
556}
557
558impl<V: Copy> Decode<V> for usize
559where
560 VarInt: Decode<V>,
561{
562 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
563 let v = VarInt::decode(r, version)?;
565 v.into_inner().try_into().map_err(|_| DecodeError::BoundsExceeded)
566 }
567}
568
569impl<V: Copy> Encode<V> for u32
570where
571 VarInt: Encode<V>,
572{
573 fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) -> Result<(), EncodeError> {
574 VarInt::from(*self).encode(w, version)
575 }
576}
577
578impl<V: Copy> Decode<V> for u32
579where
580 VarInt: Decode<V>,
581{
582 fn decode<R: bytes::Buf>(r: &mut R, version: V) -> Result<Self, DecodeError> {
583 let v = VarInt::decode(r, version)?;
584 let v = v.try_into().map_err(|_| DecodeError::BoundsExceeded)?;
585 Ok(v)
586 }
587}
588
589#[cfg(test)]
590mod tests {
591 use super::*;
592 use crate::{ietf, lite};
593 use bytes::Bytes;
594
595 #[test]
598 fn leading_ones_spec_examples() {
599 let cases: &[(&[u8], u64)] = &[
600 (&[0x25], 37),
601 (&[0x80, 0x25], 37),
602 (&[0xbb, 0xbd], 15_293),
603 (&[0xfa, 0xa1, 0xa0, 0xe4, 0x03, 0xd8], 2_893_212_287_960),
606 (
607 &[0xfe, 0xfa, 0x31, 0x8f, 0xa8, 0xe3, 0xca, 0x11],
608 70_423_237_261_249_041,
609 ),
610 (
611 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
612 18_446_744_073_709_551_615,
613 ),
614 ];
615
616 for (bytes, expected) in cases {
617 let mut buf = Bytes::from(bytes.to_vec());
619 let decoded = VarInt::decode_leading_ones(&mut buf).expect("decode should succeed");
620 assert_eq!(
621 decoded.into_inner(),
622 *expected,
623 "decode mismatch for bytes {bytes:02x?}"
624 );
625 assert_eq!(buf.len(), 0, "all bytes should be consumed for {bytes:02x?}");
626
627 if let Some(varint) = VarInt::from_u64(*expected)
631 && (bytes.len() == 1 || *expected != 37)
632 {
633 let mut encoded = Vec::new();
634 varint.encode_leading_ones(&mut encoded).expect("encode should succeed");
635 assert_eq!(&encoded, bytes, "encode mismatch for value {expected}");
636 }
637 }
638 }
639
640 #[test]
642 fn leading_ones_invalid_0xfc() {
643 let mut buf = Bytes::from_static(&[0xFC]);
644 assert!(
645 matches!(
646 VarInt::decode(&mut buf, ietf::Version::Draft17),
647 Err(DecodeError::InvalidValue)
648 ),
649 "0xFC should be rejected as invalid on draft-17"
650 );
651 }
652
653 #[test]
654 fn leading_ones_boundaries_round_trip() {
655 let cases = [
656 ((1u64 << 7) - 1, 1usize),
657 (1u64 << 7, 2usize),
658 ((1u64 << 14) - 1, 2usize),
659 (1u64 << 14, 3usize),
660 ((1u64 << 56) - 1, 8usize),
661 (1u64 << 56, 9usize),
662 ];
663
664 for (value, expected_len) in cases {
665 let varint = VarInt::from_u64(value).expect("value should be representable as VarInt");
666 let mut encoded = Vec::new();
667 varint
668 .encode_leading_ones(&mut encoded)
669 .expect("leading-ones encode should succeed");
670 assert_eq!(
671 encoded.len(),
672 expected_len,
673 "unexpected encoded length for value {value}"
674 );
675
676 let mut bytes = Bytes::from(encoded);
677 let decoded = VarInt::decode_leading_ones(&mut bytes).expect("leading-ones decode should succeed");
678 assert_eq!(decoded.into_inner(), value, "round-trip mismatch for value {value}");
679 }
680 }
681
682 #[test]
683 fn draft17_rejects_7_byte_varint() {
684 let bytes = Bytes::from(vec![0xFC, 0, 0, 0, 0, 0, 0]);
686 let mut buf = bytes.clone();
687 let err = VarInt::decode(&mut buf, ietf::Version::Draft17).unwrap_err();
688 assert!(matches!(err, DecodeError::InvalidValue));
689 }
690
691 #[test]
692 fn zigzag_roundtrip_small() {
693 for n in [-3i64, -2, -1, 0, 1, 2, 3, 100, -100] {
694 let v = VarInt::from_zigzag(n).unwrap();
695 assert_eq!(v.to_zigzag(), n, "roundtrip failed for {}", n);
696 }
697 }
698
699 #[test]
700 fn zigzag_small_values_compact() {
701 assert_eq!(VarInt::from_zigzag(0).unwrap().into_inner(), 0);
703 assert_eq!(VarInt::from_zigzag(-1).unwrap().into_inner(), 1);
704 assert_eq!(VarInt::from_zigzag(1).unwrap().into_inner(), 2);
705 assert_eq!(VarInt::from_zigzag(-2).unwrap().into_inner(), 3);
706 assert_eq!(VarInt::from_zigzag(2).unwrap().into_inner(), 4);
707 }
708
709 #[test]
710 fn zigzag_roundtrip_boundary() {
711 let max = (1i64 << 61) - 1;
713 let min = -(1i64 << 61);
714 let mid = (1i64 << 30) + 17;
715
716 for n in [max, min, mid, -mid] {
717 let v = VarInt::from_zigzag(n).unwrap();
718 assert_eq!(v.to_zigzag(), n);
719 }
720 }
721
722 #[test]
723 fn zigzag_out_of_range_rejected() {
724 assert!(VarInt::from_zigzag(1i64 << 61).is_err());
726 assert!(VarInt::from_zigzag(-(1i64 << 61) - 1).is_err());
727 assert!(VarInt::from_zigzag(i64::MAX).is_err());
728 assert!(VarInt::from_zigzag(i64::MIN).is_err());
729 }
730
731 #[test]
732 fn zigzag_quic_varint_roundtrip() {
733 for n in [-5000i64, 0, 100, -1, 1_000_000, -1_000_000] {
735 let v = VarInt::from_zigzag(n).unwrap();
736
737 let mut buf = bytes::BytesMut::new();
738 v.encode(&mut buf, lite::Version::Lite01).unwrap();
739 let mut bytes = buf.freeze();
740 let decoded = VarInt::decode(&mut bytes, lite::Version::Lite01).unwrap();
741 assert_eq!(decoded.to_zigzag(), n);
742 }
743 }
744
745 fn lite(value: u64, version: lite::Version) -> Vec<u8> {
746 let mut buf = Vec::new();
747 VarInt::try_from(value).unwrap().encode(&mut buf, version).unwrap();
748 buf
749 }
750
751 #[test]
753 fn lite06_keeps_quic_varints() {
754 for version in [lite::Version::Lite01, lite::Version::Lite05, lite::Version::Lite06] {
755 assert_eq!(lite(63, version), [0x3F]);
756 assert_eq!(lite(64, version), [0x40, 0x40]);
757 assert_eq!(lite(16_384, version), [0x80, 0x00, 0x40, 0x00]);
758 }
759 }
760
761 #[test]
763 fn lite07_uses_leading_ones() {
764 let version = lite::Version::Lite07;
765 let cases: &[(u64, &[u8])] = &[
766 (0, &[0x00]),
767 (127, &[0x7F]),
768 (128, &[0x80, 0x80]),
769 ((1 << 14) - 1, &[0xBF, 0xFF]),
770 (1 << 14, &[0xC0, 0x40, 0x00]),
771 ((1 << 21) - 1, &[0xDF, 0xFF, 0xFF]),
772 (1 << 21, &[0xE0, 0x20, 0x00, 0x00]),
773 ((1 << 56) - 1, &[0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]),
774 (1 << 56, &[0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
775 (
776 VarInt::MAX.into_inner(),
777 &[0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
778 ),
779 ];
780 for (value, wire) in cases {
781 assert_eq!(lite(*value, version), *wire, "encode {value}");
782 let mut buf = *wire;
783 assert_eq!(VarInt::decode(&mut buf, version).unwrap().into_inner(), *value);
784 assert!(buf.is_empty());
785 }
786 }
787
788 #[test]
790 fn lite07_accepts_7_byte_varint() {
791 let mut buf: &[u8] = &[0xFD, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD];
792 let decoded = VarInt::decode(&mut buf, lite::Version::Lite07).unwrap();
793 assert_eq!(decoded.into_inner(), 0x1_2345_6789_ABCD);
794 }
795
796 #[test]
799 fn lite07_values_above_62_bits_fail_loud() {
800 for wire in [[0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0xFF; 9]] {
801 let err = VarInt::decode(&mut &wire[..], lite::Version::Lite07).unwrap_err();
802 assert!(matches!(err, DecodeError::BoundsExceeded), "{wire:02x?}: {err:?}");
803 }
804 }
805
806 #[test]
807 fn draft18_accepts_7_byte_varint() {
808 let value: u64 = 0x1234_5678_9ABC;
810 let mut bytes = Vec::new();
811 let hi_bit = ((value >> 48) & 0x01) as u8;
814 bytes.push(0xFC | hi_bit);
815 for shift in (0..48).step_by(8).rev() {
816 bytes.push(((value >> shift) & 0xFF) as u8);
817 }
818 let mut buf = Bytes::from(bytes);
819 let decoded = VarInt::decode(&mut buf, ietf::Version::Draft18).unwrap();
820 assert_eq!(decoded.into_inner(), value);
821 }
822}