|
| 1 | +use bytes::{BytesMut, BufMut, Buf}; |
| 2 | +use std::cmp; |
| 3 | + |
| 4 | +pub struct ExpGolomb { |
| 5 | + buffer: BytesMut, |
| 6 | + index: usize, |
| 7 | + total_bits: usize, |
| 8 | + total_bytes: usize, |
| 9 | + current_word: usize, |
| 10 | + current_word_bits_left: usize |
| 11 | +} |
| 12 | + |
| 13 | +impl ExpGolomb { |
| 14 | + pub fn new(data: &[u8]) -> Self { |
| 15 | + let total_bytes = data.len(); |
| 16 | + Self { |
| 17 | + index: 0, |
| 18 | + total_bytes, |
| 19 | + current_word: 0, |
| 20 | + current_word_bits_left: 0, |
| 21 | + total_bits: total_bytes * 8, |
| 22 | + buffer: BytesMut::from(data), |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + #[rustfmt::skip] |
| 27 | + fn fill_current_word(&mut self) { |
| 28 | + let buffer_bytes_left = self.total_bytes - self.index; |
| 29 | + let bytes_read = cmp::min(4, buffer_bytes_left); |
| 30 | + let mut word = BytesMut::from(&self.buffer[self.index..self.index + bytes_read]); |
| 31 | + self.current_word = word.get_u32() as usize; |
| 32 | + self.current_word_bits_left = bytes_read * 8; |
| 33 | + self.index = bytes_read; |
| 34 | + } |
| 35 | + |
| 36 | + #[rustfmt::skip] |
| 37 | + fn skip_leading_zero(&mut self) -> usize { |
| 38 | + let mut zero_count = 0; |
| 39 | + for _ in zero_count..(self.current_word_bits_left - 1) { |
| 40 | + if self.current_word & (0x80000000 >> zero_count) != 0 { |
| 41 | + self.current_word <<= zero_count; |
| 42 | + self.current_word_bits_left -= zero_count; |
| 43 | + return zero_count; |
| 44 | + } |
| 45 | + |
| 46 | + zero_count += 1; |
| 47 | + } |
| 48 | + |
| 49 | + self.fill_current_word(); |
| 50 | + return zero_count + self.skip_leading_zero(); |
| 51 | + } |
| 52 | + |
| 53 | + #[rustfmt::skip] |
| 54 | + pub fn read_bits(&mut self, bits: usize) -> usize { |
| 55 | + if bits <= self.current_word_bits_left { |
| 56 | + let result = self.current_word >> (32 - bits); |
| 57 | + self.current_word_bits_left -= bits; |
| 58 | + self.current_word <<= bits; |
| 59 | + return result; |
| 60 | + } |
| 61 | + |
| 62 | + let mut result = if self.current_word_bits_left > 0 { self.current_word } else { 0 }; |
| 63 | + result = result >> (32 - self.current_word_bits_left); |
| 64 | + let bits_need_left = bits - self.current_word_bits_left; |
| 65 | + self.fill_current_word(); |
| 66 | + let bits_read_next = cmp::min(bits_need_left, self.current_word_bits_left); |
| 67 | + let result2 = self.current_word >> (32 - bits_read_next); |
| 68 | + self.current_word_bits_left -= bits_read_next; |
| 69 | + self.current_word <<= bits_read_next; |
| 70 | + result = (result << bits_read_next) | result2; |
| 71 | + result |
| 72 | + } |
| 73 | + |
| 74 | + #[rustfmt::skip] |
| 75 | + pub fn read_bool(&mut self) -> bool { |
| 76 | + self.read_bits(1) == 1 |
| 77 | + } |
| 78 | + |
| 79 | + #[rustfmt::skip] |
| 80 | + pub fn read_byte(&mut self) -> usize { |
| 81 | + self.read_bits(8) |
| 82 | + } |
| 83 | + |
| 84 | + #[rustfmt::skip] |
| 85 | + pub fn read_ueg(&mut self) -> usize { |
| 86 | + let leading_zeros = self.skip_leading_zero(); |
| 87 | + self.read_bits(leading_zeros + 1) - 1 |
| 88 | + } |
| 89 | + |
| 90 | + #[rustfmt::skip] |
| 91 | + pub fn read_seg(&mut self) -> usize { |
| 92 | + let value = self.read_ueg(); |
| 93 | + match value & 0x01 > 0 { |
| 94 | + true => (value + 1) >> 1, |
| 95 | + false => 0 - (value >> 1) |
| 96 | + } |
| 97 | + } |
| 98 | +} |
0 commit comments