1use super::{write_into, WriteInto};
2use std::io;
3use std::mem::{size_of, MaybeUninit};
4
5pub struct Uleb128<T>(pub T);
17
18pub struct Sleb128<T>(pub T);
30
31macro_rules! impl_write_into {
32 ($($wrapper:ident => { $($primitive:ident)* }),*,) => {
33 $(
34 $(
35 impl_impl!($wrapper, $primitive);
36 )*
37 )*
38 }
39}
40
41macro_rules! impl_impl {
42 (Uleb128, $primitive:ident) => {
43 impl WriteInto for Uleb128<$primitive> {
44 type Output = usize;
45
46 fn write_into(mut self, sink: &mut impl io::Write) -> io::Result<Self::Output> {
47 let mut buffer = unsafe {
50 MaybeUninit::<[MaybeUninit<u8>; max_leb128_size(size_of::<Self>())]>::uninit()
52 .assume_init()
53 };
54
55 let mut written = 0;
56 for byte in buffer.iter_mut() {
57 let mut value = self.0 as u8 & 0x7F;
58 self.0 >>= 7;
59 if self.0 != 0 {
60 value |= 0x80;
61 }
62
63 *byte = MaybeUninit::new(value);
64 written += 1;
65
66 if self.0 == 0 {
67 break;
68 }
69 }
70
71 let bytes = unsafe {
74 &*(&buffer[..written] as *const [MaybeUninit<u8>] as *const [u8])
76 };
77
78 sink.write_all(bytes)?;
79 Ok(written)
80 }
81 }
82
83 impl WriteInto for &Uleb128<$primitive> {
84 type Output = usize;
85
86 fn write_into(self, sink: &mut impl io::Write) -> io::Result<Self::Output> {
87 write_into(sink, Uleb128(self.0))
88 }
89 }
90 };
91 (Sleb128, $primitive:ident) => {
92 impl WriteInto for Sleb128<$primitive> {
93 type Output = usize;
94
95 fn write_into(mut self, sink: &mut impl io::Write) -> io::Result<Self::Output> {
96 let mut buffer = unsafe {
99 MaybeUninit::<[MaybeUninit<u8>; max_leb128_size(size_of::<Self>())]>::uninit()
101 .assume_init()
102 };
103
104 let mut written = 0;
105 for byte in buffer.iter_mut() {
106 let mut value = self.0 as u8;
107 self.0 >>= 6; let done = self.0 == 0 || self.0 == -1;
109 if done {
110 value &= 0x7F;
111 } else {
112 self.0 >>= 1;
113 value |= 0x80;
114 }
115
116 *byte = MaybeUninit::new(value);
117 written += 1;
118
119 if done {
120 break;
121 }
122 }
123
124 let bytes = unsafe {
127 &*(&buffer[..written] as *const [MaybeUninit<u8>] as *const [u8])
129 };
130
131 sink.write_all(bytes)?;
132 Ok(written)
133 }
134 }
135
136 impl WriteInto for &Sleb128<$primitive> {
137 type Output = usize;
138
139 fn write_into(self, sink: &mut impl io::Write) -> io::Result<Self::Output> {
140 write_into(sink, Sleb128(self.0))
141 }
142 }
143 };
144}
145
146impl_write_into! {
147 Uleb128 => {
148 u8 u16 u32 u64 u128 usize
149 },
150 Sleb128 => {
151 i8 i16 i32 i64 i128 isize
152 },
153}
154
155const fn max_leb128_size(bytes: usize) -> usize {
156 let bits = bytes * 8;
157 let septets = count_bits_in_chunks(bits, 7);
158 let bits_for_septents = septets * 7;
159 let bits_for_continutation_bits = septets * 1;
160 count_bits_in_chunks(bits_for_septents + bits_for_continutation_bits, 8)
161}
162
163const fn count_bits_in_chunks(bits: usize, chunk_size: usize) -> usize {
164 let chunks = bits / chunk_size;
165 let remaining = bits % chunk_size;
166 chunks + if remaining != 0 { 1 } else { 0 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::super::*;
172 use super::*;
173 use test_case::test_case;
174 use validators::vec;
175
176 mod validators {
177 pub fn vec(expected: &[u8]) -> impl FnOnce(Vec<u8>) {
178 let expected = expected.to_vec();
179 move |actual| assert_eq!(&expected, &actual)
180 }
181 }
182
183 #[test_case( 1 => 2; "when u8" )]
184 #[test_case( 2 => 3; "when u16" )]
185 #[test_case( 4 => 5; "when u32" )]
186 #[test_case( 8 => 10; "when u64" )]
187 #[test_case( 16 => 19; "when u128" )]
188 fn max_leb128_size_for_primitive_types(bytes: usize) -> usize {
189 max_leb128_size(bytes)
190 }
191
192 #[test_case( 0 => using vec(&[ 0x00 ]); "when 0" )]
193 #[test_case( 69 => using vec(&[ 0x45 ]); "when 69" )]
194 #[test_case( 123 => using vec(&[ 0x7B ]); "when 123" )]
195 #[test_case( 127 => using vec(&[ 0x7F ]); "when 127" )]
196 #[test_case( 128 => using vec(&[ 0x80, 0x01 ]); "when 128" )]
197 #[test_case( 228 => using vec(&[ 0xE4, 0x01 ]); "when 228" )]
198 #[test_case( 255 => using vec(&[ 0xFF, 0x01 ]); "when 255" )]
199 #[test_case( 4200 => using vec(&[ 0xE8, 0x20 ]); "when 4200" )]
200 #[test_case( 16383 => using vec(&[ 0xFF, 0x7F ]); "when 16383" )]
201 #[test_case( 32767 => using vec(&[ 0xFF, 0xFF, 0x01 ]); "when 32767" )]
202 #[test_case( 42000 => using vec(&[ 0x90, 0xC8, 0x02 ]); "when 42000" )]
203 #[test_case( 65535 => using vec(&[ 0xFF, 0xFF, 0x03 ]); "when 65535" )]
204 fn write_u16(number: u16) -> Vec<u8> {
205 let mut buffer = Vec::new();
206 write_into(&mut buffer, Uleb128(number)).unwrap();
207 buffer
208 }
209
210 #[test_case( -32768 => using vec(&[ 0x80, 0x80, 0x7E ]); "when minus 32768" )]
211 #[test_case( -8192 => using vec(&[ 0x80, 0x40 ]); "when minus 8192" )]
212 #[test_case( -4200 => using vec(&[ 0x98, 0x5F ]); "when minus 4200" )]
213 #[test_case( -128 => using vec(&[ 0x80, 0x7F ]); "when minus 128" )]
214 #[test_case( -123 => using vec(&[ 0x85, 0x7F ]); "when minus 123" )]
215 #[test_case( -69 => using vec(&[ 0xBB, 0x7F ]); "when minus 69" )]
216 #[test_case( -34 => using vec(&[ 0x5E ]); "when minus 34" )]
217 #[test_case( 0 => using vec(&[ 0x00 ]); "when 0" )]
218 #[test_case( 34 => using vec(&[ 0x22 ]); "when 34" )]
219 #[test_case( 69 => using vec(&[ 0xC5, 0x00 ]); "when 69" )]
220 #[test_case( 123 => using vec(&[ 0xFB, 0x00 ]); "when 123" )]
221 #[test_case( 127 => using vec(&[ 0xFF, 0x00 ]); "when 127" )]
222 #[test_case( 4200 => using vec(&[ 0xE8, 0x20 ]); "when 4200" )]
223 #[test_case( 8191 => using vec(&[ 0xFF, 0x3F ]); "when 8191" )]
224 #[test_case( 32767 => using vec(&[ 0xFF, 0xFF, 0x01 ]); "when 32767" )]
225 fn write_i16(number: i16) -> Vec<u8> {
226 let mut buffer = Vec::new();
227 write_into(&mut buffer, Sleb128(number)).unwrap();
228 buffer
229 }
230}