use crate::error::Error;
use crate::traits::VarInt;
use crate::encoding::{encode, decode};
pub trait ZigZag: Copy {
type Unsigned: VarInt;
fn zigzag_encode(self) -> Self::Unsigned;
fn zigzag_decode(value: Self::Unsigned) -> Self;
}
macro_rules! impl_zigzag {
($signed:ty, $unsigned:ty, $bits:expr) => {
impl ZigZag for $signed {
type Unsigned = $unsigned;
#[inline]
fn zigzag_encode(self) -> Self::Unsigned {
((self << 1) ^ (self >> ($bits - 1))) as $unsigned
}
#[inline]
fn zigzag_decode(value: Self::Unsigned) -> Self {
((value >> 1) as Self) ^ (-((value & 1) as Self))
}
}
};
}
impl_zigzag!(i8, u8, 8);
impl_zigzag!(i16, u16, 16);
impl_zigzag!(i32, u32, 32);
impl_zigzag!(i64, u64, 64);
impl_zigzag!(i128, u128, 128);
pub fn encode_zigzag<T: ZigZag>(value: T, buf: &mut [u8]) -> Result<usize, Error> {
let zigzag = value.zigzag_encode();
encode(zigzag, buf)
}
pub fn decode_zigzag<T: ZigZag>(buf: &[u8]) -> Result<(T, usize), Error> {
let (unsigned, bytes_read) = decode::<T::Unsigned>(buf)?;
Ok((T::zigzag_decode(unsigned), bytes_read))
}