rw_utils/
leb128_write.rs

1use std::io;
2use std::io::{Error, ErrorKind, Write};
3use std::mem::size_of;
4
5///
6/// Trait that provides various methods to write leb128 (little endian base 128) encoded numbers.
7/// Automatically implemented for all implementations of io::Write.
8/// This trait is sealed and cannot be implemented manually.
9///
10pub trait Leb128Write : private::Sealed {
11
12    ///
13    /// Writes a u16 as a unsigned leb128.
14    ///
15    fn write_leb128_u16(&mut self, value: u16) -> io::Result<()>;
16
17    ///
18    /// Writes a i16 as a signed leb128.
19    ///
20    fn write_leb128_i16(&mut self, value: i16) -> io::Result<()>;
21
22    ///
23    /// Writes a u32 as a unsigned leb128.
24    ///
25    fn write_leb128_u32(&mut self, value: u32) -> io::Result<()>;
26
27    ///
28    /// Writes a i32 as a signed leb128.
29    ///
30    fn write_leb128_i32(&mut self, value: i32) -> io::Result<()>;
31
32    ///
33    /// Writes a u64 as a unsigned leb128.
34    ///
35    fn write_leb128_u64(&mut self, value: u64) -> io::Result<()>;
36
37    ///
38    /// Writes a i64 as a signed leb128.
39    ///
40    fn write_leb128_i64(&mut self, value: i64) -> io::Result<()>;
41
42    ///
43    /// Writes a u128 as a unsigned leb128.
44    ///
45    fn write_leb128_u128(&mut self, value: u128) -> io::Result<()>;
46
47    ///
48    /// Writes a i128 as a signed leb128.
49    ///
50    fn write_leb128_i128(&mut self, value: i128) -> io::Result<()>;
51
52    ///
53    /// Write a signed leb128 of arbitrary length.
54    /// The input data is always treated as little endian.
55    ///
56    fn write_leb128_large_signed(&mut self, value: &Vec<u8>) -> io::Result<()>;
57
58    ///
59    /// Write an unsigned leb128 of arbitrary length.
60    /// The input data is always treated as little endian.
61    ///
62    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}