1 //! Some universal integer codes support for bitstream reader.
2 use crate::io::bitreader::{BitReader, BitReaderError, BitReaderResult};
4 /// Unsigned integer code types.
6 pub enum UintCodeType {
7 /// Code where number is represented as run of ones with terminating zero.
9 /// Code where number is represented as run of zeroes with terminating one.
11 /// Code for 0, 1 and 2 coded as `0`, `10` and `11`
13 /// Code for 0, 1 and 2 coded as `11`, `10` and `0`
15 /// General limited unary code with defined run and terminating bit.
16 LimitedUnary(u32, u32),
17 /// Limited run of zeroes with terminating one (unless the code has maximum length).
19 /// [`Unary012`] is essentially an alias for `LimitedZeroes(2)`.
21 /// [`Unary012`]: #variant.Unary012
23 /// Limited run of one with terminating zero (unless the code has maximum length).
29 /// Elias Gamma code (interleaved).
31 /// Elias Gamma' code (sometimes incorrectly called exp-Golomb).
35 /// Signed integer code types.
36 pub enum IntCodeType {
37 /// Golomb code. Last bit represents the sign.
39 /// Golomb code. Last bit represents the sign.
41 /// Elias Gamma code. Unsigned values are remapped as 0, 1, -1, 2, -2, ...
43 /// Elias Gamma' code. Unsigned values are remapped as 0, 1, -1, 2, -2, ...
47 /// Universal integer code reader trait for bitstream reader.
51 /// Read an unsigned Golomb code:
53 /// use nihav_core::io::bitreader::*;
54 /// use nihav_core::io::intcode::{IntCodeReader,UintCodeType};
56 /// # fn foo() -> BitReaderResult<()> {
57 /// let mem: [u8; 4] = [ 0, 1, 2, 3];
58 /// let mut br = BitReader::new(&mem, BitReaderMode::BE);
59 /// let val = br.read_code(UintCodeType::Golomb(3))?;
64 /// Read signed Elias code:
66 /// use nihav_core::io::bitreader::*;
67 /// use nihav_core::io::intcode::{IntCodeReader,IntCodeType};
69 /// # fn foo() -> BitReaderResult<()> {
70 /// let mem: [u8; 4] = [ 0, 1, 2, 3];
71 /// let mut br = BitReader::new(&mem, BitReaderMode::BE);
72 /// let val = br.read_code_signed(IntCodeType::Gamma)?;
76 pub trait IntCodeReader {
77 /// Reads an unsigned integer code of requested type.
78 fn read_code(&mut self, t: UintCodeType) -> BitReaderResult<u32>;
79 /// Reads signed integer code of requested type.
80 fn read_code_signed(&mut self, t: IntCodeType) -> BitReaderResult<i32>;
83 fn read_unary(br: &mut BitReader, terminator: u32) -> BitReaderResult<u32> {
86 if br.read(1)? == terminator { return Ok(res); }
91 fn read_unary_lim(br: &mut BitReader, len: u32, terminator: u32) -> BitReaderResult<u32> {
94 if br.read(1)? == terminator { return Ok(res); }
96 if res == len { return Ok(res); }
100 fn read_unary210(br: &mut BitReader) -> BitReaderResult<u32> {
101 let val = read_unary_lim(br, 2, 0)?;
105 fn read_golomb(br: &mut BitReader, m: u8) -> BitReaderResult<u32> {
106 if m == 0 { return Err(BitReaderError::InvalidValue); }
107 let nbits = (8 - m.leading_zeros()) as u8;
108 if (m & (m - 1)) == 0 { return read_rice(br, nbits); }
109 let cutoff = u32::from((1 << nbits) - m);
110 let pfx = read_unary(br, 0)?;
111 let tail = br.read(nbits - 1)?;
113 let res = pfx * u32::from(m) + tail;
116 let add = br.read(1)?;
117 let res = pfx * u32::from(m) + (tail - cutoff) * 2 + add + cutoff;
122 fn read_rice(br: &mut BitReader, k: u8) -> BitReaderResult<u32> {
123 let pfx = read_unary(br, 1)?;
124 let ret = (pfx << k) + br.read(k)?;
128 fn read_gamma(br: &mut BitReader) -> BitReaderResult<u32> {
130 while br.read(1)? != 1 {
131 ret = (ret << 1) | br.read(1)?;
136 fn read_gammap(br: &mut BitReader) -> BitReaderResult<u32> {
137 let pfx = read_unary(br, 1)?;
138 if pfx > 32 { return Err(BitReaderError::InvalidValue); }
139 let ret = (1 << pfx) + br.read(pfx as u8)?;
143 fn uval_to_sval0mp(uval: u32) -> i32 {
144 if (uval & 1) != 0 { -((uval >> 1) as i32) }
145 else { (uval >> 1) as i32 }
148 fn uval_to_sval0pm(uval: u32) -> i32 {
149 if (uval & 1) != 0 { ((uval + 1) >> 1) as i32 }
150 else { -((uval >> 1) as i32) }
153 impl<'a> IntCodeReader for BitReader<'a> {
155 fn read_code(&mut self, t: UintCodeType) -> BitReaderResult<u32> {
157 UintCodeType::UnaryOnes => read_unary(self, 0),
158 UintCodeType::UnaryZeroes => read_unary(self, 1),
159 UintCodeType::LimitedZeroes(len) => read_unary_lim(self, len, 1),
160 UintCodeType::LimitedOnes(len) => read_unary_lim(self, len, 0),
161 UintCodeType::LimitedUnary(len, term) => read_unary_lim(self, len, term),
162 UintCodeType::Unary012 => read_unary_lim(self, 2, 0),
163 UintCodeType::Unary210 => read_unary210(self),
164 UintCodeType::Golomb(m) => read_golomb(self, m),
165 UintCodeType::Rice(k) => read_rice(self, k),
166 UintCodeType::Gamma => read_gamma(self),
167 UintCodeType::GammaP => read_gammap(self),
170 #[allow(unused_variables)]
171 fn read_code_signed(&mut self, t: IntCodeType) -> BitReaderResult<i32> {
174 IntCodeType::Golomb(m) => read_golomb(self, m)?,
175 IntCodeType::Rice(k) => read_rice(self, k)?,
176 IntCodeType::Gamma => read_gamma(self)?,
177 IntCodeType::GammaP => read_gammap(self)?,
180 IntCodeType::Golomb(m) => Ok(uval_to_sval0mp(uval)),
181 IntCodeType::Rice(k) => Ok(uval_to_sval0mp(uval)),
182 IntCodeType::Gamma => Ok(uval_to_sval0pm(uval)),
183 IntCodeType::GammaP => Ok(uval_to_sval0pm(uval)),
191 use crate::io::bitreader::*;
195 const GDATA: [u8; 6] = [0b000_001_01, 0b0_0110_011, 0b1_1000_100, 0b1_1010_101, 0b10_10111_1, 0b1000_0000];
197 let mut br = BitReader::new(src, BitReaderMode::BE);
199 assert_eq!(br.read_code(UintCodeType::Golomb(5)).unwrap(), i);