use crate::{
buffer::Buffer,
deserialize::{Deserialize, DeserializeError, Deserializer},
formula::Formula,
serialize::{write_bytes, Serialize, Sizes},
};
pub struct Vlq;
impl Formula for Vlq {
const MAX_STACK_SIZE: Option<usize> = None;
const EXACT_SIZE: bool = false;
const HEAPLESS: bool = true;
}
trait VlqType: Copy {
fn less_eq(&self, byte: u8) -> bool;
fn shr_byte_assign(&mut self) -> u8;
fn from_lsb(lsb: u8) -> Self;
fn shl_byte_set(&mut self, lsb: u8) -> bool;
}
impl VlqType for u8 {
#[inline(always)]
fn less_eq(&self, byte: u8) -> bool {
*self <= byte
}
#[inline(always)]
fn shr_byte_assign(&mut self) -> u8 {
core::mem::replace(self, 0)
}
#[inline(always)]
fn from_lsb(lsb: u8) -> Self {
lsb
}
#[inline(always)]
fn shl_byte_set(&mut self, lsb: u8) -> bool {
if *self > 0 {
return false;
}
*self = lsb;
true
}
}
macro_rules! impl_vlq_int {
($($a:ident)*) => {
$(
impl VlqType for $a {
#[inline(always)]
fn less_eq(&self, byte: u8) -> bool {
*self <= $a::from(byte)
}
#[inline(always)]
fn shr_byte_assign(&mut self) -> u8 {
let lsb = *self as u8;
*self >>= 8;
lsb
}
#[inline(always)]
fn from_lsb(lsb: u8) -> Self {
$a::from(lsb)
}
#[inline(always)]
fn shl_byte_set(&mut self, lsb: u8) -> bool {
if self.leading_zeros() < 8 {
return false;
}
*self <<= 8;
*self |= $a::from(lsb);
true
}
}
)*
};
}
impl_vlq_int!(u16 u32 u64 u128 usize);
impl<T> Serialize<Vlq> for T
where
T: VlqType,
{
#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
Some(size_hint(*self))
}
#[inline(always)]
fn serialize<B>(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
serialize(self, sizes, buffer)
}
}
impl<'de, T> Deserialize<'de, Vlq> for T
where
T: VlqType,
{
#[inline(always)]
fn deserialize(de: Deserializer<'de>) -> Result<Self, DeserializeError> {
deserialize(de)
}
#[inline(always)]
fn deserialize_in_place(
&mut self,
deserializer: Deserializer<'de>,
) -> Result<(), DeserializeError> {
*self = deserialize(deserializer)?;
Ok(())
}
}
#[inline(always)]
fn size_hint<T>(mut value: T) -> Sizes
where
T: VlqType,
{
let mut tail = 0;
loop {
if tail >= 8 {
if value.less_eq(0) {
break;
}
} else if value.less_eq(0xF) {
break;
}
if tail == 63 {
unimplemented!(
"Encoding for values that require more than 63 bytes is not implemented yet."
)
}
tail += 1;
value.shr_byte_assign();
}
Sizes::with_stack(tail + 1)
}
#[inline(always)]
fn serialize<T, B>(mut value: T, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
T: VlqType,
B: Buffer,
{
let mut bytes = [0u8; 64];
let mut tail = 0;
loop {
if tail >= 8 {
if value.less_eq(0) {
bytes[usize::from(tail)] = 0x80 | tail;
return write_bytes(&bytes[..=usize::from(tail)], sizes, buffer);
}
} else if value.less_eq(0xF) {
let lsb = value.shr_byte_assign();
bytes[usize::from(tail)] = (tail << 4) | lsb;
return write_bytes(&bytes[..=usize::from(tail)], sizes, buffer);
}
if tail == 63 {
unimplemented!(
"Encoding for values that require more than 63 bytes is not implemented yet."
)
}
let lsb = value.shr_byte_assign();
bytes[usize::from(tail)] = lsb;
tail += 1;
}
}
#[inline(always)]
fn deserialize<T>(mut de: Deserializer) -> Result<T, DeserializeError>
where
T: VlqType,
{
let header = de.read_bytes(1)?[0];
let (tail, msb) = match header {
0x00..=0x7F => (header >> 4, header & 0x0F),
0x80..=0xBF => (header & 0x3F, 0),
0xC0..=0xFF => {
unimplemented!(
"Decoding for values that require more than 63 bytes is not implemented yet."
)
}
};
let mut value = T::from_lsb(msb);
let tail = de.read_bytes(usize::from(tail))?;
for byte in tail.iter().rev() {
if !value.shl_byte_set(*byte) {
return Err(DeserializeError::IntegerOverflow);
}
}
Ok(value)
}