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