#[derive(Debug, Clone, Default)]
pub struct Encoder {
stream: Vec<u8>,
pub low: u64,
pub range: u32,
cache_size: u32,
cache: u8,
start_position: i64,
}
impl Encoder {
pub const TOP_VALUE: u32 = 1 << 24;
pub fn new() -> Self {
Self::default()
}
pub fn set_stream(&mut self, stream: Vec<u8>) {
self.stream = stream;
}
pub fn release_stream(&mut self) -> Vec<u8> {
std::mem::take(&mut self.stream)
}
pub fn stream(&self) -> &[u8] {
&self.stream
}
pub fn stream_mut(&mut self) -> &mut Vec<u8> {
&mut self.stream
}
pub fn init(&mut self) {
self.start_position = self.stream.len() as i64;
self.low = 0;
self.range = 0xFFFF_FFFF;
self.cache_size = 1;
self.cache = 0;
}
pub fn flush_data(&mut self) {
for _ in 0..5 {
self.shift_low();
}
}
pub fn flush_stream(&mut self) {}
pub fn close_stream(&mut self) {
self.stream = Vec::new();
}
pub fn encode(&mut self, start: u32, size: u32, total: u32) {
let range_div = self.range / total;
self.range = range_div;
self.low = self
.low
.wrapping_add(start.wrapping_mul(range_div) as u64);
self.range = self.range.wrapping_mul(size);
while self.range < Self::TOP_VALUE {
self.range <<= 8;
self.shift_low();
}
}
pub fn shift_low(&mut self) {
let low32 = self.low as u32;
if low32 < 0xFF00_0000 || (self.low >> 32) == 1 {
let mut temp = self.cache;
loop {
self.stream
.push((temp as u32 + (self.low >> 32) as u32) as u8);
temp = 0xFF;
self.cache_size -= 1;
if self.cache_size == 0 {
break;
}
}
self.cache = (low32 >> 24) as u8;
}
self.cache_size += 1;
self.low = (low32 << 8) as u64;
}
pub fn encode_direct_bits(&mut self, v: u32, num_total_bits: i32) {
let mut i = num_total_bits - 1;
while i >= 0 {
self.range >>= 1;
if ((v >> i) & 1) == 1 {
self.low = self.low.wrapping_add(self.range as u64);
}
if self.range < Self::TOP_VALUE {
self.range <<= 8;
self.shift_low();
}
i -= 1;
}
}
pub fn encode_bit(&mut self, size0: u32, num_total_bits: i32, symbol: u32) {
let new_bound = (self.range >> num_total_bits) * size0;
if symbol == 0 {
self.range = new_bound;
} else {
self.low = self.low.wrapping_add(new_bound as u64);
self.range -= new_bound;
}
while self.range < Self::TOP_VALUE {
self.range <<= 8;
self.shift_low();
}
}
pub fn get_processed_size_add(&self) -> i64 {
self.cache_size as i64 + (self.stream.len() as i64 - self.start_position) + 4
}
}