1use crate::de::{Decoder, read::Reader};
4use crate::enc::{Encoder, write::Writer};
5use crate::error::{DecodeError, EncodeError};
6use crate::{Decode, Encode};
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
25#[repr(transparent)]
26pub struct Uleb128<T>(pub T);
27
28#[inline]
29fn encode<E: Encoder>(mut value: u128, encoder: &mut E) -> Result<(), EncodeError> {
30 loop {
31 let mut byte = (value & 0x7f) as u8;
32 value >>= 7;
33 if value != 0 {
34 byte |= 0x80;
35 }
36 encoder.writer().write(&[byte])?;
37 if value == 0 {
38 return Ok(());
39 }
40 }
41}
42
43#[inline]
44fn decode<D: Decoder>(bits: u32, decoder: &mut D) -> Result<u128, DecodeError> {
45 let mut value = 0u128;
46 for shift in (0..bits).step_by(7) {
47 let mut byte = [0];
48 decoder.reader().read(&mut byte)?;
49 let chunk = u128::from(byte[0] & 0x7f);
50 let remaining = bits - shift;
51 if remaining < 7 && chunk >= (1u128 << remaining) {
52 return Err(DecodeError::Other("ULEB128 integer overflow"));
53 }
54 value |= chunk << shift;
55 if byte[0] & 0x80 == 0 {
56 return Ok(value);
57 }
58 }
59 Err(DecodeError::Other("ULEB128 integer is too long"))
60}
61
62macro_rules! unsigned {
63 ($($ty:ty),* $(,)?) => {$ (
64 impl Encode for Uleb128<$ty> {
65 #[inline]
66 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
67 encode(self.0 as u128, encoder)
68 }
69 }
70
71 impl<Context> Decode<Context> for Uleb128<$ty> {
72 #[inline]
73 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
74 decoder.claim_bytes_read(core::mem::size_of::<$ty>())?;
75 decode(<$ty>::BITS, decoder).map(|value| Self(value as $ty))
76 }
77 }
78 crate::impl_borrow_decode!(Uleb128<$ty>);
79 )*};
80}
81
82macro_rules! signed {
83 ($($ty:ty => $unsigned:ty),* $(,)?) => {$ (
84 impl Encode for Uleb128<$ty> {
85 #[inline]
86 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
87 let value = self.0;
88 let zigzag = ((value as $unsigned) << 1) ^ ((value >> (<$ty>::BITS - 1)) as $unsigned);
89 encode(zigzag as u128, encoder)
90 }
91 }
92
93 impl<Context> Decode<Context> for Uleb128<$ty> {
94 #[inline]
95 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
96 decoder.claim_bytes_read(core::mem::size_of::<$ty>())?;
97 let value = decode(<$ty>::BITS, decoder)? as $unsigned;
98 Ok(Self(((value >> 1) as $ty) ^ -((value & 1) as $ty)))
99 }
100 }
101 crate::impl_borrow_decode!(Uleb128<$ty>);
102 )*};
103}
104
105unsigned!(u8, u16, u32, u64, u128, usize);
106signed!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128, isize => usize);