1use std::io;
2use std::io::{ErrorKind, Read};
3use std::mem::size_of;
4
5pub trait Leb128Read : private::Sealed {
11 fn read_leb128_u16(&mut self) -> io::Result<u16>;
16
17 fn read_leb128_i16(&mut self) -> io::Result<i16>;
22
23 fn read_leb128_u32(&mut self) -> io::Result<u32>;
28
29 fn read_leb128_i32(&mut self) -> io::Result<i32>;
34
35 fn read_leb128_u64(&mut self) -> io::Result<u64>;
40
41 fn read_leb128_i64(&mut self) -> io::Result<i64>;
46
47 fn read_leb128_u128(&mut self) -> io::Result<u128>;
52
53 fn read_leb128_i128(&mut self) -> io::Result<i128>;
58
59 fn read_leb128_large_signed(&mut self, max_size: usize) -> io::Result<Vec<u8>>;
65
66 fn read_leb128_large_unsigned(&mut self, max_size: usize) -> io::Result<Vec<u8>>;
72}
73
74fn next<T: Read>(s: &mut T) -> io::Result<u8> {
75 let mut buf = [0u8];
76 s.read_exact(buf.as_mut_slice())?;
77 return Ok(buf[0]);
78}
79
80fn finish_large_leb_read(mut shift: u32, mut acc: u64, max_size: usize, mut result: Vec<u8>, is_negative: bool) -> io::Result<Vec<u8>> {
81 while shift > 0 {
82 shift = shift.saturating_sub(8);
83
84 let to_push = (acc & 0xFFu64) as u8;
85
86 if result.len()+1 > max_size {
87 if shift != 0 {
88 return Err(io::Error::new(ErrorKind::InvalidData, "leb128 larger than desired maximum size"));
89 }
90
91 if is_negative {
92 if to_push == u8::MAX {
93 return Ok(result);
95 }
96 } else {
97 if to_push == u8::MIN {
98 return Ok(result);
100 }
101 }
102
103 return Err(io::Error::new(ErrorKind::InvalidData, "leb128 larger than desired maximum size"));
104 }
105 result.push(to_push);
106 acc >>= 8;
107 }
108
109 return Ok(result);
110}
111
112fn push_next_large_leb_block(result : &mut Vec<u8>, max_size: usize, acc: u64) -> io::Result<()>{
113 if result.len()+7 > max_size {
114 return Err(io::Error::new(ErrorKind::InvalidData, "leb128 larger than desired maximum size"));
115 }
116 result.push(((acc >> 0) & 0xFFu64) as u8);
117 result.push(((acc >> 8) & 0xFFu64) as u8);
118 result.push(((acc >> 16) & 0xFFu64) as u8);
119 result.push(((acc >> 24) & 0xFFu64) as u8);
120 result.push(((acc >> 32) & 0xFFu64) as u8);
121 result.push(((acc >> 40) & 0xFFu64) as u8);
122 result.push(((acc >> 48) & 0xFFu64) as u8);
123 return Ok(());
124}
125
126
127macro_rules! read_unsigned_leb {
128 ($type:ty, $name:ident, $err:expr) => {
129 fn $name(&mut self) -> io::Result<$type> {
130 let mut acc : $type = 0;
131 let mut shift = 0u32;
132 let size = (size_of::<$type>() * 8) as u32;
133 loop {
134 if shift >= size {
135 return Err(io::Error::new(ErrorKind::InvalidData, $err));
136 }
137 let n : u8 = next(self)?;
138 acc |= ((n & 0b0111_1111u8) as $type) << shift;
139 shift+=7;
140 if n & 0b1000_0000u8 == 0 {
141 return Ok(acc);
142 }
143 }
144 }
145 }
146}
147
148macro_rules! read_signed_leb {
149 ($type:ty, $helper:ty, $name:ident, $err:expr) => {
150 fn $name(&mut self) -> io::Result<$type> {
151 let mut acc : $helper = 0;
152 let mut shift = 0u32;
153 let size = (size_of::<$helper>() * 8) as u32;
154 loop {
155 if shift >= size {
156 return Err(io::Error::new(ErrorKind::InvalidData, $err));
157 }
158 let n : u8 = next(self)?;
159 acc |= ((n & 0b0111_1111u8) as $helper) << shift;
160
161 shift+=7;
162 if n & 0b1000_0000u8 == 0 {
163 if n & 0b0100_0000u8 != 0 && shift < size{
164 let ext : $helper = 1;
165 acc |= !((ext << shift) -1);
166 }
167 return Ok(acc as $type);
168 }
169 }
170 }
171 }
172}
173
174impl <T> Leb128Read for T where T: Read {
175
176 read_signed_leb!(i16, u16, read_leb128_i16, "leb128 larger than i16");
177 read_signed_leb!(i32, u32, read_leb128_i32, "leb128 larger than i32");
178 read_signed_leb!(i64, u64, read_leb128_i64, "leb128 larger than i64");
179 read_signed_leb!(i128, u128, read_leb128_i128, "leb128 larger than i128");
180
181 read_unsigned_leb!(u16, read_leb128_u16, "leb128 larger than u16");
182 read_unsigned_leb!(u32, read_leb128_u32, "leb128 larger than u32");
183 read_unsigned_leb!(u64, read_leb128_u64, "leb128 larger than u64");
184 read_unsigned_leb!(u128, read_leb128_u128, "leb128 larger than u128");
185 fn read_leb128_large_signed(&mut self, max_size: usize) -> io::Result<Vec<u8>> {
186 let mut acc : u64 = 0;
187 let mut shift = 0u32;
188 let mut result : Vec<u8> = Vec::with_capacity(max_size);
189 loop {
190 if shift >= 54 {
191 push_next_large_leb_block(&mut result, max_size, acc)?;
192 shift = 0;
193 acc = 0;
194 }
195 let n : u8 = next(self)?;
196 acc |= ((n & 0b0111_1111u8) as u64) << shift;
197 shift+=7;
198 if n & 0b1000_0000u8 == 0 {
199 if n & 0b0100_0000u8 != 0 {
200 acc |= !((1u64 << shift) -1);
201 return finish_large_leb_read(shift, acc, max_size, result, true);
202 }
203
204 return finish_large_leb_read(shift, acc, max_size, result, false);
205 }
206 }
207 }
208
209 fn read_leb128_large_unsigned(&mut self, max_size: usize) -> io::Result<Vec<u8>> {
210 let mut acc : u64 = 0;
211 let mut shift = 0u32;
212 let mut result : Vec<u8> = Vec::with_capacity(max_size);
213 loop {
214 if shift >= 54 {
215 push_next_large_leb_block(&mut result, max_size, acc)?;
216 shift = 0;
217 acc = 0;
218 }
219 let n : u8 = next(self)?;
220 acc |= ((n & 0b0111_1111u8) as u64) << shift;
221 shift+=7;
222 if n & 0b1000_0000u8 == 0 {
223 return finish_large_leb_read(shift, acc, max_size, result, false);
224 }
225 }
226 }
227}
228
229mod private {
230 use std::io::Read;
231
232 impl <T> Sealed for T where T: Read {}
233 pub trait Sealed {
234
235 }
236}