1use std::io::Write;
2use std::{io, mem, cmp};
3
4use lz77::LZ77State;
5use output_writer::DynamicWriter;
6use encoder_state::EncoderState;
7use input_buffer::InputBuffer;
8use compression_options::{CompressionOptions, MAX_HASH_CHECKS};
9use compress::Flush;
10use length_encode::{LeafVec, EncodedLength};
11use huffman_table::NUM_LITERALS_AND_LENGTHS;
12pub use huffman_table::MAX_MATCH;
13
14#[derive(Default)]
17pub struct DebugCounter {
18 #[cfg(debug_assertions)]
19 count: u64,
20}
21
22impl DebugCounter {
23 #[cfg(debug_assertions)]
24 pub fn get(&self) -> u64 {
25 self.count
26 }
27
28 #[cfg(not(debug_assertions))]
29 pub fn get(&self) -> u64 {
30 0
31 }
32
33 #[cfg(debug_assertions)]
34 pub fn reset(&mut self) {
35 self.count = 0;
36 }
37
38 #[cfg(not(debug_assertions))]
39 pub fn reset(&self) {}
40
41 #[cfg(debug_assertions)]
42 pub fn add(&mut self, val: u64) {
43 self.count += val;
44 }
45
46 #[cfg(not(debug_assertions))]
47 pub fn add(&self, _: u64) {}
48}
49
50pub struct LengthBuffers {
51 pub leaf_buf: LeafVec,
52 pub length_buf: Vec<EncodedLength>,
53}
54
55impl LengthBuffers {
56 #[inline]
57 fn new() -> LengthBuffers {
58 LengthBuffers {
59 leaf_buf: Vec::with_capacity(NUM_LITERALS_AND_LENGTHS),
60 length_buf: Vec::with_capacity(19),
61 }
62 }
63}
64
65pub struct DeflateState<W: Write> {
67 pub lz77_state: LZ77State,
69 pub input_buffer: InputBuffer,
70 pub compression_options: CompressionOptions,
71 pub encoder_state: EncoderState,
73 pub lz77_writer: DynamicWriter,
75 pub length_buffers: LengthBuffers,
77 pub bytes_written: u64,
79 pub inner: Option<W>,
83 pub output_buf_pos: usize,
87 pub flush_mode: Flush,
88 pub bytes_written_control: DebugCounter,
91}
92
93impl<W: Write> DeflateState<W> {
94 pub fn new(compression_options: CompressionOptions, writer: W) -> DeflateState<W> {
95 DeflateState {
96 input_buffer: InputBuffer::empty(),
97 lz77_state: LZ77State::new(
98 compression_options.max_hash_checks,
99 cmp::min(compression_options.lazy_if_less_than, MAX_HASH_CHECKS),
100 compression_options.matching_type,
101 ),
102 encoder_state: EncoderState::new(Vec::with_capacity(1024 * 32)),
103 lz77_writer: DynamicWriter::new(),
104 length_buffers: LengthBuffers::new(),
105 compression_options: compression_options,
106 bytes_written: 0,
107 inner: Some(writer),
108 output_buf_pos: 0,
109 flush_mode: Flush::None,
110 bytes_written_control: DebugCounter::default(),
111 }
112 }
113
114 #[inline]
115 pub fn output_buf(&mut self) -> &mut Vec<u8> {
116 self.encoder_state.inner_vec()
117 }
118
119 pub fn reset(&mut self, writer: W) -> io::Result<W> {
127 self.encoder_state.flush();
128 self.inner
129 .as_mut()
130 .expect("Missing writer!")
131 .write_all(self.encoder_state.inner_vec())?;
132 self.encoder_state.inner_vec().clear();
133 self.input_buffer = InputBuffer::empty();
134 self.lz77_writer.clear();
135 self.lz77_state.reset();
136 self.bytes_written = 0;
137 self.output_buf_pos = 0;
138 self.flush_mode = Flush::None;
139 if cfg!(debug_assertions) {
140 self.bytes_written_control.reset();
141 }
142 mem::replace(&mut self.inner, Some(writer))
143 .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Missing writer"))
144 }
145}