use super::{BIN_TOTAL, BIN_TOTAL_BITS, BOT, TOP, corrupt, internal};
use super::{IntoRangeInput, RangeDecoder, RangeEncoder, RangeInput, RangeOutput};
use crate::error::{Error, Result};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RangeCoderState {
pub(crate) low: u32,
pub(crate) code: u32,
pub(crate) range: u32,
}
impl Default for RangeCoderState {
fn default() -> Self {
Self {
low: 0,
code: 0,
range: u32::MAX,
}
}
}
impl RangeCoderState {
pub fn new(low: u32, code: u32, range: u32) -> Self {
Self { low, code, range }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CarrylessEncoderRegs {
pub(crate) low: u32,
pub(crate) range: u32,
}
impl Default for CarrylessEncoderRegs {
fn default() -> Self {
Self {
low: 0,
range: u32::MAX,
}
}
}
#[derive(Debug)]
pub struct CarrylessRangeDecoder<I: RangeInput> {
low: u32,
code: u32,
range: u32,
faulted: bool,
input: I,
}
impl<I: RangeInput> CarrylessRangeDecoder<I> {
pub fn new<T: IntoRangeInput<Input = I>>(input: T) -> Result<Self> {
let mut input = input.into_range_input();
let mut code = 0u32;
for _ in 0..4 {
code = (code << 8) | u32::from(input.next_byte());
}
if input.zero_bytes_past_eof() != 0 {
return Err(Error::truncated());
}
Ok(Self::from_parts(
input,
RangeCoderState {
low: 0,
code,
range: u32::MAX,
},
))
}
pub fn new_7a<T: IntoRangeInput<Input = I>>(input: T) -> Result<Self> {
let decoder = Self::new(input)?;
if decoder.code == u32::MAX {
return Err(corrupt(
"carry-less range coder: initial code is 0xFFFFFFFF",
));
}
Ok(decoder)
}
pub fn from_state<T: IntoRangeInput<Input = I>>(input: T, state: RangeCoderState) -> Self {
Self::from_parts(input.into_range_input(), state)
}
fn from_parts(input: I, state: RangeCoderState) -> Self {
Self {
low: state.low,
code: state.code,
range: state.range,
faulted: false,
input,
}
}
#[inline]
pub fn state(&self) -> RangeCoderState {
RangeCoderState {
low: self.low,
code: self.code,
range: self.range,
}
}
#[inline]
pub fn is_finished_ok(&self) -> bool {
self.code == self.low
}
#[inline]
pub fn position(&self) -> usize {
self.input.position()
}
#[inline]
pub fn zero_bytes_past_eof(&self) -> u32 {
self.input.zero_bytes_past_eof()
}
pub fn input(&self) -> &I {
&self.input
}
pub fn into_input(self) -> I {
self.input
}
#[inline(always)]
pub fn get_current_count(&mut self, scale: u32) -> Result<u32> {
let count = self.get_threshold(scale);
if self.faulted {
return Err(corrupt(
"carry-less range coder: frequency total past the range",
));
}
Ok(count)
}
#[inline(always)]
pub fn decode_freq(&mut self, cum: u32, freq: u32, _scale: u32) {
self.decode(cum, freq);
}
#[inline]
pub fn decode_binary(&mut self, freq0: u32, scale: u32) -> Result<bool> {
let count = self.get_current_count(scale)?;
if count < freq0 {
self.decode(0, freq0);
Ok(true)
} else {
self.decode(freq0, scale.wrapping_sub(freq0));
Ok(false)
}
}
#[inline(always)]
fn normalize(&mut self) {
if self.range == 0 {
self.fault();
}
loop {
if (self.low ^ self.low.wrapping_add(self.range)) >= TOP {
if self.range >= BOT {
break;
}
self.range = self.low.wrapping_neg() & (BOT - 1);
}
self.code = (self.code << 8) | u32::from(self.input.next_byte());
self.range <<= 8;
self.low <<= 8;
}
}
#[cold]
#[inline(never)]
fn fault(&mut self) -> u32 {
self.faulted = true;
self.range = 1;
u32::MAX
}
}
impl<I: RangeInput> RangeDecoder for CarrylessRangeDecoder<I> {
#[inline(always)]
fn get_threshold(&mut self, total: u32) -> u32 {
self.range = self.range.checked_div(total).unwrap_or(0);
if self.range == 0 {
return self.fault();
}
self.code.wrapping_sub(self.low) / self.range
}
#[inline(always)]
fn decode(&mut self, start: u32, size: u32) {
self.low = self.low.wrapping_add(start.wrapping_mul(self.range));
self.range = size.wrapping_mul(self.range);
self.normalize();
}
#[inline(always)]
fn decode_bit(&mut self, size0: u32) -> u32 {
self.range >>= BIN_TOTAL_BITS;
let count = match self.code.wrapping_sub(self.low).checked_div(self.range) {
Some(count) => count,
None => self.fault(),
};
if count < size0 {
self.range = size0.wrapping_mul(self.range);
self.normalize();
0
} else {
self.low = self.low.wrapping_add(size0.wrapping_mul(self.range));
self.range = BIN_TOTAL.wrapping_sub(size0).wrapping_mul(self.range);
self.normalize();
1
}
}
#[inline(always)]
fn faulted(&self) -> bool {
self.faulted
}
}
#[derive(Debug)]
pub struct CarrylessRangeEncoder<O: RangeOutput> {
low: u32,
range: u32,
faulted: bool,
out: O,
}
impl<O: RangeOutput> CarrylessRangeEncoder<O> {
pub fn new(out: O) -> Self {
Self {
low: 0,
range: u32::MAX,
faulted: false,
out,
}
}
pub fn output(&self) -> &O {
&self.out
}
pub fn output_mut(&mut self) -> &mut O {
&mut self.out
}
#[inline]
pub fn resume(out: O, regs: CarrylessEncoderRegs) -> Self {
Self {
low: regs.low,
range: regs.range,
faulted: false,
out,
}
}
#[inline]
pub fn regs(&self) -> CarrylessEncoderRegs {
CarrylessEncoderRegs {
low: self.low,
range: self.range,
}
}
pub fn flush(&mut self) {
for _ in 0..4 {
self.out.write_byte((self.low >> 24) as u8);
self.low <<= 8;
}
}
pub fn finish(mut self) -> Result<O> {
self.flush();
if self.faulted {
return Err(internal(
"carry-less range encoder: frequency total past the range",
));
}
Ok(self.out)
}
#[inline(always)]
fn normalize(&mut self) {
loop {
if (self.low ^ self.low.wrapping_add(self.range)) >= TOP {
if self.range >= BOT {
break;
}
self.range = self.low.wrapping_neg() & (BOT - 1);
}
self.out.write_byte((self.low >> 24) as u8);
self.range <<= 8;
self.low <<= 8;
}
}
#[cold]
#[inline(never)]
fn fault(&mut self) {
self.faulted = true;
}
}
impl<O: RangeOutput> RangeEncoder for CarrylessRangeEncoder<O> {
#[inline(always)]
fn encode(&mut self, start: u32, size: u32, total: u32) {
let range = self.range.checked_div(total).unwrap_or(0);
let range_out = range.wrapping_mul(size);
if range_out == 0 {
return self.fault();
}
self.low = self.low.wrapping_add(start.wrapping_mul(range));
self.range = range_out;
self.normalize();
}
#[inline(always)]
fn encode_bit(&mut self, size0: u32, bit: u32) {
let range = self.range >> BIN_TOTAL_BITS;
let (start, size) = if bit == 0 {
(0, size0)
} else {
(size0, BIN_TOTAL.wrapping_sub(size0))
};
let range_out = size.wrapping_mul(range);
if range_out == 0 {
return self.fault();
}
self.low = self.low.wrapping_add(start.wrapping_mul(range));
self.range = range_out;
self.normalize();
}
#[inline(always)]
fn faulted(&self) -> bool {
self.faulted
}
}
#[cfg(test)]
mod tests {
use super::super::SliceInput;
use super::*;
fn dec(bytes: &[u8]) -> CarrylessRangeDecoder<SliceInput<'_>> {
CarrylessRangeDecoder::new(bytes).unwrap()
}
#[test]
fn init_reads_four_big_endian_bytes_and_accepts_any_code() {
let d = dec(&[0x40, 0x00, 0x00, 0x01, 0xFF]);
assert_eq!(
d.state(),
RangeCoderState {
low: 0,
code: 0x4000_0001,
range: u32::MAX
}
);
assert_eq!(d.position(), 4);
assert!(CarrylessRangeDecoder::new(&[0xFF; 4][..]).is_ok());
assert!(matches!(
CarrylessRangeDecoder::new_7a(&[0xFF; 4][..]),
Err(Error {
kind: crate::ErrorKind::Corrupt(_),
..
})
));
for len in 0..4 {
assert!(matches!(
CarrylessRangeDecoder::new(&[0u8; 4][..len]),
Err(Error {
kind: crate::ErrorKind::Truncated,
..
})
));
}
}
#[test]
fn threshold_and_decode_without_normalization() {
let mut d = dec(&[0x40, 0x00, 0x00, 0x00, 0x55]);
assert_eq!(d.get_threshold(256), 64);
d.decode(64, 1);
assert_eq!(
d.state(),
RangeCoderState {
low: 0x3FFF_FFC0,
code: 0x4000_0000,
range: 0x00FF_FFFF
}
);
assert_eq!(d.position(), 4);
}
#[test]
fn normalization_truncates_the_range_and_low_wraps() {
let mut d = dec(&[0, 0, 0, 0, 0xAB, 0xCD]);
d.low = 0x12FF_FF00;
d.range = 0x200;
d.normalize();
assert_eq!(d.low, 0xFFFF_0000);
assert_eq!(d.range, 0x1_0000);
assert_eq!(d.code, 0xAB);
assert_eq!(d.position(), 5);
}
#[test]
fn counts_the_zeros_it_is_fed_past_eof() {
let mut d = dec(&[0u8; 4]);
d.low = 0;
d.range = 1;
d.normalize();
assert_eq!(d.range, TOP);
assert_eq!(d.zero_bytes_past_eof(), 3);
assert_eq!(d.position(), 4);
}
#[test]
fn a_frequency_total_past_the_range_is_corrupt_not_a_division_by_zero() {
let mut d = dec(&[0x40, 0, 0, 0, 0, 0, 0, 0]);
d.range = 100;
assert!(matches!(
d.get_current_count(1000),
Err(Error {
kind: crate::ErrorKind::Corrupt(_),
..
})
));
assert!(d.faulted());
assert!(d.get_current_count(1).is_err());
assert!(d.decode_binary(1, 2).is_err());
let mut d = dec(&[0u8; 8]);
assert_eq!(d.get_threshold(0), u32::MAX);
assert!(d.faulted());
let mut d = dec(&[0u8; 8]);
d.range = (1 << 14) - 1;
let _ = d.decode_bit(1 << 13);
assert!(d.faulted());
}
#[test]
fn a_zero_symbol_size_faults_instead_of_spinning() {
let mut d = dec(&[0u8; 8]);
let _ = d.get_threshold(1 << 10);
d.decode(0, 0);
assert!(d.faulted());
assert_ne!(d.state().range, 0);
}
#[test]
fn decode_bit_matches_threshold_then_decode() {
let input = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22];
for size0 in [1u32, 100, 4096, 8192, 16000, 16383] {
let mut bit = dec(&input);
let mut long = dec(&input);
let got = bit.decode_bit(size0);
let want = u32::from(!long.decode_binary(size0, BIN_TOTAL).unwrap());
assert_eq!(got, want);
assert_eq!(bit.state(), long.state());
assert_eq!(bit.position(), long.position());
}
}
#[test]
fn resuming_from_state_reads_no_init_bytes() {
let input = [0x40, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78];
let mut first = dec(&input[..4]);
let _ = first.get_threshold(256);
first.decode(1, 3);
let state = first.state();
let resumed = CarrylessRangeDecoder::from_state(&input[4..], state);
assert_eq!(resumed.state(), state);
assert_eq!(resumed.position(), 0);
}
#[test]
fn encoder_shifts_out_the_top_byte_and_flushes_low() {
let mut e = CarrylessRangeEncoder::new(alloc_crate::vec::Vec::new());
e.encode(0x12, 1, 256);
assert_eq!((e.low, e.range), (0x11FF_FFEE, 0x00FF_FFFF));
assert!(e.out.is_empty());
e.encode(0, 1, 0x10101);
assert_eq!(e.out, [0x11, 0xFF]);
assert_eq!((e.low, e.range), (0xFFEE_0000, 0x12_0000));
let out = e.finish().unwrap();
assert_eq!(out, [0x11, 0xFF, 0xFF, 0xEE, 0x00, 0x00]);
}
#[test]
fn encoder_faults_are_reported_by_finish() {
let mut e = CarrylessRangeEncoder::new(alloc_crate::vec::Vec::new());
e.range = 100;
e.encode(0, 1, 1000);
assert!(e.faulted());
assert!(matches!(
e.finish(),
Err(Error {
kind: crate::ErrorKind::Internal(_),
..
})
));
let mut e = CarrylessRangeEncoder::new(alloc_crate::vec::Vec::new());
e.encode_bit(0, 0);
assert!(e.faulted());
}
}