tiny_varint/
zigzag.rs

1use crate::error::Error;
2use crate::traits::VarInt;
3use crate::encoding::{encode, decode};
4
5/// Trait for ZigZag encoding
6pub trait ZigZag: Copy {
7    /// Associated unsigned type
8    type Unsigned: VarInt;
9    
10    /// Encode to unsigned integer using ZigZag
11    fn zigzag_encode(self) -> Self::Unsigned;
12    
13    /// Decode from unsigned integer encoded with ZigZag
14    fn zigzag_decode(value: Self::Unsigned) -> Self;
15}
16
17// Implement ZigZag for all signed integer types
18macro_rules! impl_zigzag {
19    ($signed:ty, $unsigned:ty, $bits:expr) => {
20        impl ZigZag for $signed {
21            type Unsigned = $unsigned;
22            
23            #[inline]
24            fn zigzag_encode(self) -> Self::Unsigned {
25                ((self << 1) ^ (self >> ($bits - 1))) as $unsigned
26            }
27            
28            #[inline]
29            fn zigzag_decode(value: Self::Unsigned) -> Self {
30                ((value >> 1) as Self) ^ (-((value & 1) as Self))
31            }
32        }
33    };
34}
35
36// Implement for all signed integer types
37impl_zigzag!(i8, u8, 8);
38impl_zigzag!(i16, u16, 16);
39impl_zigzag!(i32, u32, 32);
40impl_zigzag!(i64, u64, 64);
41impl_zigzag!(i128, u128, 128);
42
43/// Encode a signed integer using ZigZag, then encode it as a varint
44///
45/// Returns the number of bytes written
46///
47/// # Arguments
48/// * `value` - The signed integer to encode
49/// * `buf` - The output buffer to write to
50///
51/// # Errors
52/// * Returns `Error::BufferTooSmall` if the buffer is too small
53pub fn encode_zigzag<T: ZigZag>(value: T, buf: &mut [u8]) -> Result<usize, Error> {
54    let zigzag = value.zigzag_encode();
55    encode(zigzag, buf)
56}
57
58/// Decode a signed integer from a varint-encoded zigzag value
59///
60/// Returns the decoded value and the number of bytes read
61///
62/// # Arguments
63/// * `buf` - The input buffer containing the zigzag varint encoded value
64///
65/// # Errors
66/// * Returns `Error::InputTooShort` if the input buffer is insufficient
67/// * Returns `Error::InvalidEncoding` if the varint encoding is invalid
68/// * Returns `Error::Overflow` if an overflow occurs during decoding
69pub fn decode_zigzag<T: ZigZag>(buf: &[u8]) -> Result<(T, usize), Error> {
70    let (unsigned, bytes_read) = decode::<T::Unsigned>(buf)?;
71    Ok((T::zigzag_decode(unsigned), bytes_read))
72}