1use std::io;
2use std::io::{Error, ErrorKind, Write};
3use std::mem::size_of;
4
5pub trait Leb128Write : private::Sealed {
11
12 fn write_leb128_u16(&mut self, value: u16) -> io::Result<()>;
16
17 fn write_leb128_i16(&mut self, value: i16) -> io::Result<()>;
21
22 fn write_leb128_u32(&mut self, value: u32) -> io::Result<()>;
26
27 fn write_leb128_i32(&mut self, value: i32) -> io::Result<()>;
31
32 fn write_leb128_u64(&mut self, value: u64) -> io::Result<()>;
36
37 fn write_leb128_i64(&mut self, value: i64) -> io::Result<()>;
41
42 fn write_leb128_u128(&mut self, value: u128) -> io::Result<()>;
46
47 fn write_leb128_i128(&mut self, value: i128) -> io::Result<()>;
51
52 fn write_leb128_large_signed(&mut self, value: &Vec<u8>) -> io::Result<()>;
57
58 fn write_leb128_large_unsigned(&mut self, value: &Vec<u8>) -> io::Result<()>;
63}
64
65fn pump_leb128_data<T: Write>(s: &mut T, value: &Vec<u8>, last: usize) -> io::Result<(u64, usize)> {
66 let mut acc: u64 = 0;
67 let mut size: usize = 0;
68 for x in value.as_slice()[0..last].iter() {
69 if size >= 56 {
70 while size > 0 {
71 size -= 7;
72 let next = ((acc & 0b0111_1111u64) as u8) | 0b1000_0000u8 ;
73 acc >>= 7;
74 s.write_all(&[next])?;
75 }
76 acc = 0;
77 }
78
79 acc |= (*x as u64) << size;
80 size += 8;
81 }
82
83 return Ok((acc,size));
84}
85
86macro_rules! write_unsigned_leb {
87 ($type:ty, $name:ident) => {
88 fn $name(&mut self, value: $type) -> io::Result<()> {
89 if value == 0 {
90 return self.write_all(&[0]);
91 }
92
93 let mut acc : $type = value;
94
95 let mut size = size_of::<$type>()*8;
96 loop {
97 size = size.saturating_sub(7);
98 let mut next = (acc & 0b0111_1111) as u8;
99 acc >>= 7;
100
101 if acc == 0 || size == 0 {
102 return self.write_all(&[next]);
103 }
104
105 next |= 0b1000_0000;
106
107 self.write_all(&[next])?;
108 }
109 }
110 }
111}
112
113macro_rules! write_signed_leb {
114 ($type:ty, $helper:ty, $name:ident) => {
115 fn $name(&mut self, value: $type) -> io::Result<()> {
116 if value == 0 {
117 return self.write_all(&[0]);
118 }
119
120 let mut acc = value as $helper;
121 let mut size = size_of::<$helper>()*8;
122 let mut acc_eq : $helper = !0;
123
124 loop {
125 size = size.saturating_sub(7);
126 let mut next = (acc & 0b0111_1111) as u8;
127
128 if size == 0 {
129 return self.write_all(&[next]);
130 }
131
132 acc >>= 7;
133 acc_eq >>= 7;
134
135 if next & 0b0100_0000 != 0 {
136 if acc_eq == acc {
137 return self.write_all(&[next]);
138 }
139 } else {
140 if acc == 0 {
141 return self.write_all(&[next]);
142 }
143 }
144
145 next |= 0b1000_0000;
146
147 self.write_all(&[next])?;
148 }
149 }
150 }
151}
152
153
154impl <T> Leb128Write for T where T: Write {
155
156 write_unsigned_leb!(u16, write_leb128_u16);
157 write_unsigned_leb!(u32, write_leb128_u32);
158 write_unsigned_leb!(u64, write_leb128_u64);
159 write_unsigned_leb!(u128, write_leb128_u128);
160
161 write_signed_leb!(i16, u16, write_leb128_i16);
162 write_signed_leb!(i32, u32, write_leb128_i32);
163 write_signed_leb!(i64, u64, write_leb128_i64);
164 write_signed_leb!(i128, u128, write_leb128_i128);
165
166
167 fn write_leb128_large_signed(&mut self, value: &Vec<u8>) -> io::Result<()> {
168 if value.len() == 0 {
169 return Err(Error::new(ErrorKind::Other, "value parameter has len of 0"));
170 }
171
172 let mut last = value.len();
173 let is_negative = value[last-1] & 0b1000_0000u8 != 0;
174 if is_negative {
175 while last > 0 && value[last-1] == u8::MAX {
176 last -= 1;
177 }
178 } else {
179 while last > 0 && value[last-1] == 0{
180 last -= 1;
181 }
182 }
183
184 if last == 0 {
185 if is_negative {
186 return self.write_all(&[0b0111_1111u8]);
187 }
188 return self.write_all(&[0]);
189 }
190
191 let (mut acc, mut size) = pump_leb128_data(self, value, last)?;
192
193 let mut acc_cmp : u64 = !0;
194
195 if is_negative {
196 acc |= !((1 << size)-1)
197 }
198
199 loop {
200 size = size.saturating_sub(7);
201 let mut next = (acc & 0b0111_1111u64) as u8;
202 acc >>= 7;
203 acc_cmp >>= 7;
204
205 if size == 0 {
206 return self.write_all(&[next]);
207 }
208
209 if is_negative {
210 if acc == acc_cmp && next & 0b0100_0000 != 0 {
211 return self.write_all(&[next]);
212 }
213 } else {
214 if acc == 0 && next & 0b0100_0000 == 0 {
215 return self.write_all(&[next]);
216 }
217 }
218
219 next |= 0b1000_0000u8;
220
221 self.write_all(&[next])?;
222 }
223 }
224
225 fn write_leb128_large_unsigned(&mut self, value: &Vec<u8>) -> io::Result<()> {
226 if value.len() == 0 {
227 return Err(Error::new(ErrorKind::Other, "value parameter has len of 0"));
228 }
229
230 let mut last = value.len();
231 while last > 0 && value[last-1] == 0 {
232 last -= 1;
233 }
234
235 if last == 0 {
236 return self.write_all(&[0]);
237 }
238
239 let (mut acc, mut size) = pump_leb128_data(self, value, last)?;
240
241 loop {
242 size = size.saturating_sub(7);
243 let mut next = (acc & 0b0111_1111u64) as u8;
244 acc >>= 7;
245
246 if size == 0 || acc == 0 {
247 return self.write_all(&[next]);
248 }
249
250 next |= 0b1000_0000u8;
251
252 self.write_all(&[next])?;
253 }
254 }
255}
256
257mod private {
258 use std::io::Write;
259
260 impl <T> Sealed for T where T: Write {}
261 pub trait Sealed {
262
263 }
264}