Skip to main content

uts_core/codec/imp/
primitives.rs

1use crate::codec::*;
2
3macro_rules! leb128 {
4    ($ty:ty) => {
5        paste::paste! {
6            impl crate::codec::Encode for $ty {
7                #[inline]
8                fn encode(&self, encoder: &mut impl crate::codec::Encoder) -> Result<(), $crate::error::EncodeError> {
9                    let mut n = *self;
10                    let mut buf = [0u8; <$ty>::BITS.div_ceil(7) as usize];
11                    let mut i = 0;
12
13                    loop {
14                        let mut byte = (n as u8) & 0x7f;
15                        n >>= 7;
16
17                        if n != 0 {
18                            byte |= 0x80;
19                        }
20
21                        buf[i] = byte;
22                        i += 1;
23
24                        if n == 0 {
25                            break;
26                        }
27                    }
28
29                    encoder.write_all(&buf[..i])?;
30                    Ok(())
31                }
32            }
33
34            impl<A: $crate::alloc::Allocator> crate::codec::DecodeIn<A> for $ty {
35                #[inline]
36                fn decode_in(decoder: &mut impl crate::codec::Decoder, _alloc: A) -> Result<Self, $crate::error::DecodeError> {
37                    let mut ret: $ty = 0;
38                    let mut shift: u32 = 0;
39
40                    loop {
41                        // Bottom 7 bits are value bits
42                        let byte = decoder.decode_byte()?;
43                        let value = (byte & 0x7f) as $ty;
44
45                        // This is a stable port of `shl_exact`
46                        // FIXME: This should be replaced with `shl_exact` once it is stabilized.
47                        // ```
48                        // ret |= ((byte & 0x7f) as $ty)
49                        //     .shl_exact(shift)
50                        //     .ok_or($crate::error::DecodeError::LEB128Overflow(<$ty>::BITS))?;
51                        // ```
52                        // #[unstable(feature = "exact_bitshifts", issue = "144336")]
53                        // #[must_use = "this returns the result of the operation, \
54                        //               without modifying the original"]
55                        // #[inline]
56                        // pub const fn shl_exact(self, rhs: u32) -> Option<$SelfT> {
57                        //     if rhs < self.leading_zeros() || rhs < self.leading_ones() {
58                        //         // SAFETY: rhs is checked above
59                        //         Some(unsafe { self.unchecked_shl(rhs) })
60                        //     } else {
61                        //         None
62                        //     }
63                        // }
64                        if shift < value.leading_zeros() || shift < value.leading_ones() {
65                            // SAFETY: shift is checked above
66                            ret |= unsafe { ((byte & 0x7f) as $ty).unchecked_shl(shift) };
67                        } else {
68                            return Err($crate::error::DecodeError::LEB128Overflow(<$ty>::BITS));
69                        }
70
71                        // Top bit is a continue bit
72                        if byte & 0x80 == 0 {
73                            break;
74                        }
75                        shift = shift
76                            .checked_add(7)
77                            .ok_or($crate::error::DecodeError::LEB128Overflow(<$ty>::BITS))?;
78                    }
79
80                    Ok(ret)
81                }
82            }
83        }
84    };
85    ($($ty:ty),+ $(,)?) => {
86        $(leb128!($ty);)+
87    };
88}
89
90leb128!(u16, u32, u64, u128);
91
92impl Encode for u8 {
93    #[inline]
94    fn encode(&self, encoder: &mut impl Encoder) -> Result<(), EncodeError> {
95        encoder.write_all([*self])?;
96        Ok(())
97    }
98}
99
100impl<A: Allocator> DecodeIn<A> for u8 {
101    #[inline]
102    fn decode_in(decoder: &mut impl Decoder, _alloc: A) -> Result<Self, DecodeError> {
103        let mut byte = [0u8; 1];
104        decoder.read_exact(&mut byte)?;
105        Ok(byte[0])
106    }
107}
108
109impl Encode for usize {
110    #[inline]
111    fn encode(&self, encoder: &mut impl Encoder) -> Result<(), EncodeError> {
112        let val: u32 = (*self).try_into().map_err(|_| EncodeError::UsizeOverflow)?;
113        val.encode(encoder)?;
114        Ok(())
115    }
116}
117
118impl<A: Allocator> DecodeIn<A> for usize {
119    #[inline]
120    fn decode_in(decoder: &mut impl Decoder, _alloc: A) -> Result<Self, DecodeError> {
121        let val = u32::decode(decoder)?;
122        Ok(val as usize)
123    }
124}