varing 0.5.2

Protobuf's varint encoding/decoding for LEB128 friendly types with full const context operations supports.
Documentation
use core::num::*;

macro_rules! impl_for_non_zero {
  ($($ty:ident), +$(,)?) => {
    $(
      paste::paste! {
        impl $crate::Varint for [< NonZero $ty:camel >] {
          const MIN_ENCODED_LEN: usize = $ty::MIN_ENCODED_LEN;

          const MAX_ENCODED_LEN: usize = $ty::MAX_ENCODED_LEN;

          fn encoded_len(&self) -> usize {
            self.get().encoded_len()
          }

          fn encode(&self, buf: &mut [u8]) -> Result<usize, crate::EncodeError> {
            self.get().encode(buf)
          }

          fn decode(buf: &[u8]) -> Result<(usize, Self), crate::DecodeError>
          where
            Self: Sized,
          {
            $ty::decode(buf).and_then(|(n, x)| {
              if x == 0 {
                Err(crate::DecodeError::custom(concat!(stringify!([< NonZero $ty:camel >]), "cannot be zero")))
              } else {
                Ok((n, unsafe { Self::new_unchecked(x) }))
              }
            })
          }
        }
      }
    )*
  };
}

impl_for_non_zero!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128,);

#[cfg(test)]
mod tests {
  use crate::{consume_varint, Varint};
  use core::num::*;

  macro_rules! fuzzy {
    ($($ty:ty), +$(,)?) => {
      $(
        paste::paste! {
          #[quickcheck_macros::quickcheck]
          fn [< fuzzy_non_zero_ $ty _varint>](value: $ty) -> bool {
            if value == 0 {
              return true;
            }

            let value = [< NonZero $ty:camel >]::new(value).unwrap();

            let mut buf = [0; <[< NonZero $ty:camel >]>::MAX_ENCODED_LEN];
            let Ok(encoded_len) = value.encode(&mut buf) else { return false; };
            if encoded_len != value.encoded_len() || !(value.encoded_len() <= <[< NonZero $ty:camel >]>::MAX_ENCODED_LEN) {
              return false;
            }

            let Ok(consumed) = consume_varint(&buf) else {
              return false;
            };
            if consumed != encoded_len {
              return false;
            }

            if let Ok((bytes_read, decoded)) = <[< NonZero $ty:camel >]>::decode(&buf) {
              value == decoded && encoded_len == bytes_read
            } else {
              false
            }
          }
        }
      )*
    };
  }

  fuzzy!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128,);
}