1#![doc = include_str!("../README.md")]
2#![no_std]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(docsrs, allow(unused_attributes))]
5#![deny(missing_docs)]
6
7use core::{num::NonZeroU64, ops::RangeInclusive};
8
9pub use char::*;
10pub use duration::*;
11
12mod char;
13mod duration;
14
15macro_rules! impl_varint {
16 ($($ty:literal), +$(,)?) => {
17 $(
18 paste::paste! {
19 impl Varint for [< u $ty >] {
20 const MIN_ENCODED_LEN: usize = [< encoded_ u $ty _varint_len >](0);
21 const MAX_ENCODED_LEN: usize = [< encoded_ u $ty _varint_len >](<[< u $ty >]>::MAX);
22
23 #[inline]
24 fn encoded_len(&self) -> usize {
25 [< encoded_ u $ty _varint_len >](*self)
26 }
27
28 fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
29 [< encode_ u $ty _varint_to >](*self, buf)
30 }
31
32 #[inline]
33 fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError> {
34 [< decode_ u $ty _varint >](buf)
35 }
36 }
37
38 impl Varint for [< i $ty >] {
39 const MIN_ENCODED_LEN: usize = [< encoded_ i $ty _varint_len >](0);
40 const MAX_ENCODED_LEN: usize = [< encoded_ i $ty _varint_len >](<[< i $ty >]>::MAX);
41
42 #[inline]
43 fn encoded_len(&self) -> usize {
44 [< encoded_ i $ty _varint_len >](*self)
45 }
46
47 fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
48 [< encode_ i $ty _varint_to >](*self, buf)
49 }
50
51 #[inline]
52 fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError> {
53 [< decode_ i $ty _varint >](buf)
54 }
55 }
56 }
57 )*
58 };
59}
60
61macro_rules! decode_varint {
62 (|$buf:ident| $ty:ident) => {{
63 let mut result = 0;
64 let mut shift = 0;
65 let mut index = 0;
66
67 loop {
68 if index == $ty::MAX_ENCODED_LEN {
69 return Err(DecodeError::Overflow);
70 }
71
72 if index >= $buf.len() {
73 return Err(DecodeError::Underflow);
74 }
75
76 let next = $buf[index] as $ty;
77
78 let v = $ty::BITS as usize / 7 * 7;
79 let has_overflow = if shift < v {
80 false
81 } else if shift == v {
82 next & ((u8::MAX << (::core::mem::size_of::<$ty>() % 7)) as $ty) != 0
83 } else {
84 true
85 };
86
87 if has_overflow {
88 return Err(DecodeError::Overflow);
89 }
90
91 result += (next & 0x7F) << shift;
92 if next & 0x80 == 0 {
93 break;
94 }
95 shift += 7;
96 index += 1;
97 }
98 Ok((index + 1, result))
99 }};
100}
101
102macro_rules! encode_varint {
103 ($buf:ident[$x:ident]) => {{
104 let mut i = 0;
105
106 while $x >= 0x80 {
107 if i >= $buf.len() {
108 panic!("insufficient buffer capacity");
109 }
110
111 $buf[i] = ($x as u8) | 0x80;
112 $x >>= 7;
113 i += 1;
114 }
115
116 if i >= $buf.len() {
118 panic!("insufficient buffer capacity");
119 }
120
121 $buf[i] = $x as u8;
122 i + 1
123 }};
124 (@to_buf $ty:ident::$buf:ident[$x:ident]) => {{
125 paste::paste! {
126 let mut i = 0;
127 let orig = $x;
128
129 while $x >= 0x80 {
130 if i >= $buf.len() {
131 return Err(EncodeError::underflow([< encoded_ $ty _varint_len >](orig), $buf.len()));
132 }
133
134 $buf[i] = ($x as u8) | 0x80;
135 $x >>= 7;
136 i += 1;
137 }
138
139 if i >= $buf.len() {
141 return Err(EncodeError::underflow(i + 1, $buf.len()));
142 }
143
144 $buf[i] = $x as u8;
145 Ok(i + 1)
146 }
147 }};
148}
149
150macro_rules! varint_len {
151 ($($ty:ident),+$(,)?) => {
152 $(
153 paste::paste! {
154 #[doc = "The returned value will be in range of [`" $ty "::ENCODED_LEN_RANGE`]."]
156 #[inline]
157 pub const fn [< encoded_ $ty _varint_len >](value: $ty) -> usize {
158 encoded_u64_varint_len(value as u64)
159 }
160 }
161 )*
162 };
163 (@zigzag $($ty:ident),+$(,)?) => {
164 $(
165 paste::paste! {
166 #[doc = "The returned value will be in range of [`" $ty "::ENCODED_LEN_RANGE`]."]
168 #[inline]
169 pub const fn [< encoded_ $ty _varint_len >](value: $ty) -> usize {
170 encoded_i64_varint_len(value as i64)
171 }
172 }
173 )*
174 };
175}
176
177macro_rules! buffer {
178 ($($ty:ident), +$(,)?) => {
179 $(
180 paste::paste! {
181 #[doc = "A buffer for storing LEB128 encoded " $ty " values."]
182 #[derive(Copy, Clone, Eq)]
183 pub struct [< $ty:camel VarintBuffer >]([u8; $ty::MAX_ENCODED_LEN + 1]);
184
185 impl core::fmt::Debug for [< $ty:camel VarintBuffer >] {
186 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187 self.0[..self.len()].fmt(f)
188 }
189 }
190
191 impl PartialEq for [< $ty:camel VarintBuffer >] {
192 fn eq(&self, other: &Self) -> bool {
193 self.as_bytes().eq(other.as_bytes())
194 }
195 }
196
197 impl core::hash::Hash for [< $ty:camel VarintBuffer >] {
198 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
199 self.as_bytes().hash(state)
200 }
201 }
202
203 impl [< $ty:camel VarintBuffer >] {
204 const LAST_INDEX: usize = $ty::MAX_ENCODED_LEN;
205
206 #[allow(dead_code)]
207 #[inline]
208 const fn new(mut val: $ty) -> Self {
209 let mut buf = [0; $ty::MAX_ENCODED_LEN + 1];
210 let mut_buf = &mut buf;
211 let len = encode_varint!(mut_buf[val]);
212 buf[Self::LAST_INDEX] = len as u8;
213 Self(buf)
214 }
215
216 #[inline]
218 #[allow(clippy::len_without_is_empty)]
219 pub const fn len(&self) -> usize {
220 self.0[Self::LAST_INDEX] as usize
221 }
222
223 #[inline]
225 pub const fn as_bytes(&self) -> &[u8] {
226 self.0.split_at(self.len()).0
227 }
228 }
229
230 impl core::ops::Deref for [< $ty:camel VarintBuffer >] {
231 type Target = [u8];
232
233 fn deref(&self) -> &Self::Target {
234 &self.0[..self.len()]
235 }
236 }
237
238 impl core::borrow::Borrow<[u8]> for [< $ty:camel VarintBuffer >] {
239 fn borrow(&self) -> &[u8] {
240 self
241 }
242 }
243
244 impl AsRef<[u8]> for [< $ty:camel VarintBuffer >] {
245 fn as_ref(&self) -> &[u8] {
246 self
247 }
248 }
249 }
250 )*
251 };
252}
253
254macro_rules! encode {
255 ($($ty:literal), +$(,)?) => {
256 $(
257 paste::paste! {
258 #[doc = "Encodes an `u" $ty "` value into LEB128 variable length format, and writes it to the buffer."]
259 #[inline]
260 pub const fn [< encode_ u $ty _varint >](x: [< u $ty >]) -> [< U $ty:camel VarintBuffer >] {
261 [< U $ty:camel VarintBuffer >]::new(x)
262 }
263
264 #[doc = "Encodes an `i" $ty "` value into LEB128 variable length format, and writes it to the buffer."]
265 #[inline]
266 pub const fn [< encode_ i $ty _varint >](x: [< i $ty >]) -> [< I $ty:camel VarintBuffer >] {
267 let x = (x << 1) ^ (x >> ($ty - 1)); [< I $ty:camel VarintBuffer >]([< U $ty:camel VarintBuffer >]::new(x as [< u $ty >]).0)
269 }
270
271 #[doc = "Encodes an `u" $ty "` value into LEB128 variable length format, and writes it to the buffer."]
272 #[inline]
273 pub const fn [< encode_ u $ty _varint_to >](mut x: [< u $ty >], buf: &mut [u8]) -> Result<usize, EncodeError> {
274 encode_varint!(@to_buf [< u $ty >]::buf[x])
275 }
276
277 #[doc = "Encodes an `i" $ty "` value into LEB128 variable length format, and writes it to the buffer."]
278 #[inline]
279 pub const fn [< encode_ i $ty _varint_to >](x: [< i $ty >], buf: &mut [u8]) -> Result<usize, EncodeError> {
280 let mut x = {
281 ((x << 1) ^ (x >> ($ty - 1))) as [< u $ty >]
283 };
284 encode_varint!(@to_buf [<u $ty>]::buf[x])
285 }
286 }
287 )*
288 };
289}
290
291macro_rules! decode {
292 ($($ty:literal), + $(,)?) => {
293 $(
294 paste::paste! {
295 #[doc = "Decodes an `i" $ty "` in LEB128 encoded format from the buffer."]
296 pub const fn [< decode_ u $ty _varint >](buf: &[u8]) -> Result<(usize, [< u $ty >]), DecodeError> {
299 decode_varint!(|buf| [< u $ty >])
300 }
301
302 #[doc = "Decodes an `u" $ty "` in LEB128 encoded format from the buffer."]
303 pub const fn [< decode_ i $ty _varint >](buf: &[u8]) -> Result<(usize, [< i $ty >]), DecodeError> {
306 match [< decode_ u $ty _varint >](buf) {
307 Ok((bytes_read, value)) => {
308 let value = ((value >> 1) as [< i $ty >]) ^ { -((value & 1) as [< i $ty >]) }; Ok((bytes_read, value))
310 },
311 Err(e) => Err(e),
312 }
313 }
314 }
315 )*
316 };
317}
318
319impl_varint!(8, 16, 32, 64, 128,);
320varint_len!(u8, u16, u32,);
321varint_len!(@zigzag i8, i16, i32,);
322buffer!(u8, u16, u32, u64, u128, i16, i32, i64, i128);
323encode!(128, 64, 32, 16);
324decode!(128, 64, 32, 16, 8);
325
326#[doc = "Encodes an `u8` value into LEB128 variable length format, and writes it to the buffer."]
327#[inline]
328pub const fn encode_u8_varint_to(mut x: u8, buf: &mut [u8]) -> Result<usize, EncodeError> {
329 encode_varint!(@to_buf u8::buf[x])
330}
331
332#[doc = "Encodes an `i8` value into LEB128 variable length format, and writes it to the buffer."]
333#[inline]
334pub const fn encode_i8_varint_to(orig: i8, buf: &mut [u8]) -> Result<usize, EncodeError> {
335 let mut n = {
336 ((orig << 1) ^ (orig >> 7)) as u8
338 };
339
340 let mut i = 0;
341
342 while n > 0x7F {
343 if i >= buf.len() {
344 return Err(EncodeError::underflow(
345 encoded_i8_varint_len(orig),
346 buf.len(),
347 ));
348 }
349
350 buf[i] = (n & 0x7F) | 0x80;
352 i += 1;
353 n >>= 7;
354 }
355
356 if i >= buf.len() {
358 return Err(EncodeError::underflow(i + 1, buf.len()));
359 }
360
361 buf[i] = n;
362 Ok(i + 1)
363}
364
365#[doc = "Encodes an `u8` value into LEB128 variable length format, and writes it to the buffer."]
366#[inline]
367pub const fn encode_u8_varint(x: u8) -> U8VarintBuffer {
368 U8VarintBuffer::new(x)
369}
370
371#[doc = "Encodes an `i8` value into LEB128 variable length format, and writes it to the buffer."]
372#[inline]
373pub const fn encode_i8_varint(x: i8) -> I8VarintBuffer {
374 let x = (x << 1) ^ (x >> (8 - 1)); I8VarintBuffer(U8VarintBuffer::new(x as u8).0)
376}
377
378pub trait Varint {
384 const MIN_ENCODED_LEN: usize;
391
392 const MAX_ENCODED_LEN: usize;
399
400 const ENCODED_LEN_RANGE: RangeInclusive<usize> = Self::MIN_ENCODED_LEN..=Self::MAX_ENCODED_LEN;
409
410 fn encoded_len(&self) -> usize;
413
414 fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError>;
418
419 fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError>
423 where
424 Self: Sized;
425}
426
427#[inline]
430pub const fn encoded_u128_varint_len(value: u128) -> usize {
431 if value < 128 {
435 return 1;
436 }
437
438 let highest_bit = 128 - value.leading_zeros();
440 highest_bit.div_ceil(7) as usize
443}
444
445#[inline]
448pub const fn encoded_i128_varint_len(x: i128) -> usize {
449 let x = (x << 1) ^ (x >> 127); encoded_u128_varint_len(x as u128)
451}
452
453#[inline]
456pub const fn encoded_i64_varint_len(x: i64) -> usize {
457 let x = (x << 1) ^ (x >> 63); encoded_u64_varint_len(x as u64)
459}
460
461#[inline]
464pub const fn encoded_u64_varint_len(value: u64) -> usize {
465 let log2value = unsafe { NonZeroU64::new_unchecked(value | 1) }.ilog2();
469 ((log2value * 9 + (64 + 9)) / 64) as usize
470}
471
472pub const fn consume_varint(buf: &[u8]) -> Result<usize, DecodeError> {
494 if buf.is_empty() {
495 return Ok(0);
496 }
497
498 let mut idx = 0;
500 let buf_len = buf.len();
501
502 while idx < buf_len {
503 let byte = buf[idx];
504 if byte & 0x80 == 0 {
506 return Ok(idx + 1);
508 }
509
510 if idx == buf_len - 1 {
512 return Err(DecodeError::Underflow);
513 }
514 idx += 1;
515 }
516
517 Err(DecodeError::Underflow)
520}
521
522#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, thiserror::Error)]
524#[non_exhaustive]
525pub enum EncodeError {
526 #[error("buffer does not have enough capacity to encode the value")]
528 Underflow {
529 required: usize,
531 remaining: usize,
533 },
534 #[error("{0}")]
536 Custom(&'static str),
537}
538
539impl EncodeError {
540 #[inline]
542 pub const fn underflow(required: usize, remaining: usize) -> Self {
543 Self::Underflow {
544 required,
545 remaining,
546 }
547 }
548
549 #[inline]
551 pub const fn custom(msg: &'static str) -> Self {
552 Self::Custom(msg)
553 }
554}
555
556#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, thiserror::Error)]
558#[non_exhaustive]
559pub enum DecodeError {
560 #[error("value would overflow the target type")]
562 Overflow,
563 #[error("buffer does not contain enough data to decode a value")]
565 Underflow,
566 #[error("{0}")]
568 Custom(&'static str),
569}
570
571impl DecodeError {
572 #[inline]
574 pub const fn custom(msg: &'static str) -> Self {
575 Self::Custom(msg)
576 }
577}
578
579#[derive(Clone, Copy, PartialEq, Eq)]
581pub struct I8VarintBuffer([u8; i8::MAX_ENCODED_LEN + 1]);
582
583impl core::fmt::Debug for I8VarintBuffer {
584 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
585 self.0[..self.len()].fmt(f)
586 }
587}
588impl I8VarintBuffer {
589 const LAST_INDEX: usize = i8::MAX_ENCODED_LEN;
590 #[allow(dead_code)]
591 #[inline]
592 const fn new(val: i8) -> Self {
593 let mut buf = [0; i8::MAX_ENCODED_LEN + 1];
594 let mut_buf = &mut buf;
595 let len = {
596 let mut n = {
597 ((val << 1) ^ (val >> 7)) as u8
599 };
600
601 let mut i = 0;
602 while n > 0x7F {
603 if i >= mut_buf.len() {
604 panic!("insufficient buffer capacity");
605 }
606
607 mut_buf[i] = (n & 0x7F) | 0x80;
609 i += 1;
610 n >>= 7;
611 }
612
613 if i >= mut_buf.len() {
615 panic!("insufficient buffer capacity");
616 }
617
618 mut_buf[i] = n;
619 i + 1
620 };
621 buf[Self::LAST_INDEX] = len as u8;
622 Self(buf)
623 }
624 #[inline]
626 #[allow(clippy::len_without_is_empty)]
627 pub const fn len(&self) -> usize {
628 self.0[Self::LAST_INDEX] as usize
629 }
630 #[inline]
632 pub const fn as_bytes(&self) -> &[u8] {
633 self.0.split_at(self.len()).0
634 }
635}
636
637impl core::ops::Deref for I8VarintBuffer {
638 type Target = [u8];
639 fn deref(&self) -> &Self::Target {
640 &self.0[..self.len()]
641 }
642}
643impl core::borrow::Borrow<[u8]> for I8VarintBuffer {
644 fn borrow(&self) -> &[u8] {
645 self
646 }
647}
648impl AsRef<[u8]> for I8VarintBuffer {
649 fn as_ref(&self) -> &[u8] {
650 self
651 }
652}
653
654mod non_zero;
655
656#[cfg(feature = "ruint_1")]
657mod ruint_impl;
658
659#[cfg(feature = "arbitrary-int_1")]
661#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary-int")))]
662pub mod arbitrary_int;
663
664#[cfg(feature = "primitive-types_0_13")]
665mod primitive_types;
666
667#[cfg(feature = "ethereum-types_0_15")]
668mod ethereum_types;
669
670#[cfg(test)]
671mod tests {
672 extern crate std;
673
674 use super::*;
675
676 fn check(value: u64, encoded: &[u8]) {
677 let a = encode_u64_varint(value);
678 assert_eq!(a.as_ref(), encoded);
679 assert_eq!(a.len(), encoded.len());
680 assert_eq!(a.len(), encoded_u64_varint_len(value));
681
682 let (read, decoded) = decode_u64_varint(&a).unwrap();
683 assert_eq!(decoded, value);
684 assert_eq!(read, encoded.len());
685 assert_eq!(a.len(), encoded_u64_varint_len(value));
686 }
687
688 #[test]
689 fn roundtrip_u64() {
690 check(2u64.pow(0) - 1, &[0x00]);
691 check(2u64.pow(0), &[0x01]);
692
693 check(2u64.pow(7) - 1, &[0x7F]);
694 check(2u64.pow(7), &[0x80, 0x01]);
695 check(300u64, &[0xAC, 0x02]);
696
697 check(2u64.pow(14) - 1, &[0xFF, 0x7F]);
698 check(2u64.pow(14), &[0x80, 0x80, 0x01]);
699
700 check(2u64.pow(21) - 1, &[0xFF, 0xFF, 0x7F]);
701 check(2u64.pow(21), &[0x80, 0x80, 0x80, 0x01]);
702
703 check(2u64.pow(28) - 1, &[0xFF, 0xFF, 0xFF, 0x7F]);
704 check(2u64.pow(28), &[0x80, 0x80, 0x80, 0x80, 0x01]);
705
706 check(2u64.pow(35) - 1, &[0xFF, 0xFF, 0xFF, 0xFF, 0x7F]);
707 check(2u64.pow(35), &[0x80, 0x80, 0x80, 0x80, 0x80, 0x01]);
708
709 check(2u64.pow(42) - 1, &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]);
710 check(2u64.pow(42), &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01]);
711
712 check(
713 2u64.pow(49) - 1,
714 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F],
715 );
716 check(
717 2u64.pow(49),
718 &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01],
719 );
720
721 check(
722 2u64.pow(56) - 1,
723 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F],
724 );
725 check(
726 2u64.pow(56),
727 &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01],
728 );
729
730 check(
731 2u64.pow(63) - 1,
732 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F],
733 );
734 check(
735 2u64.pow(63),
736 &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01],
737 );
738
739 check(
740 u64::MAX,
741 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01],
742 );
743 }
744
745 #[test]
746 fn test_large_number_encode_decode() {
747 let original = 30000u64;
748 let encoded = encode_u64_varint(original);
749 let (bytes_read, decoded) = decode_u64_varint(&encoded).unwrap();
750 assert_eq!(original, decoded);
751 assert_eq!(bytes_read, encoded.len());
752 }
753
754 #[test]
755 fn test_decode_overflow_error() {
756 let buffer = [0x80u8; 11]; match decode_u64_varint(&buffer) {
758 Err(DecodeError::Overflow) => (),
759 _ => panic!("Expected Overflow error"),
760 }
761
762 let buffer = [0x80u8; 6]; match decode_u32_varint(&buffer) {
764 Err(DecodeError::Overflow) => (),
765 _ => panic!("Expected Overflow error"),
766 }
767
768 let buffer = [0x80u8; 4]; match decode_u16_varint(&buffer) {
770 Err(DecodeError::Overflow) => (),
771 _ => panic!("Expected Overflow error"),
772 }
773 }
774
775 fn test_zigzag_encode_decode<T>(value: T)
777 where
778 T: Copy
779 + PartialEq
780 + core::fmt::Debug
781 + core::ops::Shl<Output = T>
782 + core::ops::Shr<Output = T>
783 + Into<i64>
784 + core::convert::TryInto<usize>
785 + core::convert::TryFrom<usize>,
786 {
787 let encoded = encode_i64_varint(value.into());
788 let bytes_written = encoded.len();
789
790 let decode_result = decode_i64_varint(&encoded);
792 assert!(decode_result.is_ok(), "Decoding failed");
793 let (decoded_bytes, decoded_value) = decode_result.unwrap();
794
795 assert_eq!(
796 decoded_bytes, bytes_written,
797 "Incorrect number of bytes decoded"
798 );
799 assert_eq!(
800 decoded_value,
801 value.into(),
802 "Decoded value does not match original"
803 );
804 }
805
806 #[test]
807 fn test_zigzag_encode_decode_i8() {
808 let values = [-1, 0, 1, -100, 100, i8::MIN, i8::MAX];
809 for &value in &values {
810 test_zigzag_encode_decode(value);
811 }
812 }
813
814 #[test]
815 fn test_zigzag_encode_decode_i16() {
816 let values = [-1, 0, 1, -100, 100, i16::MIN, i16::MAX];
817 for &value in &values {
818 test_zigzag_encode_decode(value);
819 }
820 }
821
822 #[test]
823 fn test_zigzag_encode_decode_i32() {
824 let values = [-1, 0, 1, -10000, 10000, i32::MIN, i32::MAX];
825 for &value in &values {
826 test_zigzag_encode_decode(value);
827 }
828 }
829
830 #[test]
831 fn test_zigzag_encode_decode_i64() {
832 let values = [-1, 0, 1, -1000000000, 1000000000, i64::MIN, i64::MAX];
833 for &value in &values {
834 test_zigzag_encode_decode(value);
835 }
836 }
837}
838
839#[cfg(test)]
840mod fuzzy {
841 use super::*;
842
843 use quickcheck_macros::quickcheck;
844
845 macro_rules! fuzzy {
846 ($($ty:ty), +$(,)?) => {
847 $(
848 paste::paste! {
849 #[quickcheck]
850 fn [< fuzzy_ $ty >](value: $ty) -> bool {
851 let encoded = [< encode_ $ty _varint >](value);
852 if encoded.len() != [< encoded_ $ty _varint_len >] (value) || !(encoded.len() <= <$ty>::MAX_ENCODED_LEN) {
853 return false;
854 }
855
856 let Ok(consumed) = consume_varint(&encoded) else {
857 return false;
858 };
859 if consumed != encoded.len() {
860 return false;
861 }
862
863 if let Ok((bytes_read, decoded)) = [< decode_ $ty _varint >](&encoded) {
864 value == decoded && encoded.len() == bytes_read
865 } else {
866 false
867 }
868 }
869
870 #[quickcheck]
871 fn [< fuzzy_ $ty _varint>](value: $ty) -> bool {
872 let mut buf = [0; <$ty>::MAX_ENCODED_LEN];
873 let Ok(encoded_len) = value.encode(&mut buf) else { return false; };
874 if encoded_len != value.encoded_len() || !(value.encoded_len() <= <$ty>::MAX_ENCODED_LEN) {
875 return false;
876 }
877
878 let Ok(consumed) = consume_varint(&buf) else {
879 return false;
880 };
881 if consumed != encoded_len {
882 return false;
883 }
884
885 if let Ok((bytes_read, decoded)) = <$ty>::decode(&buf) {
886 value == decoded && encoded_len == bytes_read
887 } else {
888 false
889 }
890 }
891 }
892 )*
893 };
894 }
895
896 fuzzy!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
897
898 #[cfg(feature = "std")]
899 mod with_std {
900 use super::*;
901
902 extern crate std;
903
904 use std::{vec, vec::Vec};
905
906 #[quickcheck]
907 fn fuzzy_buffer_underflow(value: u64, short_len: usize) -> bool {
908 let short_len = short_len % 9; if short_len >= value.encoded_len() {
910 return true; }
912 let mut short_buffer = vec![0u8; short_len];
913 matches!(
914 value.encode(&mut short_buffer),
915 Err(EncodeError::Underflow { .. })
916 )
917 }
918
919 #[quickcheck]
920 fn fuzzy_invalid_sequences(bytes: Vec<u8>) -> bool {
921 if bytes.is_empty() {
922 return matches!(decode_u64_varint(&bytes), Err(DecodeError::Underflow));
923 }
924
925 if bytes.len() > 10 {
927 return true;
928 }
929
930 if bytes.iter().all(|b| b & 0x80 != 0) {
932 return matches!(decode_u64_varint(&bytes), Err(DecodeError::Underflow));
933 }
934
935 match decode_u64_varint(&bytes) {
937 Ok(_) => true,
938 Err(_) => true,
939 }
940 }
941 }
942}