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> {
71 let mut leading_zeros: u8 = 0;
73 while self.read_bit()? == 0 {
74 leading_zeros += 1;
75 if leading_zeros > 63 {
76 return Err(OxiError::InvalidData(
77 "Exp-Golomb code too long (> 63 leading zeros)".to_string(),
78 ));
79 }
80 }
81
82 if leading_zeros == 0 {
83 return Ok(0);
84 }
85
86 let suffix = self.read_bits(leading_zeros)?;
88
89 Ok((1u64 << leading_zeros) - 1 + suffix)
91 }
92
93 #[allow(clippy::cast_possible_wrap)]
132 pub fn read_signed_exp_golomb(&mut self) -> OxiResult<i64> {
133 let ue = self.read_exp_golomb()?;
134
135 let abs_value = ue.div_ceil(2) as i64;
139 if ue & 1 == 0 {
140 Ok(-abs_value)
141 } else {
142 Ok(abs_value)
143 }
144 }
145
146 #[inline]
155 pub fn read_ue(&mut self) -> OxiResult<u64> {
156 self.read_exp_golomb()
157 }
158
159 #[inline]
168 pub fn read_se(&mut self) -> OxiResult<i64> {
169 self.read_signed_exp_golomb()
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_read_exp_golomb_zero() {
179 let data = [0b10000000];
181 let mut reader = BitReader::new(&data);
182 assert_eq!(
183 reader
184 .read_exp_golomb()
185 .expect("read_exp_golomb should succeed"),
186 0
187 );
188 assert_eq!(reader.bits_read(), 1);
189 }
190
191 #[test]
192 fn test_read_exp_golomb_one() {
193 let data = [0b01000000];
195 let mut reader = BitReader::new(&data);
196 assert_eq!(
197 reader
198 .read_exp_golomb()
199 .expect("read_exp_golomb should succeed"),
200 1
201 );
202 assert_eq!(reader.bits_read(), 3);
203 }
204
205 #[test]
206 fn test_read_exp_golomb_two() {
207 let data = [0b01100000];
209 let mut reader = BitReader::new(&data);
210 assert_eq!(
211 reader
212 .read_exp_golomb()
213 .expect("read_exp_golomb should succeed"),
214 2
215 );
216 assert_eq!(reader.bits_read(), 3);
217 }
218
219 #[test]
220 fn test_read_exp_golomb_three() {
221 let data = [0b00100000];
223 let mut reader = BitReader::new(&data);
224 assert_eq!(
225 reader
226 .read_exp_golomb()
227 .expect("read_exp_golomb should succeed"),
228 3
229 );
230 assert_eq!(reader.bits_read(), 5);
231 }
232
233 #[test]
234 fn test_read_exp_golomb_four() {
235 let data = [0b00101000];
237 let mut reader = BitReader::new(&data);
238 assert_eq!(
239 reader
240 .read_exp_golomb()
241 .expect("read_exp_golomb should succeed"),
242 4
243 );
244 assert_eq!(reader.bits_read(), 5);
245 }
246
247 #[test]
248 fn test_read_exp_golomb_five() {
249 let data = [0b00110000];
251 let mut reader = BitReader::new(&data);
252 assert_eq!(
253 reader
254 .read_exp_golomb()
255 .expect("read_exp_golomb should succeed"),
256 5
257 );
258 assert_eq!(reader.bits_read(), 5);
259 }
260
261 #[test]
262 fn test_read_exp_golomb_six() {
263 let data = [0b00111000];
265 let mut reader = BitReader::new(&data);
266 assert_eq!(
267 reader
268 .read_exp_golomb()
269 .expect("read_exp_golomb should succeed"),
270 6
271 );
272 assert_eq!(reader.bits_read(), 5);
273 }
274
275 #[test]
276 fn test_read_exp_golomb_seven() {
277 let data = [0b00010000];
279 let mut reader = BitReader::new(&data);
280 assert_eq!(
281 reader
282 .read_exp_golomb()
283 .expect("read_exp_golomb should succeed"),
284 7
285 );
286 assert_eq!(reader.bits_read(), 7);
287 }
288
289 #[test]
290 fn test_read_exp_golomb_large() {
291 let data = [0b00011110];
293 let mut reader = BitReader::new(&data);
294 assert_eq!(
295 reader
296 .read_exp_golomb()
297 .expect("read_exp_golomb should succeed"),
298 14
299 );
300 }
301
302 #[test]
303 fn test_read_signed_exp_golomb_zero() {
304 let data = [0b10000000];
306 let mut reader = BitReader::new(&data);
307 assert_eq!(
308 reader
309 .read_signed_exp_golomb()
310 .expect("read_signed_exp_golomb should succeed"),
311 0
312 );
313 }
314
315 #[test]
316 fn test_read_signed_exp_golomb_positive_one() {
317 let data = [0b01000000];
319 let mut reader = BitReader::new(&data);
320 assert_eq!(
321 reader
322 .read_signed_exp_golomb()
323 .expect("read_signed_exp_golomb should succeed"),
324 1
325 );
326 }
327
328 #[test]
329 fn test_read_signed_exp_golomb_negative_one() {
330 let data = [0b01100000];
332 let mut reader = BitReader::new(&data);
333 assert_eq!(
334 reader
335 .read_signed_exp_golomb()
336 .expect("read_signed_exp_golomb should succeed"),
337 -1
338 );
339 }
340
341 #[test]
342 fn test_read_signed_exp_golomb_positive_two() {
343 let data = [0b00100000];
345 let mut reader = BitReader::new(&data);
346 assert_eq!(
347 reader
348 .read_signed_exp_golomb()
349 .expect("read_signed_exp_golomb should succeed"),
350 2
351 );
352 }
353
354 #[test]
355 fn test_read_signed_exp_golomb_negative_two() {
356 let data = [0b00101000];
358 let mut reader = BitReader::new(&data);
359 assert_eq!(
360 reader
361 .read_signed_exp_golomb()
362 .expect("read_signed_exp_golomb should succeed"),
363 -2
364 );
365 }
366
367 #[test]
368 fn test_read_signed_exp_golomb_sequence() {
369 let test_cases: [(u64, i64); 7] =
371 [(0, 0), (1, 1), (2, -1), (3, 2), (4, -2), (5, 3), (6, -3)];
372
373 for (ue_val, expected_se) in test_cases {
374 let abs_value = ((ue_val + 1) / 2) as i64;
375 let se_val = if ue_val & 1 == 0 {
376 -abs_value
377 } else {
378 abs_value
379 };
380 assert_eq!(
381 se_val, expected_se,
382 "ue({ue_val}) should map to se({expected_se})"
383 );
384 }
385 }
386
387 #[test]
388 fn test_read_multiple_exp_golomb() {
389 let data = [0b10100000];
391 let mut reader = BitReader::new(&data);
392 assert_eq!(
393 reader
394 .read_exp_golomb()
395 .expect("read_exp_golomb should succeed"),
396 0
397 );
398 assert_eq!(
399 reader
400 .read_exp_golomb()
401 .expect("read_exp_golomb should succeed"),
402 1
403 );
404 }
405
406 #[test]
407 fn test_read_ue_alias() {
408 let data = [0b01000000];
409 let mut reader = BitReader::new(&data);
410 assert_eq!(reader.read_ue().expect("read_ue should succeed"), 1);
411 }
412
413 #[test]
414 fn test_read_se_alias() {
415 let data = [0b01100000];
416 let mut reader = BitReader::new(&data);
417 assert_eq!(reader.read_se().expect("read_se should succeed"), -1);
418 }
419
420 #[test]
421 fn test_exp_golomb_eof() {
422 let data = [0b00000000];
424 let mut reader = BitReader::new(&data);
425 let result = reader.read_exp_golomb();
426 assert!(result.is_err());
427 }
428
429 #[test]
432 fn test_exp_golomb_boundary_values() {
433 let data = [0b00011110];
436 let mut reader = BitReader::new(&data);
437 assert_eq!(
438 reader
439 .read_exp_golomb()
440 .expect("read_exp_golomb should succeed"),
441 14
442 );
443
444 let data = [0b00011111];
446 let mut reader = BitReader::new(&data);
447 assert_eq!(
448 reader
449 .read_exp_golomb()
450 .expect("read_exp_golomb should succeed"),
451 14
452 );
453 }
454
455 #[test]
456 fn test_exp_golomb_consecutive_zeros() {
457 let data = [0b11110000]; let mut reader = BitReader::new(&data);
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 assert_eq!(
479 reader
480 .read_exp_golomb()
481 .expect("read_exp_golomb should succeed"),
482 0
483 );
484 }
485
486 #[test]
487 fn test_signed_exp_golomb_range() {
488 let test_cases = [
490 (0b10000000, 0), (0b01000000, 1), (0b01100000, -1), (0b00100000, 2), (0b00101000, -2), (0b00110000, 3), (0b00111000, -3), ];
498
499 for (data_byte, expected) in test_cases {
500 let data = [data_byte];
501 let mut reader = BitReader::new(&data);
502 assert_eq!(
503 reader
504 .read_signed_exp_golomb()
505 .expect("read_signed_exp_golomb should succeed"),
506 expected
507 );
508 }
509 }
510
511 #[test]
512 fn test_signed_exp_golomb_large_values() {
513 let data = [0b00010100];
517 let mut reader = BitReader::new(&data);
518 assert_eq!(
519 reader
520 .read_signed_exp_golomb()
521 .expect("read_signed_exp_golomb should succeed"),
522 5
523 );
524
525 let data = [0b00010110];
528 let mut reader = BitReader::new(&data);
529 assert_eq!(
530 reader
531 .read_signed_exp_golomb()
532 .expect("read_signed_exp_golomb should succeed"),
533 -5
534 );
535 }
536
537 #[test]
538 fn test_exp_golomb_mixed_with_other_reads() {
539 let data = [0b11100000]; let mut reader = BitReader::new(&data);
542
543 assert!(reader.read_flag().expect("read_flag should succeed"));
544 assert!(reader.read_flag().expect("read_flag should succeed"));
545 assert_eq!(
546 reader
547 .read_exp_golomb()
548 .expect("read_exp_golomb should succeed"),
549 0
550 );
551 }
552
553 #[test]
554 fn test_exp_golomb_too_many_leading_zeros() {
555 let data = [0x00; 10]; let mut reader = BitReader::new(&data);
558 let result = reader.read_exp_golomb();
559 assert!(result.is_err());
560 }
561
562 #[test]
563 fn test_exp_golomb_insufficient_suffix_bits() {
564 let data = [0b00000001]; let mut reader = BitReader::new(&data);
567 let result = reader.read_exp_golomb();
568 assert!(result.is_err());
569 }
570
571 #[test]
572 fn test_exp_golomb_arithmetic() {
573 let data = [0b00010110];
577 let mut reader = BitReader::new(&data);
578 assert_eq!(
579 reader
580 .read_exp_golomb()
581 .expect("read_exp_golomb should succeed"),
582 10
583 );
584 }
585
586 #[test]
587 fn test_signed_zero_mapping() {
588 let data = [0b10000000];
590 let mut reader = BitReader::new(&data);
591 let value = reader.read_se().expect("read_se should succeed");
592 assert_eq!(value, 0);
593 }
594
595 #[test]
596 fn test_alternating_signed_pattern() {
597 let data = [
600 0b01001100, 0b10000000, ];
603 let mut reader = BitReader::new(&data);
604
605 assert_eq!(reader.read_se().expect("read_se should succeed"), 1);
606 assert_eq!(reader.read_se().expect("read_se should succeed"), -1);
607 assert_eq!(reader.read_se().expect("read_se should succeed"), 2);
608 }
609
610 #[test]
611 fn test_ue_se_alias_consistency() {
612 let data = [0b01000000, 0b01100000];
614 let mut reader = BitReader::new(&data);
615
616 let ue_val = reader.read_ue().expect("read_ue should succeed");
617 let se_val = reader.read_se().expect("read_se should succeed");
618
619 let mut reader2 = BitReader::new(&data);
620 assert_eq!(
621 reader2
622 .read_exp_golomb()
623 .expect("read_exp_golomb should succeed"),
624 ue_val
625 );
626 assert_eq!(
627 reader2
628 .read_signed_exp_golomb()
629 .expect("read_signed_exp_golomb should succeed"),
630 se_val
631 );
632 }
633}