use arbitrary_int_1::*;
use core::num::NonZeroUsize;
use crate::{utils::Buffer, *};
macro_rules! generate {
($($storage:ident($start:literal..=$end:literal)), +$(,)?) => {
$(
seq_macro::seq!(N in $start..=$end {
generate!($storage(
#(
u~N,
)*
));
});
)*
};
($($underlying:ident($($inner:ident), +$(,)?)),+$(,)?) => {
$(
$(
paste::paste! {
#[doc = "The returned value will be in range of [`" $inner "::ENCODED_LEN_RANGE`]."]
#[inline]
pub const fn [< encoded_ $inner _varint_len >](value: $inner) -> NonZeroUsize {
[<encoded_ $underlying _varint_len>](value.value())
}
#[doc = "Encodes an `" $inner "` value into LEB128 variable length format, and writes it to the buffer."]
#[inline]
pub const fn [< encode_ $inner _varint >](x: $inner) -> $crate::utils::Buffer<{ $inner::MAX_ENCODED_LEN.get() + 1 }> {
let mut buf = [0; { $inner::MAX_ENCODED_LEN.get() + 1 }];
let len = match [< encode_ $inner _varint_to >](x, &mut buf) {
Ok(len) => len,
Err(_) => panic!("buffer should be large enough"),
};
buf[$crate::utils::Buffer::<{ $inner::MAX_ENCODED_LEN.get() + 1 }>::CAPACITY.get()] = len.get() as u8;
$crate::utils::Buffer::new(buf)
}
#[doc = "Encodes an `" $inner "` value into LEB128 variable length format, and writes it to the buffer."]
#[inline]
pub const fn [< encode_ $inner _varint_to >](value: $inner, buf: &mut [u8]) -> Result<NonZeroUsize, ConstEncodeError> {
[<encode_ $underlying _varint_to>](value.value(), buf)
}
#[doc = "Decodes an `" $inner "` in LEB128 encoded format from the buffer."]
#[inline]
pub const fn [< decode_ $inner _varint >](buf: &[u8]) -> Result<(NonZeroUsize, $inner), ConstDecodeError> {
match [<decode_ $underlying _varint>](buf) {
Ok((readed, val)) => {
match $inner::try_new(val) {
Ok(val) => Ok((readed, val)),
Err(_) => Err(ConstDecodeError::Overflow),
}
},
Err(err) => Err(err),
}
}
#[cfg(test)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct [< Fuzzy $inner:camel >]($inner);
#[cfg(test)]
const _: () = {
use quickcheck::{Arbitrary, Gen};
impl Arbitrary for [< Fuzzy $inner:camel >] {
fn arbitrary(g: &mut Gen) -> Self {
let val = loop {
let val = $underlying::arbitrary(g);
if val >= $inner::MIN.[<as_ $underlying>]() && val <= $inner::MAX.[<as_ $underlying>]() {
break val;
}
};
Self($inner::try_new(val).unwrap())
}
}
};
#[cfg(test)]
quickcheck::quickcheck! {
fn [< fuzzy_ $inner _varint >](x: [< Fuzzy $inner:camel >]) -> bool {
let x = x.0;
let mut buf = [0; $inner::MAX_ENCODED_LEN.get()];
let len = [< encode_ $inner _varint_to >](x, &mut buf).unwrap();
let buffer = [< encode_ $inner _varint >](x);
assert_eq!(buffer.len(), len.get());
assert_eq!(buffer.as_slice(), &buf[..len.get()]);
let (readed, val) = [< decode_ $inner _varint >](&buf).unwrap();
assert_eq!(readed, len);
assert_eq!(val, x);
true
}
}
#[test]
fn [< test_ $inner _min_max_varint >]() {
let min = $inner::MIN;
let max = $inner::MAX;
let min_encoded_len = [< encoded_ $inner _varint_len >](min);
let max_encoded_len = [< encoded_ $inner _varint_len >](max);
assert_eq!(min_encoded_len, $inner::MIN_ENCODED_LEN);
assert_eq!(max_encoded_len, $inner::MAX_ENCODED_LEN);
let mut buf = [0; $inner::MAX_ENCODED_LEN.get()];
let len = [< encode_ $inner _varint_to >](min, &mut buf).unwrap();
assert_eq!(len, min_encoded_len);
let buffer = [< encode_ $inner _varint >](min);
assert_eq!(buffer.len(), min_encoded_len.get());
assert_eq!(buffer.as_slice(), &buf[..min_encoded_len.get()]);
let (readed, val) = [< decode_ $inner _varint >](&buf).unwrap();
assert_eq!(readed, len);
assert_eq!(val, min);
let len = [< encode_ $inner _varint_to >](max, &mut buf).unwrap();
assert_eq!(len, max_encoded_len);
let buffer = [< encode_ $inner _varint >](max);
assert_eq!(buffer.len(), max_encoded_len.get());
assert_eq!(buffer.as_slice(), &buf[..max_encoded_len.get()]);
let (readed, val) = [< decode_ $inner _varint >](&buf).unwrap();
assert_eq!(readed, len);
assert_eq!(val, max);
}
}
)*
)*
};
($($storage:literal), +$(,)?) => {
paste::paste! {
$(
#[doc = "Returns the encoded length of the value in LEB128 variable length format."]
pub const fn [< encoded_uint_d $storage _len >]<const BITS: usize>(value: UInt<[< u $storage>], BITS>) -> NonZeroUsize {
[< encoded_u $storage _varint_len >](value.value())
}
#[doc = "Encodes an `Uint<u" $storage ", BITS>` value into LEB128 variable length format, and writes it to the buffer."]
pub const fn [< encode_uint_d $storage _to >]<const BITS: usize>(value: UInt<[< u $storage>], BITS>, buf: &mut [u8]) -> Result<NonZeroUsize, ConstEncodeError> {
[< encode_u $storage _varint_to >](value.value(), buf)
}
#[doc = "Encodes an `Uint<u" $storage ", BITS>` value into LEB128 variable length format, and writes it to the buffer."]
pub const fn [< encode_uint_d $storage>]<const BITS: usize>(value: UInt<[< u $storage>], BITS>) -> Buffer<{ [< u $storage>]::MAX_ENCODED_LEN.get() + 1 }> {
[< encode_u $storage _varint >](value.value())
}
#[doc = "Decodes an `Uint<u" $storage ", BITS>` in LEB128 encoded format from the buffer."]
pub const fn [< decode_uint_d $storage>]<const BITS: usize>(buf: &[u8]) -> Result<(NonZeroUsize, UInt<[< u $storage>], BITS>), ConstDecodeError> {
match [< decode_u $storage _varint >](buf) {
Ok((readed, val)) => {
match UInt::<[< u $storage>], BITS>::try_new(val) {
Ok(val) => Ok((readed, val)),
Err(_) => Err(ConstDecodeError::Overflow),
}
}
Err(err) => Err(err),
}
}
impl<const BITS: usize> Varint for UInt<[< u $storage>], BITS> {
const MIN_ENCODED_LEN: NonZeroUsize = [< encoded_uint_d $storage _len >](UInt::<[< u $storage>], BITS>::MIN);
const MAX_ENCODED_LEN: NonZeroUsize = [< encoded_uint_d $storage _len >](UInt::<[< u $storage>], BITS>::MAX);
fn encoded_len(&self) -> NonZeroUsize {
[< encoded_uint_d $storage _len >](*self)
}
fn encode(&self, buf: &mut [u8]) -> Result<NonZeroUsize, crate::EncodeError> {
[< encode_uint_d $storage _to >](*self, buf).map_err(Into::into)
}
fn decode(buf: &[u8]) -> Result<(NonZeroUsize, Self), crate::DecodeError>
where
Self: Sized,
{
[< decode_uint_d $storage >](buf).map_err(Into::into)
}
}
)*
}
};
}
generate!(
u8(1..=7),
u16(9..=15),
u32(17..=31),
u64(33..=63),
u128(65..=127),
);
generate!(8, 16, 32, 64, 128,);