use std::io::Write;
use std::{io, mem, cmp};
use lz77::LZ77State;
use output_writer::DynamicWriter;
use encoder_state::EncoderState;
use input_buffer::InputBuffer;
use compression_options::{CompressionOptions, MAX_HASH_CHECKS};
use compress::Flush;
use length_encode::{LeafVec, EncodedLength};
use huffman_table::NUM_LITERALS_AND_LENGTHS;
pub use huffman_table::MAX_MATCH;
#[derive(Default)]
pub struct DebugCounter {
#[cfg(debug_assertions)]
count: u64,
}
impl DebugCounter {
#[cfg(debug_assertions)]
pub fn get(&self) -> u64 {
self.count
}
#[cfg(not(debug_assertions))]
pub fn get(&self) -> u64 {
0
}
#[cfg(debug_assertions)]
pub fn reset(&mut self) {
self.count = 0;
}
#[cfg(not(debug_assertions))]
pub fn reset(&self) {}
#[cfg(debug_assertions)]
pub fn add(&mut self, val: u64) {
self.count += val;
}
#[cfg(not(debug_assertions))]
pub fn add(&self, _: u64) {}
}
pub struct LengthBuffers {
pub leaf_buf: LeafVec,
pub length_buf: Vec<EncodedLength>,
}
impl LengthBuffers {
#[inline]
fn new() -> LengthBuffers {
LengthBuffers {
leaf_buf: Vec::with_capacity(NUM_LITERALS_AND_LENGTHS),
length_buf: Vec::with_capacity(19),
}
}
}
pub struct DeflateState<W: Write> {
pub lz77_state: LZ77State,
pub input_buffer: InputBuffer,
pub compression_options: CompressionOptions,
pub encoder_state: EncoderState,
pub lz77_writer: DynamicWriter,
pub length_buffers: LengthBuffers,
pub bytes_written: u64,
pub inner: Option<W>,
pub output_buf_pos: usize,
pub flush_mode: Flush,
pub bytes_written_control: DebugCounter,
}
impl<W: Write> DeflateState<W> {
pub fn new(compression_options: CompressionOptions, writer: W) -> DeflateState<W> {
DeflateState {
input_buffer: InputBuffer::empty(),
lz77_state: LZ77State::new(
compression_options.max_hash_checks,
cmp::min(compression_options.lazy_if_less_than, MAX_HASH_CHECKS),
compression_options.matching_type,
),
encoder_state: EncoderState::new(Vec::with_capacity(1024 * 32)),
lz77_writer: DynamicWriter::new(),
length_buffers: LengthBuffers::new(),
compression_options: compression_options,
bytes_written: 0,
inner: Some(writer),
output_buf_pos: 0,
flush_mode: Flush::None,
bytes_written_control: DebugCounter::default(),
}
}
#[inline]
pub fn output_buf(&mut self) -> &mut Vec<u8> {
self.encoder_state.inner_vec()
}
pub fn reset(&mut self, writer: W) -> io::Result<W> {
self.encoder_state.flush();
self.inner
.as_mut()
.expect("Missing writer!")
.write_all(self.encoder_state.inner_vec())?;
self.encoder_state.inner_vec().clear();
self.input_buffer = InputBuffer::empty();
self.lz77_writer.clear();
self.lz77_state.reset();
self.bytes_written = 0;
self.output_buf_pos = 0;
self.flush_mode = Flush::None;
if cfg!(debug_assertions) {
self.bytes_written_control.reset();
}
mem::replace(&mut self.inner, Some(writer))
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Missing writer"))
}
}