oximedia_io/bits/
exp_golomb.rs1use super::BitReader;
35use oximedia_core::{OxiError, OxiResult};
36
37impl BitReader<'_> {
38 pub fn read_exp_golomb(&mut self) -> OxiResult<u64> {
68 let mut leading_zeros: u8 = 0;
70 while self.read_bit()? == 0 {
71 leading_zeros += 1;
72 if leading_zeros > 63 {
73 return Err(OxiError::InvalidData(
74 "Exp-Golomb code too long (> 63 leading zeros)".to_string(),
75 ));
76 }
77 }
78
79 if leading_zeros == 0 {
80 return Ok(0);
81 }
82
83 let suffix = self.read_bits(leading_zeros)?;
85
86 Ok((1u64 << leading_zeros) - 1 + suffix)
88 }
89
90 #[allow(clippy::cast_possible_wrap)]
126 pub fn read_signed_exp_golomb(&mut self) -> OxiResult<i64> {
127 let ue = self.read_exp_golomb()?;
128
129 let abs_value = ue.div_ceil(2) as i64;
133 if ue & 1 == 0 {
134 Ok(-abs_value)
135 } else {
136 Ok(abs_value)
137 }
138 }
139
140 #[inline]
149 pub fn read_ue(&mut self) -> OxiResult<u64> {
150 self.read_exp_golomb()
151 }
152
153 #[inline]
162 pub fn read_se(&mut self) -> OxiResult<i64> {
163 self.read_signed_exp_golomb()
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_read_exp_golomb_zero() {
173 let data = [0b10000000];
175 let mut reader = BitReader::new(&data);
176 assert_eq!(
177 reader
178 .read_exp_golomb()
179 .expect("read_exp_golomb should succeed"),
180 0
181 );
182 assert_eq!(reader.bits_read(), 1);
183 }
184
185 #[test]
186 fn test_read_exp_golomb_one() {
187 let data = [0b01000000];
189 let mut reader = BitReader::new(&data);
190 assert_eq!(
191 reader
192 .read_exp_golomb()
193 .expect("read_exp_golomb should succeed"),
194 1
195 );
196 assert_eq!(reader.bits_read(), 3);
197 }
198
199 #[test]
200 fn test_read_exp_golomb_two() {
201 let data = [0b01100000];
203 let mut reader = BitReader::new(&data);
204 assert_eq!(
205 reader
206 .read_exp_golomb()
207 .expect("read_exp_golomb should succeed"),
208 2
209 );
210 assert_eq!(reader.bits_read(), 3);
211 }
212
213 #[test]
214 fn test_read_exp_golomb_three() {
215 let data = [0b00100000];
217 let mut reader = BitReader::new(&data);
218 assert_eq!(
219 reader
220 .read_exp_golomb()
221 .expect("read_exp_golomb should succeed"),
222 3
223 );
224 assert_eq!(reader.bits_read(), 5);
225 }
226
227 #[test]
228 fn test_read_exp_golomb_four() {
229 let data = [0b00101000];
231 let mut reader = BitReader::new(&data);
232 assert_eq!(
233 reader
234 .read_exp_golomb()
235 .expect("read_exp_golomb should succeed"),
236 4
237 );
238 assert_eq!(reader.bits_read(), 5);
239 }
240
241 #[test]
242 fn test_read_exp_golomb_five() {
243 let data = [0b00110000];
245 let mut reader = BitReader::new(&data);
246 assert_eq!(
247 reader
248 .read_exp_golomb()
249 .expect("read_exp_golomb should succeed"),
250 5
251 );
252 assert_eq!(reader.bits_read(), 5);
253 }
254
255 #[test]
256 fn test_read_exp_golomb_six() {
257 let data = [0b00111000];
259 let mut reader = BitReader::new(&data);
260 assert_eq!(
261 reader
262 .read_exp_golomb()
263 .expect("read_exp_golomb should succeed"),
264 6
265 );
266 assert_eq!(reader.bits_read(), 5);
267 }
268
269 #[test]
270 fn test_read_exp_golomb_seven() {
271 let data = [0b00010000];
273 let mut reader = BitReader::new(&data);
274 assert_eq!(
275 reader
276 .read_exp_golomb()
277 .expect("read_exp_golomb should succeed"),
278 7
279 );
280 assert_eq!(reader.bits_read(), 7);
281 }
282
283 #[test]
284 fn test_read_exp_golomb_large() {
285 let data = [0b00011110];
287 let mut reader = BitReader::new(&data);
288 assert_eq!(
289 reader
290 .read_exp_golomb()
291 .expect("read_exp_golomb should succeed"),
292 14
293 );
294 }
295
296 #[test]
297 fn test_read_signed_exp_golomb_zero() {
298 let data = [0b10000000];
300 let mut reader = BitReader::new(&data);
301 assert_eq!(
302 reader
303 .read_signed_exp_golomb()
304 .expect("read_signed_exp_golomb should succeed"),
305 0
306 );
307 }
308
309 #[test]
310 fn test_read_signed_exp_golomb_positive_one() {
311 let data = [0b01000000];
313 let mut reader = BitReader::new(&data);
314 assert_eq!(
315 reader
316 .read_signed_exp_golomb()
317 .expect("read_signed_exp_golomb should succeed"),
318 1
319 );
320 }
321
322 #[test]
323 fn test_read_signed_exp_golomb_negative_one() {
324 let data = [0b01100000];
326 let mut reader = BitReader::new(&data);
327 assert_eq!(
328 reader
329 .read_signed_exp_golomb()
330 .expect("read_signed_exp_golomb should succeed"),
331 -1
332 );
333 }
334
335 #[test]
336 fn test_read_signed_exp_golomb_positive_two() {
337 let data = [0b00100000];
339 let mut reader = BitReader::new(&data);
340 assert_eq!(
341 reader
342 .read_signed_exp_golomb()
343 .expect("read_signed_exp_golomb should succeed"),
344 2
345 );
346 }
347
348 #[test]
349 fn test_read_signed_exp_golomb_negative_two() {
350 let data = [0b00101000];
352 let mut reader = BitReader::new(&data);
353 assert_eq!(
354 reader
355 .read_signed_exp_golomb()
356 .expect("read_signed_exp_golomb should succeed"),
357 -2
358 );
359 }
360
361 #[test]
362 fn test_read_signed_exp_golomb_sequence() {
363 let test_cases: [(u64, i64); 7] =
365 [(0, 0), (1, 1), (2, -1), (3, 2), (4, -2), (5, 3), (6, -3)];
366
367 for (ue_val, expected_se) in test_cases {
368 let abs_value = ((ue_val + 1) / 2) as i64;
369 let se_val = if ue_val & 1 == 0 {
370 -abs_value
371 } else {
372 abs_value
373 };
374 assert_eq!(
375 se_val, expected_se,
376 "ue({ue_val}) should map to se({expected_se})"
377 );
378 }
379 }
380
381 #[test]
382 fn test_read_multiple_exp_golomb() {
383 let data = [0b10100000];
385 let mut reader = BitReader::new(&data);
386 assert_eq!(
387 reader
388 .read_exp_golomb()
389 .expect("read_exp_golomb should succeed"),
390 0
391 );
392 assert_eq!(
393 reader
394 .read_exp_golomb()
395 .expect("read_exp_golomb should succeed"),
396 1
397 );
398 }
399
400 #[test]
401 fn test_read_ue_alias() {
402 let data = [0b01000000];
403 let mut reader = BitReader::new(&data);
404 assert_eq!(reader.read_ue().expect("read_ue should succeed"), 1);
405 }
406
407 #[test]
408 fn test_read_se_alias() {
409 let data = [0b01100000];
410 let mut reader = BitReader::new(&data);
411 assert_eq!(reader.read_se().expect("read_se should succeed"), -1);
412 }
413
414 #[test]
415 fn test_exp_golomb_eof() {
416 let data = [0b00000000];
418 let mut reader = BitReader::new(&data);
419 let result = reader.read_exp_golomb();
420 assert!(result.is_err());
421 }
422
423 #[test]
426 fn test_exp_golomb_boundary_values() {
427 let data = [0b00011110];
430 let mut reader = BitReader::new(&data);
431 assert_eq!(
432 reader
433 .read_exp_golomb()
434 .expect("read_exp_golomb should succeed"),
435 14
436 );
437
438 let data = [0b00011111];
440 let mut reader = BitReader::new(&data);
441 assert_eq!(
442 reader
443 .read_exp_golomb()
444 .expect("read_exp_golomb should succeed"),
445 14
446 );
447 }
448
449 #[test]
450 fn test_exp_golomb_consecutive_zeros() {
451 let data = [0b11110000]; let mut reader = BitReader::new(&data);
454 assert_eq!(
455 reader
456 .read_exp_golomb()
457 .expect("read_exp_golomb should succeed"),
458 0
459 );
460 assert_eq!(
461 reader
462 .read_exp_golomb()
463 .expect("read_exp_golomb should succeed"),
464 0
465 );
466 assert_eq!(
467 reader
468 .read_exp_golomb()
469 .expect("read_exp_golomb should succeed"),
470 0
471 );
472 assert_eq!(
473 reader
474 .read_exp_golomb()
475 .expect("read_exp_golomb should succeed"),
476 0
477 );
478 }
479
480 #[test]
481 fn test_signed_exp_golomb_range() {
482 let test_cases = [
484 (0b10000000, 0), (0b01000000, 1), (0b01100000, -1), (0b00100000, 2), (0b00101000, -2), (0b00110000, 3), (0b00111000, -3), ];
492
493 for (data_byte, expected) in test_cases {
494 let data = [data_byte];
495 let mut reader = BitReader::new(&data);
496 assert_eq!(
497 reader
498 .read_signed_exp_golomb()
499 .expect("read_signed_exp_golomb should succeed"),
500 expected
501 );
502 }
503 }
504
505 #[test]
506 fn test_signed_exp_golomb_large_values() {
507 let data = [0b00010100];
511 let mut reader = BitReader::new(&data);
512 assert_eq!(
513 reader
514 .read_signed_exp_golomb()
515 .expect("read_signed_exp_golomb should succeed"),
516 5
517 );
518
519 let data = [0b00010110];
522 let mut reader = BitReader::new(&data);
523 assert_eq!(
524 reader
525 .read_signed_exp_golomb()
526 .expect("read_signed_exp_golomb should succeed"),
527 -5
528 );
529 }
530
531 #[test]
532 fn test_exp_golomb_mixed_with_other_reads() {
533 let data = [0b11100000]; let mut reader = BitReader::new(&data);
536
537 assert!(reader.read_flag().expect("read_flag should succeed"));
538 assert!(reader.read_flag().expect("read_flag should succeed"));
539 assert_eq!(
540 reader
541 .read_exp_golomb()
542 .expect("read_exp_golomb should succeed"),
543 0
544 );
545 }
546
547 #[test]
548 fn test_exp_golomb_too_many_leading_zeros() {
549 let data = [0x00; 10]; let mut reader = BitReader::new(&data);
552 let result = reader.read_exp_golomb();
553 assert!(result.is_err());
554 }
555
556 #[test]
557 fn test_exp_golomb_insufficient_suffix_bits() {
558 let data = [0b00000001]; let mut reader = BitReader::new(&data);
561 let result = reader.read_exp_golomb();
562 assert!(result.is_err());
563 }
564
565 #[test]
566 fn test_exp_golomb_arithmetic() {
567 let data = [0b00010110];
571 let mut reader = BitReader::new(&data);
572 assert_eq!(
573 reader
574 .read_exp_golomb()
575 .expect("read_exp_golomb should succeed"),
576 10
577 );
578 }
579
580 #[test]
581 fn test_signed_zero_mapping() {
582 let data = [0b10000000];
584 let mut reader = BitReader::new(&data);
585 let value = reader.read_se().expect("read_se should succeed");
586 assert_eq!(value, 0);
587 }
588
589 #[test]
590 fn test_alternating_signed_pattern() {
591 let data = [
594 0b01001100, 0b10000000, ];
597 let mut reader = BitReader::new(&data);
598
599 assert_eq!(reader.read_se().expect("read_se should succeed"), 1);
600 assert_eq!(reader.read_se().expect("read_se should succeed"), -1);
601 assert_eq!(reader.read_se().expect("read_se should succeed"), 2);
602 }
603
604 #[test]
605 fn test_ue_se_alias_consistency() {
606 let data = [0b01000000, 0b01100000];
608 let mut reader = BitReader::new(&data);
609
610 let ue_val = reader.read_ue().expect("read_ue should succeed");
611 let se_val = reader.read_se().expect("read_se should succeed");
612
613 let mut reader2 = BitReader::new(&data);
614 assert_eq!(
615 reader2
616 .read_exp_golomb()
617 .expect("read_exp_golomb should succeed"),
618 ue_val
619 );
620 assert_eq!(
621 reader2
622 .read_signed_exp_golomb()
623 .expect("read_signed_exp_golomb should succeed"),
624 se_val
625 );
626 }
627}