#![allow(dead_code)]
pub const NUM_BIT_MODEL_TOTAL_BITS: u32 = 11;
pub const BIT_MODEL_TOTAL: u32 = 1 << NUM_BIT_MODEL_TOTAL_BITS;
pub const NUM_MOVE_BITS: u32 = 5;
pub const NUM_TOP_BITS: u32 = 24;
pub const TOP_VALUE: u32 = 1 << NUM_TOP_BITS;
pub const INITIAL_PROB: u16 = (BIT_MODEL_TOTAL / 2) as u16;
#[derive(Debug)]
pub struct LzmaRangeEncoder {
range: u32,
low: u64,
cache: u8,
cache_size: u32,
output: Vec<u8>,
}
impl LzmaRangeEncoder {
pub fn new() -> Self {
Self {
range: 0xFFFFFFFF,
low: 0,
cache: 0,
cache_size: 0, output: Vec::with_capacity(4096),
}
}
pub fn len(&self) -> usize {
self.output.len() + 1 + self.cache_size as usize
}
pub fn is_empty(&self) -> bool {
self.output.is_empty() && self.cache_size == 0
}
pub fn encode_bit(&mut self, prob: &mut u16, bit: bool) {
let p = *prob as u32;
let bound = (self.range >> NUM_BIT_MODEL_TOTAL_BITS) * p;
if bit {
self.low += bound as u64;
self.range -= bound;
*prob -= *prob >> NUM_MOVE_BITS;
} else {
self.range = bound;
*prob += ((BIT_MODEL_TOTAL - p) >> NUM_MOVE_BITS) as u16;
}
self.normalize();
}
pub fn encode_direct_bit(&mut self, bit: bool) {
self.range >>= 1;
if bit {
self.low += self.range as u64;
}
self.normalize();
}
pub fn encode_direct_bits(&mut self, value: u32, num_bits: u32) {
for i in (0..num_bits).rev() {
let bit = (value >> i) & 1;
self.encode_direct_bit(bit != 0);
}
}
pub fn encode_bit_tree(&mut self, probs: &mut [u16], num_bits: u32, symbol: u32) {
let mut m = 1u32;
for i in (0..num_bits).rev() {
let bit = (symbol >> i) & 1;
self.encode_bit(&mut probs[m as usize], bit != 0);
m = (m << 1) | bit;
}
}
pub fn encode_bit_tree_reverse(&mut self, probs: &mut [u16], num_bits: u32, symbol: u32) {
let mut m = 1u32;
for i in 0..num_bits {
let bit = (symbol >> i) & 1;
self.encode_bit(&mut probs[m as usize], bit != 0);
m = (m << 1) | bit;
}
}
fn normalize(&mut self) {
while self.range < TOP_VALUE {
self.shift_low();
self.range <<= 8;
}
}
fn shift_low(&mut self) {
let overflow = (self.low >> 32) as u8;
let low32 = self.low as u32;
if (low32 < 0xFF000000) || (overflow != 0) {
self.output.push(self.cache.wrapping_add(overflow));
let carry_byte = 0xFF_u8.wrapping_add(overflow);
for _ in 0..self.cache_size {
self.output.push(carry_byte);
}
self.cache = (low32 >> 24) as u8;
self.cache_size = 0;
} else {
self.cache_size += 1;
}
self.low = low32.wrapping_shl(8) as u64;
}
pub fn finish(mut self) -> Vec<u8> {
for _ in 0..5 {
self.shift_low();
}
self.output
}
}
impl Default for LzmaRangeEncoder {
fn default() -> Self {
Self::new()
}
}
pub fn init_probs(probs: &mut [u16]) {
for p in probs.iter_mut() {
*p = INITIAL_PROB;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_bit_probability_update() {
let mut rc = LzmaRangeEncoder::new();
let mut prob = INITIAL_PROB;
let initial_prob = prob;
rc.encode_bit(&mut prob, false);
assert!(prob > initial_prob, "prob should increase for bit=0");
let mid_prob = prob;
rc.encode_bit(&mut prob, true);
assert!(prob < mid_prob, "prob should decrease for bit=1");
}
#[test]
fn test_encode_bit_tree() {
let mut rc = LzmaRangeEncoder::new();
let mut probs = [INITIAL_PROB; 8];
rc.encode_bit_tree(&mut probs, 3, 5);
let output = rc.finish();
assert!(!output.is_empty());
}
#[test]
fn test_encode_bit_tree_reverse() {
let mut rc = LzmaRangeEncoder::new();
let mut probs = [INITIAL_PROB; 16];
rc.encode_bit_tree_reverse(&mut probs, 4, 10);
let output = rc.finish();
assert!(!output.is_empty());
}
#[test]
fn test_encode_direct_bits() {
let mut rc = LzmaRangeEncoder::new();
rc.encode_direct_bits(0b1010, 4);
rc.encode_direct_bits(0xFF, 8);
rc.encode_direct_bits(0x1234, 16);
let output = rc.finish();
assert!(!output.is_empty());
}
#[test]
fn test_init_probs() {
let mut probs = [0u16; 100];
init_probs(&mut probs);
for p in probs.iter() {
assert_eq!(*p, INITIAL_PROB);
}
}
#[test]
fn test_encoder_empty() {
let rc = LzmaRangeEncoder::new();
assert!(rc.is_empty());
}
#[test]
fn test_encoder_finish_produces_5_bytes_minimum() {
let rc = LzmaRangeEncoder::new();
let output = rc.finish();
assert!(output.len() >= 5);
}
}