const_varint/
lib.rs

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    // Check buffer capacity before writing final byte
117    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      // Check buffer capacity before writing final byte
140      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        /// Returns the encoded length of the value in LEB128 variable length format.
155        #[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        /// Returns the encoded length of the value in LEB128 variable length format.
167        #[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          /// Returns the number of bytes in the buffer.
217          #[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          /// Extracts a slice from the buffer.
224          #[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)); // Zig-zag encoding;
268          [< 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            // Zig-zag encoding
282            ((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        ///
297        /// Returns the bytes readed and the decoded value if successful.
298        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        ///
304        /// Returns the bytes readed and the decoded value if successful.
305        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 >]) }; // Zig-zag decoding
309              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    // Zig-zag encoding
337    ((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    // Store 7 bits and set the high bit to indicate more bytes follow
351    buf[i] = (n & 0x7F) | 0x80;
352    i += 1;
353    n >>= 7;
354  }
355
356  // Check buffer capacity before writing final byte
357  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)); // Zig-zag encoding;
375  I8VarintBuffer(U8VarintBuffer::new(x as u8).0)
376}
377
378/// A trait for types that can be encoded as variable-length integers (varints).
379///
380/// Varints are a method of serializing integers using one or more bytes that allows small
381/// numbers to be stored in fewer bytes. The encoding scheme is compatible with Protocol Buffers'
382/// base-128 varint format.
383pub trait Varint {
384  /// The minimum number of bytes needed to encode any value of this type.
385  ///
386  /// - For `u16` and `i16`, this is `1`.
387  /// - For `u32` and `i32`, this is `1`.
388  /// - For `u64` and `i64`, this is `1`.
389  /// - For `u128` and `i128`, this is `1`.
390  const MIN_ENCODED_LEN: usize;
391
392  /// The maximum number of bytes that might be needed to encode any value of this type.
393  ///
394  /// - For `u16` and `i16`, this is `3`.
395  /// - For `u32` and `i32`, this is `5`.
396  /// - For `u64` and `i64`, this is `10`.
397  /// - For `u128` and `i128`, this is `19`.
398  const MAX_ENCODED_LEN: usize;
399
400  /// The range of possible encoded lengths for this type, from `MIN_ENCODED_LEN` to `MAX_ENCODED_LEN` inclusive.
401  ///
402  /// This range can be used to pre-allocate buffers or validate encoded data lengths.
403  ///
404  /// - For `u16` and `i16`, this range is `1..=3`, representing possible encoded lengths of 1, 2, or 3 bytes.
405  /// - For `u32` and `i32`, this range is `1..=5`, representing possible encoded lengths of 1, 2, 3, 4, or 5 bytes.
406  /// - For `u64` and `u64`, this range is `1..=10`, representing possible encoded lengths of 1 to 10 bytes.
407  /// - For `u128` and `i128`, this range is `1..=19`, representing possible encoded lengths of 1 to 19 bytes.
408  const ENCODED_LEN_RANGE: RangeInclusive<usize> = Self::MIN_ENCODED_LEN..=Self::MAX_ENCODED_LEN;
409
410  /// Returns the encoded length of the value in LEB128 variable length format.
411  /// The returned value will be in range [`Self::ENCODED_LEN_RANGE`](Varint::ENCODED_LEN_RANGE).
412  fn encoded_len(&self) -> usize;
413
414  /// Encodes the value as a varint and writes it to the buffer.
415  ///
416  /// Returns the number of bytes written to the buffer.
417  fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError>;
418
419  /// Decodes the value from the buffer.
420  ///
421  /// Returns the number of bytes read from the buffer and the decoded value if successful.
422  fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError>
423  where
424    Self: Sized;
425}
426
427/// Returns the encoded length of the value in LEB128 variable length format.
428/// The returned value will be in range [`u128::ENCODED_LEN_RANGE`].
429#[inline]
430pub const fn encoded_u128_varint_len(value: u128) -> usize {
431  // Each byte in LEB128 encoding can hold 7 bits of data
432  // We want to find how many groups of 7 bits are needed
433  // Special case for 0 and small numbers
434  if value < 128 {
435    return 1;
436  }
437
438  // Calculate position of highest set bit
439  let highest_bit = 128 - value.leading_zeros();
440  // Convert to number of LEB128 bytes needed
441  // Each byte holds 7 bits, but we need to round up
442  highest_bit.div_ceil(7) as usize
443}
444
445/// Returns the encoded length of the value in LEB128 variable length format.
446/// The returned value will be in range [`i128::ENCODED_LEN_RANGE`].
447#[inline]
448pub const fn encoded_i128_varint_len(x: i128) -> usize {
449  let x = (x << 1) ^ (x >> 127); // Zig-zag encoding; // Zig-zag decoding;
450  encoded_u128_varint_len(x as u128)
451}
452
453/// Returns the encoded length of the value in LEB128 variable length format.
454/// The returned value will be in range [`i64::ENCODED_LEN_RANGE`].
455#[inline]
456pub const fn encoded_i64_varint_len(x: i64) -> usize {
457  let x = (x << 1) ^ (x >> 63); // Zig-zag encoding
458  encoded_u64_varint_len(x as u64)
459}
460
461/// Returns the encoded length of the value in LEB128 variable length format.
462/// The returned value will be in range [`u64::ENCODED_LEN_RANGE`].
463#[inline]
464pub const fn encoded_u64_varint_len(value: u64) -> usize {
465  // Based on [VarintSize64][1].
466  // [1]: https://github.com/protocolbuffers/protobuf/blob/v28.3/src/google/protobuf/io/coded_stream.h#L1744-L1756
467  // Safety: (value | 1) is never zero
468  let log2value = unsafe { NonZeroU64::new_unchecked(value | 1) }.ilog2();
469  ((log2value * 9 + (64 + 9)) / 64) as usize
470}
471
472/// Calculates the number of bytes occupied by a varint encoded value in the buffer.
473///
474/// In varint encoding, each byte uses 7 bits for the value and the highest bit (MSB)
475/// as a continuation flag. A set MSB (1) indicates more bytes follow, while an unset MSB (0)
476/// marks the last byte of the varint.
477///
478/// ## Returns
479/// * `Ok(usize)` - The number of bytes the varint occupies in the buffer
480/// * `Err(DecodeError)` - If the buffer is empty or contains an incomplete varint
481///
482/// ## Examples
483///
484/// ```rust
485/// use const_varint::consume_varint;
486///
487/// let buf = [0x96, 0x01]; // Varint encoding of 150
488/// assert_eq!(consume_varint(&buf), Ok(2));
489///
490/// let buf = [0x7F]; // Varint encoding of 127
491/// assert_eq!(consume_varint(&buf), Ok(1));
492/// ```
493pub const fn consume_varint(buf: &[u8]) -> Result<usize, DecodeError> {
494  if buf.is_empty() {
495    return Ok(0);
496  }
497
498  // Scan the buffer to find the end of the varint
499  let mut idx = 0;
500  let buf_len = buf.len();
501
502  while idx < buf_len {
503    let byte = buf[idx];
504    // Check if this is the last byte of the varint (MSB is not set)
505    if byte & 0x80 == 0 {
506      // Found the last byte, return the total number of bytes
507      return Ok(idx + 1);
508    }
509
510    // If we've reached the end of the buffer but haven't found the end of the varint
511    if idx == buf_len - 1 {
512      return Err(DecodeError::Underflow);
513    }
514    idx += 1;
515  }
516
517  // This point is reached only if all bytes have their MSB set and we've
518  // exhausted the buffer, which means the varint is incomplete
519  Err(DecodeError::Underflow)
520}
521
522/// Encode varint error
523#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, thiserror::Error)]
524#[non_exhaustive]
525pub enum EncodeError {
526  /// The buffer does not have enough capacity to encode the value.
527  #[error("buffer does not have enough capacity to encode the value")]
528  Underflow {
529    /// The number of bytes needed to encode the value.
530    required: usize,
531    /// The number of bytes remaining in the buffer.
532    remaining: usize,
533  },
534  /// A custom error message.
535  #[error("{0}")]
536  Custom(&'static str),
537}
538
539impl EncodeError {
540  /// Creates a new `EncodeError::Underflow` with the required and remaining bytes.
541  #[inline]
542  pub const fn underflow(required: usize, remaining: usize) -> Self {
543    Self::Underflow {
544      required,
545      remaining,
546    }
547  }
548
549  /// Creates a new `EncodeError::Custom` with the given message.
550  #[inline]
551  pub const fn custom(msg: &'static str) -> Self {
552    Self::Custom(msg)
553  }
554}
555
556/// Decoding varint error.
557#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, thiserror::Error)]
558#[non_exhaustive]
559pub enum DecodeError {
560  /// The buffer does not contain a valid LEB128 encoding.
561  #[error("value would overflow the target type")]
562  Overflow,
563  /// The buffer does not contain enough data to decode.
564  #[error("buffer does not contain enough data to decode a value")]
565  Underflow,
566  /// A custom error message.
567  #[error("{0}")]
568  Custom(&'static str),
569}
570
571impl DecodeError {
572  /// Creates a new `DecodeError::Custom` with the given message.
573  #[inline]
574  pub const fn custom(msg: &'static str) -> Self {
575    Self::Custom(msg)
576  }
577}
578
579///A buffer for storing LEB128 encoded i8 values.
580#[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        // Zig-zag encoding
598        ((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        // Store 7 bits and set the high bit to indicate more bytes follow
608        mut_buf[i] = (n & 0x7F) | 0x80;
609        i += 1;
610        n >>= 7;
611      }
612
613      // Check buffer capacity before writing final byte
614      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  /// Returns the number of bytes in the buffer.
625  #[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  /// Extracts a slice from the buffer.
631  #[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/// LEB128 encoding/decoding for `u1`, `u2` .. `u127`
660#[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]; // More than 10 bytes
757    match decode_u64_varint(&buffer) {
758      Err(DecodeError::Overflow) => (),
759      _ => panic!("Expected Overflow error"),
760    }
761
762    let buffer = [0x80u8; 6]; // More than 5 bytes
763    match decode_u32_varint(&buffer) {
764      Err(DecodeError::Overflow) => (),
765      _ => panic!("Expected Overflow error"),
766    }
767
768    let buffer = [0x80u8; 4]; // More than 3 bytes
769    match decode_u16_varint(&buffer) {
770      Err(DecodeError::Overflow) => (),
771      _ => panic!("Expected Overflow error"),
772    }
773  }
774
775  // Helper function for zig-zag encoding and decoding
776  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    // Decode
791    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; // Keep length under max varint size
909      if short_len >= value.encoded_len() {
910        return true; // Skip test if buffer is actually large enough
911      }
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      // Only test sequences up to max varint length
926      if bytes.len() > 10 {
927        return true;
928      }
929
930      // If all bytes have continuation bit set, should get Underflow
931      if bytes.iter().all(|b| b & 0x80 != 0) {
932        return matches!(decode_u64_varint(&bytes), Err(DecodeError::Underflow));
933      }
934
935      // For other cases, we should get either a valid decode or an error
936      match decode_u64_varint(&bytes) {
937        Ok(_) => true,
938        Err(_) => true,
939      }
940    }
941  }
942}