pub trait ZigZag: Sized + Copy {
type Unsigned;
fn zigzag_encode(self) -> Self::Unsigned;
fn zigzag_decode(encoded: Self::Unsigned) -> Self;
}
macro_rules! impl_zigzag {
($signed:ty, $unsigned:ty) => {
impl ZigZag for $signed {
type Unsigned = $unsigned;
#[inline(always)]
fn zigzag_encode(self) -> Self::Unsigned {
const BITS: u32 = <$signed>::BITS;
((self << 1) ^ (self >> (BITS - 1))) as $unsigned
}
#[inline(always)]
fn zigzag_decode(encoded: Self::Unsigned) -> Self {
(encoded >> 1) as $signed ^ -((encoded & 1) as $signed)
}
}
};
}
impl_zigzag!(i8, u8);
impl_zigzag!(i16, u16);
impl_zigzag!(i32, u32);
impl_zigzag!(i64, u64);
impl_zigzag!(isize, usize);
#[cfg(test)]
mod tests {
use super::ZigZag;
#[test]
fn test_zigzag() {
let enc = (-1i8).zigzag_encode();
assert_eq!(enc, 1u8);
let dec = i8::zigzag_decode(enc);
assert_eq!(dec, -1i8);
let enc = (0i16).zigzag_encode();
assert_eq!(enc, 0u16);
let dec = i16::zigzag_decode(enc);
assert_eq!(dec, 0i16);
let enc = (1i32).zigzag_encode();
assert_eq!(enc, 2u32);
let dec = i32::zigzag_decode(enc);
assert_eq!(dec, 1i32);
let enc = (-12345i64).zigzag_encode();
assert_eq!(enc, 24689u64);
let dec = i64::zigzag_decode(enc);
assert_eq!(dec, -12345i64);
}
}
pub trait VarIntWritable: Copy + PartialOrd {
fn is_zero(self) -> bool;
fn low_7_bits(self) -> u8;
fn shr_7(&mut self);
}
macro_rules! impl_varint_writable {
($($t:ty),*) => {
$(
impl VarIntWritable for $t {
#[inline(always)]
fn is_zero(self) -> bool {
self == 0
}
#[inline(always)]
fn low_7_bits(self) -> u8 {
(self & 0x7F) as u8
}
#[inline(always)]
fn shr_7(&mut self) {
*self >>= 7;
}
}
)*
};
}
impl_varint_writable!(u8, u16, u32, u64, usize, u128);