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
//! # Zende //! //! Zende is a minimal library for the ***z***igzag ***en***coding and //! ***de***coding of integers. #![doc(html_root_url = "https://docs.rs/zende/0.1.3")] use std::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); }