1 //! Some universal integer codes support for bitstream reader.
2 use crate::io::bitreader::{BitReader, BitReaderError, BitReaderResult};
3 use crate::io::bitwriter::BitWriter;
5 /// Unsigned integer code types.
7 pub enum UintCodeType {
8 /// Code where number is represented as run of ones with terminating zero.
10 /// Code where number is represented as run of zeroes with terminating one.
12 /// Code for 0, 1 and 2 coded as `0`, `10` and `11`
14 /// Code for 0, 1 and 2 coded as `11`, `10` and `0`
16 /// General limited unary code with defined run and terminating bit.
17 LimitedUnary(u32, u32),
18 /// Limited run of zeroes with terminating one (unless the code has maximum length).
20 /// [`Unary012`] is essentially an alias for `LimitedZeroes(2)`.
22 /// [`Unary012`]: #variant.Unary012
24 /// Limited run of one with terminating zero (unless the code has maximum length).
30 /// Elias Gamma code (interleaved).
32 /// Elias Gamma' code (sometimes incorrectly called exp-Golomb).
36 /// Signed integer code types.
37 pub enum IntCodeType {
38 /// Golomb code. Last bit represents the sign.
40 /// Golomb code. Last bit represents the sign.
42 /// Elias Gamma code. Unsigned values are remapped as 0, 1, -1, 2, -2, ...
44 /// Elias Gamma' code. Unsigned values are remapped as 0, 1, -1, 2, -2, ...
48 /// Universal integer code reader trait for bitstream reader.
52 /// Read an unsigned Golomb code:
54 /// use nihav_core::io::bitreader::*;
55 /// use nihav_core::io::intcode::{IntCodeReader,UintCodeType};
57 /// # fn foo() -> BitReaderResult<()> {
58 /// let mem: [u8; 4] = [ 0, 1, 2, 3];
59 /// let mut br = BitReader::new(&mem, BitReaderMode::BE);
60 /// let val = br.read_code(UintCodeType::Golomb(3))?;
65 /// Read signed Elias code:
67 /// use nihav_core::io::bitreader::*;
68 /// use nihav_core::io::intcode::{IntCodeReader,IntCodeType};
70 /// # fn foo() -> BitReaderResult<()> {
71 /// let mem: [u8; 4] = [ 0, 1, 2, 3];
72 /// let mut br = BitReader::new(&mem, BitReaderMode::BE);
73 /// let val = br.read_code_signed(IntCodeType::Gamma)?;
77 pub trait IntCodeReader {
78 /// Reads an unsigned integer code of requested type.
79 fn read_code(&mut self, t: UintCodeType) -> BitReaderResult<u32>;
80 /// Reads signed integer code of requested type.
81 fn read_code_signed(&mut self, t: IntCodeType) -> BitReaderResult<i32>;
84 fn read_unary(br: &mut BitReader, terminator: u32) -> BitReaderResult<u32> {
87 if br.read(1)? == terminator { return Ok(res); }
92 fn read_unary_lim(br: &mut BitReader, len: u32, terminator: u32) -> BitReaderResult<u32> {
95 if br.read(1)? == terminator { return Ok(res); }
97 if res == len { return Ok(res); }
101 fn read_unary210(br: &mut BitReader) -> BitReaderResult<u32> {
102 let val = read_unary_lim(br, 2, 0)?;
106 fn read_golomb(br: &mut BitReader, m: u8) -> BitReaderResult<u32> {
107 if m == 0 { return Err(BitReaderError::InvalidValue); }
108 let nbits = (8 - m.leading_zeros()) as u8;
109 if (m & (m - 1)) == 0 { return read_rice(br, nbits); }
110 let cutoff = u32::from((1 << nbits) - m);
111 let pfx = read_unary(br, 0)?;
112 let tail = br.read(nbits - 1)?;
114 let res = pfx * u32::from(m) + tail;
117 let add = br.read(1)?;
118 let res = pfx * u32::from(m) + (tail - cutoff) * 2 + add + cutoff;
123 fn read_rice(br: &mut BitReader, k: u8) -> BitReaderResult<u32> {
124 let pfx = read_unary(br, 1)?;
125 let ret = (pfx << k) + br.read(k)?;
129 fn read_gamma(br: &mut BitReader) -> BitReaderResult<u32> {
131 while br.read(1)? != 1 {
132 ret = (ret << 1) | br.read(1)?;
137 fn read_gammap(br: &mut BitReader) -> BitReaderResult<u32> {
138 let pfx = read_unary(br, 1)?;
139 if pfx > 32 { return Err(BitReaderError::InvalidValue); }
140 let ret = (1 << pfx) + br.read(pfx as u8)?;
144 fn uval_to_sval0mp(uval: u32) -> i32 {
145 if (uval & 1) != 0 { -(((uval + 1) >> 1) as i32) }
146 else { (uval >> 1) as i32 }
149 fn uval_to_sval0pm(uval: u32) -> i32 {
150 if (uval & 1) != 0 { ((uval + 1) >> 1) as i32 }
151 else { -((uval >> 1) as i32) }
154 impl<'a> IntCodeReader for BitReader<'a> {
156 fn read_code(&mut self, t: UintCodeType) -> BitReaderResult<u32> {
158 UintCodeType::UnaryOnes => read_unary(self, 0),
159 UintCodeType::UnaryZeroes => read_unary(self, 1),
160 UintCodeType::LimitedZeroes(len) => read_unary_lim(self, len, 1),
161 UintCodeType::LimitedOnes(len) => read_unary_lim(self, len, 0),
162 UintCodeType::LimitedUnary(len, term) => read_unary_lim(self, len, term),
163 UintCodeType::Unary012 => read_unary_lim(self, 2, 0),
164 UintCodeType::Unary210 => read_unary210(self),
165 UintCodeType::Golomb(m) => read_golomb(self, m),
166 UintCodeType::Rice(k) => read_rice(self, k),
167 UintCodeType::Gamma => read_gamma(self),
168 UintCodeType::GammaP => read_gammap(self),
171 #[allow(unused_variables)]
172 fn read_code_signed(&mut self, t: IntCodeType) -> BitReaderResult<i32> {
175 IntCodeType::Golomb(m) => read_golomb(self, m)?,
176 IntCodeType::Rice(k) => read_rice(self, k)?,
177 IntCodeType::Gamma => read_gamma(self)?,
178 IntCodeType::GammaP => read_gammap(self)?,
181 IntCodeType::Golomb(m) => Ok(uval_to_sval0mp(uval)),
182 IntCodeType::Rice(k) => Ok(uval_to_sval0mp(uval)),
183 IntCodeType::Gamma => Ok(uval_to_sval0pm(uval)),
184 IntCodeType::GammaP => Ok(uval_to_sval0pm(uval)),
189 /// Universal integer code writer trait for bitstream writer.
193 /// Write an unsigned Golomb code:
195 /// use nihav_core::io::bitwriter::*;
196 /// use nihav_core::io::intcode::{IntCodeWriter,UintCodeType};
198 /// let mut bw = BitWriter::new(Vec::new(), BitWriterMode::BE);
199 /// bw.write_code(UintCodeType::Golomb(3), 42);
202 /// Write signed Elias code:
204 /// use nihav_core::io::bitwriter::*;
205 /// use nihav_core::io::intcode::{IntCodeWriter,IntCodeType};
207 /// let mut bw = BitWriter::new(Vec::new(), BitWriterMode::BE);
208 /// bw.write_code_signed(IntCodeType::Gamma, 42)?;
210 pub trait IntCodeWriter {
211 /// Writes an unsigned integer code of requested type.
212 fn write_code(&mut self, t: UintCodeType, val: u32);
213 /// Writes signed integer code of requested type.
214 fn write_code_signed(&mut self, t: IntCodeType, val: i32);
217 impl IntCodeWriter for BitWriter {
219 fn write_code(&mut self, t: UintCodeType, val: u32) {
221 UintCodeType::UnaryOnes => write_unary(self, val, 0),
222 UintCodeType::UnaryZeroes => write_unary(self, val, 1),
223 UintCodeType::LimitedZeroes(len) => write_unary_lim(self, val, len, 1),
224 UintCodeType::LimitedOnes(len) => write_unary_lim(self, val, len, 0),
225 UintCodeType::LimitedUnary(len, term) => write_unary_lim(self, val, len, term),
226 UintCodeType::Unary012 => write_unary_lim(self, val, 2, 0),
227 UintCodeType::Unary210 => write_unary210(self, val),
228 UintCodeType::Golomb(m) => write_golomb(self, val, m),
229 UintCodeType::Rice(k) => write_rice(self, val, k),
230 UintCodeType::Gamma => write_gamma(self, val),
231 UintCodeType::GammaP => write_gammap(self, val),
234 fn write_code_signed(&mut self, t: IntCodeType, val: i32) {
236 IntCodeType::Golomb(m) => write_golomb(self, sval0mp_to_uval(val), m),
237 IntCodeType::Rice(k) => write_rice(self, sval0mp_to_uval(val), k),
238 IntCodeType::Gamma => write_gamma(self, sval0pm_to_uval(val)),
239 IntCodeType::GammaP => write_gammap(self, sval0pm_to_uval(val)),
244 fn sval0mp_to_uval(val: i32) -> u32 {
245 if val < 0 { (-val as u32) * 2 - 1 }
246 else { (val as u32) * 2 }
249 fn sval0pm_to_uval(val: i32) -> u32 {
250 if val >= 0 { (val as u32) * 2 + 1 }
251 else { (-val as u32) * 2 }
254 fn write_unary210(bw: &mut BitWriter, val: u32) {
255 bw.write_bit(val == 0);
257 bw.write_bit(val == 1);
261 fn write_unary(bw: &mut BitWriter, val: u32, term: u32) {
262 let term = term != 0;
269 fn write_unary_lim(bw: &mut BitWriter, val: u32, maxval: u32, term: u32) {
270 let term = term != 0;
279 fn write_rice(bw: &mut BitWriter, val: u32, k: u8) {
280 let mut exp = val >> k;
286 bw.write(0, exp as u8);
290 let mant = val & ((1 << k) - 1);
295 fn write_golomb(bw: &mut BitWriter, val: u32, m: u8) {
296 if m == 0 { return; }
297 let nbits = (8 - m.leading_zeros()) as u8;
298 if (m & (m - 1)) == 0 { return write_rice(bw, val, nbits); }
299 let q = val / u32::from(m);
300 let r = val % u32::from(m);
301 let cutoff = u32::from((1 << nbits) - m);
303 write_unary(bw, q, 0);
305 bw.write(r, nbits - 1);
307 bw.write(r + cutoff, nbits);
311 fn write_gamma(bw: &mut BitWriter, val: u32) {
313 let bits = (32 - val.leading_zeros()) as u8;
314 let mut mask = 1 << bits >> 2;
317 bw.write_bit((val & mask) != 0);
323 fn write_gammap(bw: &mut BitWriter, val: u32) {
324 let bits = 31 - val.leading_zeros();
325 write_unary(bw, bits, 1);
326 bw.write(val - (1 << bits), bits as u8);
332 use crate::io::bitreader::*;
333 use crate::io::bitwriter::*;
337 const GDATA: [u8; 6] = [0b000_001_01, 0b0_0110_011, 0b1_1000_100, 0b1_1010_101, 0b10_10111_1, 0b1000_0000];
339 let mut br = BitReader::new(src, BitReaderMode::BE);
341 assert_eq!(br.read_code(UintCodeType::Golomb(5)).unwrap(), i);
346 let mut bw = BitWriter::new(Vec::new(), BitWriterMode::BE);
347 bw.write_code(UintCodeType::Golomb(5), 42);
348 bw.write_code(UintCodeType::Gamma, 42);
349 bw.write_code(UintCodeType::GammaP, 42);
351 let mut br = BitReader::new(&data, BitReaderMode::BE);
353 let mut br = BitReader::new(&data, BitReaderMode::BE);
354 assert_eq!(br.read_code(UintCodeType::Golomb(5)).unwrap(), 42);
355 assert_eq!(br.read_code(UintCodeType::Gamma).unwrap(), 42);
356 assert_eq!(br.read_code(UintCodeType::GammaP).unwrap(), 42);