uts-core 0.1.0-alpha.1

Core types and traits for Univeral Timestamps in Rust
Documentation
use crate::codec::*;

macro_rules! leb128 {
    ($ty:ty) => {
        paste::paste! {
            impl crate::codec::Encode for $ty {
                #[inline]
                fn encode(&self, encoder: &mut impl crate::codec::Encoder) -> Result<(), $crate::error::EncodeError> {
                    let mut n = *self;
                    let mut buf = [0u8; <$ty>::BITS.div_ceil(7) as usize];
                    let mut i = 0;

                    loop {
                        let mut byte = (n as u8) & 0x7f;
                        n >>= 7;

                        if n != 0 {
                            byte |= 0x80;
                        }

                        buf[i] = byte;
                        i += 1;

                        if n == 0 {
                            break;
                        }
                    }

                    encoder.write_all(&buf[..i])?;
                    Ok(())
                }
            }

            impl<A: $crate::alloc::Allocator> crate::codec::DecodeIn<A> for $ty {
                #[inline]
                fn decode_in(decoder: &mut impl crate::codec::Decoder, _alloc: A) -> Result<Self, $crate::error::DecodeError> {
                    let mut ret: $ty = 0;
                    let mut shift: u32 = 0;

                    loop {
                        // Bottom 7 bits are value bits
                        let byte = decoder.decode_byte()?;
                        let value = (byte & 0x7f) as $ty;

                        // This is a stable port of `shl_exact`
                        // FIXME: This should be replaced with `shl_exact` once it is stabilized.
                        // ```
                        // ret |= ((byte & 0x7f) as $ty)
                        //     .shl_exact(shift)
                        //     .ok_or($crate::error::DecodeError::LEB128Overflow(<$ty>::BITS))?;
                        // ```
                        // #[unstable(feature = "exact_bitshifts", issue = "144336")]
                        // #[must_use = "this returns the result of the operation, \
                        //               without modifying the original"]
                        // #[inline]
                        // pub const fn shl_exact(self, rhs: u32) -> Option<$SelfT> {
                        //     if rhs < self.leading_zeros() || rhs < self.leading_ones() {
                        //         // SAFETY: rhs is checked above
                        //         Some(unsafe { self.unchecked_shl(rhs) })
                        //     } else {
                        //         None
                        //     }
                        // }
                        if shift < value.leading_zeros() || shift < value.leading_ones() {
                            // SAFETY: shift is checked above
                            ret |= unsafe { ((byte & 0x7f) as $ty).unchecked_shl(shift) };
                        } else {
                            return Err($crate::error::DecodeError::LEB128Overflow(<$ty>::BITS));
                        }

                        // Top bit is a continue bit
                        if byte & 0x80 == 0 {
                            break;
                        }
                        shift = shift
                            .checked_add(7)
                            .ok_or($crate::error::DecodeError::LEB128Overflow(<$ty>::BITS))?;
                    }

                    Ok(ret)
                }
            }
        }
    };
    ($($ty:ty),+ $(,)?) => {
        $(leb128!($ty);)+
    };
}

leb128!(u16, u32, u64, u128);

impl Encode for u8 {
    #[inline]
    fn encode(&self, encoder: &mut impl Encoder) -> Result<(), EncodeError> {
        encoder.write_all([*self])?;
        Ok(())
    }
}

impl<A: Allocator> DecodeIn<A> for u8 {
    #[inline]
    fn decode_in(decoder: &mut impl Decoder, _alloc: A) -> Result<Self, DecodeError> {
        let mut byte = [0u8; 1];
        decoder.read_exact(&mut byte)?;
        Ok(byte[0])
    }
}

impl Encode for usize {
    #[inline]
    fn encode(&self, encoder: &mut impl Encoder) -> Result<(), EncodeError> {
        let val: u32 = (*self).try_into().map_err(|_| EncodeError::UsizeOverflow)?;
        val.encode(encoder)?;
        Ok(())
    }
}

impl<A: Allocator> DecodeIn<A> for usize {
    #[inline]
    fn decode_in(decoder: &mut impl Decoder, _alloc: A) -> Result<Self, DecodeError> {
        let val = u32::decode(decoder)?;
        Ok(val as usize)
    }
}