+//! Some universal integer codes support for bitstream reader.
use crate::io::bitreader::{BitReader, BitReaderError, BitReaderResult};
+/// Unsigned integer code types.
#[derive(Debug)]
pub enum UintCodeType {
+ /// Code where number is represented as run of ones with terminating zero.
UnaryOnes,
+ /// Code where number is represented as run of zeroes with terminating one.
UnaryZeroes,
+ /// Code for 0, 1 and 2 coded as `0`, `10` and `11`
Unary012,
+ /// Code for 0, 1 and 2 coded as `11`, `10` and `0`
Unary210,
+ /// General limited unary code with defined run and terminating bit.
LimitedUnary(u32, u32),
+ /// Limited run of zeroes with terminating one (unless the code has maximum length).
+ ///
+ /// [`Unary012`] is essentially an alias for `LimitedZeroes(2)`.
+ ///
+ /// [`Unary012`]: #variant.Unary012
+ LimitedZeroes(u32),
+ /// Limited run of one with terminating zero (unless the code has maximum length).
+ LimitedOnes(u32),
+ /// Golomb code.
Golomb(u8),
+ /// Rice code.
Rice(u8),
+ /// Elias Gamma code (interleaved).
Gamma,
+ /// Elias Gamma' code (sometimes incorrectly called exp-Golomb).
GammaP,
}
+/// Signed integer code types.
pub enum IntCodeType {
+ /// Golomb code. Last bit represents the sign.
Golomb(u8),
+ /// Golomb code. Last bit represents the sign.
Rice(u8),
+ /// Elias Gamma code. Unsigned values are remapped as 0, 1, -1, 2, -2, ...
Gamma,
+ /// Elias Gamma' code. Unsigned values are remapped as 0, 1, -1, 2, -2, ...
GammaP,
}
+/// Universal integer code reader trait for bitstream reader.
+///
+/// # Examples
+///
+/// Read an unsigned Golomb code:
+/// ````
+/// use nihav_core::io::bitreader::*;
+/// use nihav_core::io::intcode::{IntCodeReader,UintCodeType};
+///
+/// # fn foo() -> BitReaderResult<()> {
+/// let mem: [u8; 4] = [ 0, 1, 2, 3];
+/// let mut br = BitReader::new(&mem, BitReaderMode::BE);
+/// let val = br.read_code(UintCodeType::Golomb(3))?;
+/// # Ok(())
+/// # }
+/// ````
+///
+/// Read signed Elias code:
+/// ````
+/// use nihav_core::io::bitreader::*;
+/// use nihav_core::io::intcode::{IntCodeReader,IntCodeType};
+///
+/// # fn foo() -> BitReaderResult<()> {
+/// let mem: [u8; 4] = [ 0, 1, 2, 3];
+/// let mut br = BitReader::new(&mem, BitReaderMode::BE);
+/// let val = br.read_code_signed(IntCodeType::Gamma)?;
+/// # Ok(())
+/// # }
+/// ````
pub trait IntCodeReader {
+ /// Reads an unsigned integer code of requested type.
fn read_code(&mut self, t: UintCodeType) -> BitReaderResult<u32>;
+ /// Reads signed integer code of requested type.
fn read_code_signed(&mut self, t: IntCodeType) -> BitReaderResult<i32>;
}
let mut res: u32 = 0;
loop {
if br.read(1)? == terminator { return Ok(res); }
- res = res + 1;
+ res += 1;
}
}
let mut res: u32 = 0;
loop {
if br.read(1)? == terminator { return Ok(res); }
- res = res + 1;
+ res += 1;
if res == len { return Ok(res); }
}
}
if m == 0 { return Err(BitReaderError::InvalidValue); }
let nbits = (8 - m.leading_zeros()) as u8;
if (m & (m - 1)) == 0 { return read_rice(br, nbits); }
- let cutoff = ((1 << nbits) - m) as u32;
+ let cutoff = u32::from((1 << nbits) - m);
let pfx = read_unary(br, 0)?;
let tail = br.read(nbits - 1)?;
if tail < cutoff {
- let res = pfx * (m as u32) + tail;
+ let res = pfx * u32::from(m) + tail;
Ok (res)
} else {
let add = br.read(1)?;
- let res = pfx * (m as u32) + (tail - cutoff) * 2 + add + cutoff;
+ let res = pfx * u32::from(m) + (tail - cutoff) * 2 + add + cutoff;
Ok (res)
}
}
match t {
UintCodeType::UnaryOnes => read_unary(self, 0),
UintCodeType::UnaryZeroes => read_unary(self, 1),
+ UintCodeType::LimitedZeroes(len) => read_unary_lim(self, len, 1),
+ UintCodeType::LimitedOnes(len) => read_unary_lim(self, len, 0),
UintCodeType::LimitedUnary(len, term) => read_unary_lim(self, len, term),
UintCodeType::Unary012 => read_unary_lim(self, 2, 0),
UintCodeType::Unary210 => read_unary210(self),
fn int_codes() {
const GDATA: [u8; 6] = [0b000_001_01, 0b0_0110_011, 0b1_1000_100, 0b1_1010_101, 0b10_10111_1, 0b1000_0000];
let src = &GDATA;
- let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
+ let mut br = BitReader::new(src, BitReaderMode::BE);
for i in 0..11 {
assert_eq!(br.read_code(UintCodeType::Golomb(5)).unwrap(), i);
}