1#![cfg_attr(feature = "docs", doc = "\n\nSee the [changelog][changelog] for a full release history.")]
7#![cfg_attr(feature = "docs", doc = "## Feature flags")]
8#![cfg_attr(feature = "docs", doc = document_features::document_features!())]
9#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
45#![cfg_attr(docsrs, feature(doc_auto_cfg))]
46#![deny(missing_docs)]
47#![deny(unsafe_code)]
48#![deny(unreachable_pub)]
49#![deny(clippy::mod_module_files)]
50
51use std::io;
52
53use scuffle_bytes_util::{BitReader, BitWriter};
54
55pub trait BitReaderExpGolombExt {
61 fn read_exp_golomb(&mut self) -> io::Result<u64>;
63
64 fn read_signed_exp_golomb(&mut self) -> io::Result<i64> {
66 let exp_glob = self.read_exp_golomb()?;
67
68 if exp_glob.is_multiple_of(2) {
69 Ok(-((exp_glob / 2) as i64))
70 } else {
71 Ok((exp_glob / 2) as i64 + 1)
72 }
73 }
74}
75
76impl<R: io::Read> BitReaderExpGolombExt for BitReader<R> {
77 fn read_exp_golomb(&mut self) -> io::Result<u64> {
78 let mut leading_zeros = 0;
79 while !self.read_bit()? {
80 leading_zeros += 1;
81 }
82
83 let mut result = 1;
84 for _ in 0..leading_zeros {
85 result <<= 1;
86 result |= self.read_bit()? as u64;
87 }
88
89 Ok(result - 1)
90 }
91}
92
93pub trait BitWriterExpGolombExt {
99 fn write_exp_golomb(&mut self, input: u64) -> io::Result<()>;
101
102 fn write_signed_exp_golomb(&mut self, number: i64) -> io::Result<()> {
104 let number = if number <= 0 {
105 -number as u64 * 2
106 } else {
107 number as u64 * 2 - 1
108 };
109
110 self.write_exp_golomb(number)
111 }
112}
113
114impl<W: io::Write> BitWriterExpGolombExt for BitWriter<W> {
115 fn write_exp_golomb(&mut self, input: u64) -> io::Result<()> {
116 let mut number = input + 1;
117 let mut leading_zeros = 0;
118 while number > 1 {
119 number >>= 1;
120 leading_zeros += 1;
121 }
122
123 for _ in 0..leading_zeros {
124 self.write_bit(false)?;
125 }
126
127 self.write_bits(input + 1, leading_zeros + 1)?;
128
129 Ok(())
130 }
131}
132
133pub fn size_of_signed_exp_golomb(number: i64) -> u64 {
137 let number = if number <= 0 {
138 -number as u64 * 2
139 } else {
140 number as u64 * 2 - 1
141 };
142
143 size_of_exp_golomb(number)
144}
145
146pub fn size_of_exp_golomb(number: u64) -> u64 {
150 let mut number = number + 1;
151 let mut leading_zeros = 0;
152 while number > 1 {
153 number >>= 1;
154 leading_zeros += 1;
155 }
156
157 leading_zeros * 2 + 1
158}
159
160#[cfg(test)]
161#[cfg_attr(all(test, coverage_nightly), coverage(off))]
162mod tests {
163 use bytes::Buf;
164 use scuffle_bytes_util::{BitReader, BitWriter};
165
166 use crate::{BitReaderExpGolombExt, BitWriterExpGolombExt, size_of_exp_golomb, size_of_signed_exp_golomb};
167
168 pub(crate) fn get_remaining_bits(reader: &BitReader<std::io::Cursor<Vec<u8>>>) -> usize {
169 let remaining = reader.get_ref().remaining();
170
171 if reader.is_aligned() {
172 remaining * 8
173 } else {
174 remaining * 8 + (8 - reader.bit_pos() as usize)
175 }
176 }
177
178 #[test]
179 fn test_exp_glob_decode() {
180 let mut bit_writer = BitWriter::<Vec<u8>>::default();
181
182 bit_writer.write_bits(0b1, 1).unwrap(); bit_writer.write_bits(0b010, 3).unwrap(); bit_writer.write_bits(0b011, 3).unwrap(); bit_writer.write_bits(0b00100, 5).unwrap(); bit_writer.write_bits(0b00101, 5).unwrap(); bit_writer.write_bits(0b00110, 5).unwrap(); bit_writer.write_bits(0b00111, 5).unwrap(); let data = bit_writer.finish().unwrap();
191
192 let mut bit_reader = BitReader::new(std::io::Cursor::new(data));
193
194 let remaining_bits = get_remaining_bits(&bit_reader);
195
196 let result = bit_reader.read_exp_golomb().unwrap();
197 assert_eq!(result, 0);
198 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 1);
199
200 let result = bit_reader.read_exp_golomb().unwrap();
201 assert_eq!(result, 1);
202 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 4);
203
204 let result = bit_reader.read_exp_golomb().unwrap();
205 assert_eq!(result, 2);
206 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 7);
207
208 let result = bit_reader.read_exp_golomb().unwrap();
209 assert_eq!(result, 3);
210 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 12);
211
212 let result = bit_reader.read_exp_golomb().unwrap();
213 assert_eq!(result, 4);
214 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 17);
215
216 let result = bit_reader.read_exp_golomb().unwrap();
217 assert_eq!(result, 5);
218 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 22);
219
220 let result = bit_reader.read_exp_golomb().unwrap();
221 assert_eq!(result, 6);
222 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 27);
223 }
224
225 #[test]
226 fn test_signed_exp_glob_decode() {
227 let mut bit_writer = BitWriter::<Vec<u8>>::default();
228
229 bit_writer.write_bits(0b1, 1).unwrap(); bit_writer.write_bits(0b010, 3).unwrap(); bit_writer.write_bits(0b011, 3).unwrap(); bit_writer.write_bits(0b00100, 5).unwrap(); bit_writer.write_bits(0b00101, 5).unwrap(); bit_writer.write_bits(0b00110, 5).unwrap(); bit_writer.write_bits(0b00111, 5).unwrap(); let data = bit_writer.finish().unwrap();
238
239 let mut bit_reader = BitReader::new(std::io::Cursor::new(data));
240
241 let remaining_bits = get_remaining_bits(&bit_reader);
242
243 let result = bit_reader.read_signed_exp_golomb().unwrap();
244 assert_eq!(result, 0);
245 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 1);
246
247 let result = bit_reader.read_signed_exp_golomb().unwrap();
248 assert_eq!(result, 1);
249 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 4);
250
251 let result = bit_reader.read_signed_exp_golomb().unwrap();
252 assert_eq!(result, -1);
253 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 7);
254
255 let result = bit_reader.read_signed_exp_golomb().unwrap();
256 assert_eq!(result, 2);
257 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 12);
258
259 let result = bit_reader.read_signed_exp_golomb().unwrap();
260 assert_eq!(result, -2);
261 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 17);
262
263 let result = bit_reader.read_signed_exp_golomb().unwrap();
264 assert_eq!(result, 3);
265 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 22);
266
267 let result = bit_reader.read_signed_exp_golomb().unwrap();
268 assert_eq!(result, -3);
269 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 27);
270 }
271
272 #[test]
273 fn test_exp_glob_encode() {
274 let mut bit_writer = BitWriter::<Vec<u8>>::default();
275
276 bit_writer.write_exp_golomb(0).unwrap();
277 bit_writer.write_exp_golomb(1).unwrap();
278 bit_writer.write_exp_golomb(2).unwrap();
279 bit_writer.write_exp_golomb(3).unwrap();
280 bit_writer.write_exp_golomb(4).unwrap();
281 bit_writer.write_exp_golomb(5).unwrap();
282 bit_writer.write_exp_golomb(6).unwrap();
283 bit_writer.write_exp_golomb(u64::MAX - 1).unwrap();
284
285 let data = bit_writer.finish().unwrap();
286
287 let mut bit_reader = BitReader::new(std::io::Cursor::new(data));
288
289 let remaining_bits = get_remaining_bits(&bit_reader);
290
291 let result = bit_reader.read_exp_golomb().unwrap();
292 assert_eq!(result, 0);
293 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 1);
294
295 let result = bit_reader.read_exp_golomb().unwrap();
296 assert_eq!(result, 1);
297 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 4);
298
299 let result = bit_reader.read_exp_golomb().unwrap();
300 assert_eq!(result, 2);
301 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 7);
302
303 let result = bit_reader.read_exp_golomb().unwrap();
304 assert_eq!(result, 3);
305 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 12);
306
307 let result = bit_reader.read_exp_golomb().unwrap();
308 assert_eq!(result, 4);
309 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 17);
310
311 let result = bit_reader.read_exp_golomb().unwrap();
312 assert_eq!(result, 5);
313 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 22);
314
315 let result = bit_reader.read_exp_golomb().unwrap();
316 assert_eq!(result, 6);
317 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 27);
318
319 let result = bit_reader.read_exp_golomb().unwrap();
320 assert_eq!(result, u64::MAX - 1);
321 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 154);
322 }
323
324 #[test]
325 fn test_signed_exp_glob_encode() {
326 let mut bit_writer = BitWriter::<Vec<u8>>::default();
327
328 bit_writer.write_signed_exp_golomb(0).unwrap();
329 bit_writer.write_signed_exp_golomb(1).unwrap();
330 bit_writer.write_signed_exp_golomb(-1).unwrap();
331 bit_writer.write_signed_exp_golomb(2).unwrap();
332 bit_writer.write_signed_exp_golomb(-2).unwrap();
333 bit_writer.write_signed_exp_golomb(3).unwrap();
334 bit_writer.write_signed_exp_golomb(-3).unwrap();
335 bit_writer.write_signed_exp_golomb(i64::MAX).unwrap();
336
337 let data = bit_writer.finish().unwrap();
338
339 let mut bit_reader = BitReader::new(std::io::Cursor::new(data));
340
341 let remaining_bits = get_remaining_bits(&bit_reader);
342
343 let result = bit_reader.read_signed_exp_golomb().unwrap();
344 assert_eq!(result, 0);
345 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 1);
346
347 let result = bit_reader.read_signed_exp_golomb().unwrap();
348 assert_eq!(result, 1);
349 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 4);
350
351 let result = bit_reader.read_signed_exp_golomb().unwrap();
352 assert_eq!(result, -1);
353 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 7);
354
355 let result = bit_reader.read_signed_exp_golomb().unwrap();
356 assert_eq!(result, 2);
357 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 12);
358
359 let result = bit_reader.read_signed_exp_golomb().unwrap();
360 assert_eq!(result, -2);
361 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 17);
362
363 let result = bit_reader.read_signed_exp_golomb().unwrap();
364 assert_eq!(result, 3);
365 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 22);
366
367 let result = bit_reader.read_signed_exp_golomb().unwrap();
368 assert_eq!(result, -3);
369 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 27);
370
371 let result = bit_reader.read_signed_exp_golomb().unwrap();
372 assert_eq!(result, i64::MAX);
373 assert_eq!(get_remaining_bits(&bit_reader), remaining_bits - 154);
374 }
375
376 #[test]
377 fn test_expg_sizes() {
378 assert_eq!(1, size_of_exp_golomb(0)); assert_eq!(3, size_of_exp_golomb(1)); assert_eq!(3, size_of_exp_golomb(2)); assert_eq!(5, size_of_exp_golomb(3)); assert_eq!(5, size_of_exp_golomb(4)); assert_eq!(5, size_of_exp_golomb(5)); assert_eq!(5, size_of_exp_golomb(6)); assert_eq!(1, size_of_signed_exp_golomb(0)); assert_eq!(3, size_of_signed_exp_golomb(1)); assert_eq!(3, size_of_signed_exp_golomb(-1)); assert_eq!(5, size_of_signed_exp_golomb(2)); assert_eq!(5, size_of_signed_exp_golomb(-2)); assert_eq!(5, size_of_signed_exp_golomb(3)); assert_eq!(5, size_of_signed_exp_golomb(-3)); }
394}
395
396#[cfg(feature = "docs")]
398#[scuffle_changelog::changelog]
399pub mod changelog {}