1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//! # Zende
//!
//! Zende is a minimal library for the ***z***igzag ***en***coding and
//! ***de***coding of integers.
#![no_std]
#![doc(html_root_url = "https://docs.rs/zende/0.1.8")]
use core::mem;
const BITS_PER_BYTE: usize = 8;
/// An extension trait implemented for all Rust integers to encode and decode
/// between signed and unsigned variants using
/// [zigzag encoding][wiki].
///
/// # Examples
///
/// Encoding a signed integer:
///
/// ```
/// use zende::Zigzag;
///
/// assert_eq!(0i8.zigzag(), 0u8);
/// assert_eq!((-1i8).zigzag(), 1u8);
/// assert_eq!(1i8.zigzag(), 2u8);
///
/// assert_eq!(i8::MIN.zigzag(), u8::MAX);
/// assert_eq!(i16::MIN.zigzag(), u16::MAX);
/// assert_eq!(i32::MIN.zigzag(), u32::MAX);
/// assert_eq!(i64::MIN.zigzag(), u64::MAX);
/// assert_eq!(i128::MIN.zigzag(), u128::MAX);
///
/// assert_eq!(isize::MIN.zigzag(), usize::MAX);
/// ```
///
/// Decoding an unsigned integer:
///
/// ```
/// use zende::Zigzag;
///
/// assert_eq!(0u8.zigzag(), 0i8);
/// assert_eq!(1u8.zigzag(), -1i8);
/// assert_eq!(2u8.zigzag(), 1i8);
///
/// assert_eq!(u8::MAX.zigzag(), i8::MIN);
/// assert_eq!(u16::MAX.zigzag(), i16::MIN);
/// assert_eq!(u32::MAX.zigzag(), i32::MIN);
/// assert_eq!(u64::MAX.zigzag(), i64::MIN);
/// assert_eq!(u128::MAX.zigzag(), i128::MIN);
///
/// assert_eq!(usize::MAX.zigzag(), isize::MIN);
/// ```
///
/// [wiki]: https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding
pub trait Zigzag<T>: private::Sealed {
/// Converts signed integers to unsigned integers and vice versa using
/// [zigzag encoding][wiki].
///
/// # Examples
///
/// ```
/// use zende::Zigzag;
///
/// assert_eq!(0i8.zigzag(), 0u8);
/// assert_eq!((-1i8).zigzag(), 1u8);
/// assert_eq!(1i8.zigzag(), 2u8);
///
/// assert_eq!(0u8.zigzag(), 0i8);
/// assert_eq!(1u8.zigzag(), -1i8);
/// assert_eq!(2u8.zigzag(), 1i8);
/// ```
///
/// [wiki]: https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding
fn zigzag(self) -> T;
}
macro_rules! impl_zigzag {
($(($signed:ty, $unsigned:ty)),*) => {
$(
impl Zigzag<$unsigned> for $signed {
#[inline]
fn zigzag(self) -> $unsigned {
const TYPE_BITS: usize = mem::size_of::<$unsigned>() * BITS_PER_BYTE;
(self >> TYPE_BITS - 1) as $unsigned ^ (self << 1) as $unsigned
}
}
impl Zigzag<$signed> for $unsigned {
#[inline]
fn zigzag(self) -> $signed {
(self >> 1) as $signed ^ -((self & 1) as $signed)
}
}
)*
}
}
impl_zigzag!(
(i8, u8),
(i16, u16),
(i32, u32),
(i64, u64),
(i128, u128),
(isize, usize)
);
mod private {
pub trait Sealed {}
macro_rules! impl_sealed {
($($t:ty),*) => {
$(
impl Sealed for $t {}
)*
}
}
impl_sealed!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
}