1use std::io::Write;
2use std::io;
3
4use deflate_state::DeflateState;
5use encoder_state::EncoderState;
6use lzvalue::LZValue;
7use lz77::{lz77_compress_block, LZ77Status};
8use huffman_lengths::{gen_huffman_lengths, write_huffman_lengths, BlockType};
9use bitstream::LsbWriter;
10use stored_block::{compress_block_stored, write_stored_header, MAX_STORED_BLOCK_LENGTH};
11
12const LARGEST_OUTPUT_BUF_SIZE: usize = 1024 * 32;
13
14#[derive(Eq, PartialEq, Debug, Copy, Clone)]
18pub enum Flush {
19 None,
21 Sync,
25 _Partial,
26 _Block,
27 _Full,
28 Finish,
30}
31
32pub fn flush_to_bitstream(buffer: &[LZValue], state: &mut EncoderState) {
35 for &b in buffer {
36 state.write_lzvalue(b.value());
37 }
38 state.write_end_of_block()
39}
40
41#[cfg(test)]
45pub fn compress_data_fixed(input: &[u8]) -> Vec<u8> {
46 use lz77::lz77_compress;
47
48 let mut state = EncoderState::fixed(Vec::new());
49 let compressed = lz77_compress(input).unwrap();
50
51 state.write_start_of_block(true, true);
53 flush_to_bitstream(&compressed, &mut state);
54
55 state.flush();
56 state.reset(Vec::new())
57}
58
59fn write_stored_block(input: &[u8], mut writer: &mut LsbWriter, final_block: bool) {
60
61 if !input.is_empty() {
63 let mut i = input.chunks(MAX_STORED_BLOCK_LENGTH).peekable();
64
65 while let Some(chunk) = i.next() {
66 let last_chunk = i.peek().is_none();
67 write_stored_header(writer, final_block && last_chunk);
69
70 compress_block_stored(chunk, &mut writer).expect("Write error");
72
73 }
74 } else {
75 write_stored_header(writer, final_block);
77 compress_block_stored(&[], &mut writer).expect("Write error");
78 }
79}
80
81pub fn compress_data_dynamic_n<W: Write>(
83 input: &[u8],
84 deflate_state: &mut DeflateState<W>,
85 flush: Flush,
86) -> io::Result<usize> {
87 let mut bytes_written = 0;
88
89 let mut slice = input;
90
91 loop {
92 let output_buf_len = deflate_state.output_buf().len();
93 let output_buf_pos = deflate_state.output_buf_pos;
94 if output_buf_len > LARGEST_OUTPUT_BUF_SIZE {
97 let written = deflate_state
98 .inner
99 .as_mut()
100 .expect("Missing writer!")
101 .write(&deflate_state.encoder_state.inner_vec()[output_buf_pos..])?;
102
103 if written < output_buf_len.checked_sub(output_buf_pos).unwrap() {
104 deflate_state.output_buf_pos += written;
106 } else {
107 deflate_state.output_buf_pos = 0;
109 deflate_state.output_buf().clear();
110 }
111
112 if bytes_written == 0 {
113 return Err(io::Error::new(
117 io::ErrorKind::Interrupted,
118 "Internal buffer full.",
119 ));
120 } else {
121 return Ok(bytes_written);
122 }
123 }
124
125 if deflate_state.lz77_state.is_last_block() {
126 break;
128 }
129
130 let (written, status, position) = lz77_compress_block(
131 slice,
132 &mut deflate_state.lz77_state,
133 &mut deflate_state.input_buffer,
134 &mut deflate_state.lz77_writer,
135 flush,
136 );
137
138 bytes_written += written;
140 deflate_state.bytes_written += written as u64;
143
144 if status == LZ77Status::NeedInput {
145 return Ok(bytes_written);
149 }
150
151 slice = &slice[written..];
153
154 let last_block = deflate_state.lz77_state.is_last_block();
157
158 let current_block_input_bytes = deflate_state.lz77_state.current_block_input_bytes();
159
160 if cfg!(debug_assertions) {
161 deflate_state
162 .bytes_written_control
163 .add(current_block_input_bytes);
164 }
165
166 let partial_bits = deflate_state.encoder_state.writer.pending_bits();
167
168 let res = {
169 let (l_freqs, d_freqs) = deflate_state.lz77_writer.get_frequencies();
170 let (l_lengths, d_lengths) =
171 deflate_state.encoder_state.huffman_table.get_lengths_mut();
172
173 gen_huffman_lengths(
174 l_freqs,
175 d_freqs,
176 current_block_input_bytes,
177 partial_bits,
178 l_lengths,
179 d_lengths,
180 &mut deflate_state.length_buffers,
181 )
182 };
183
184 match res {
187 BlockType::Dynamic(header) => {
188 deflate_state
190 .encoder_state
191 .write_start_of_block(false, last_block);
192
193 write_huffman_lengths(
195 &header,
196 &deflate_state.encoder_state.huffman_table,
197 &mut deflate_state.length_buffers.length_buf,
198 &mut deflate_state.encoder_state.writer,
199 );
200
201 deflate_state
204 .encoder_state
205 .huffman_table
206 .update_from_lengths();
207
208
209 flush_to_bitstream(
211 deflate_state.lz77_writer.get_buffer(),
212 &mut deflate_state.encoder_state,
213 );
214 }
215 BlockType::Fixed => {
216 deflate_state
218 .encoder_state
219 .write_start_of_block(true, last_block);
220
221 deflate_state.encoder_state.set_huffman_to_fixed();
223
224 flush_to_bitstream(
226 deflate_state.lz77_writer.get_buffer(),
227 &mut deflate_state.encoder_state,
228 );
229 }
230 BlockType::Stored => {
231 let start_pos = position.saturating_sub(current_block_input_bytes as usize);
234
235 assert!(
236 position >= current_block_input_bytes as usize,
237 "Error! Trying to output a stored block with forgotten data!\
238 if you encounter this error, please file an issue!"
239 );
240
241 write_stored_block(
242 &deflate_state.input_buffer.get_buffer()[start_pos..position],
243 &mut deflate_state.encoder_state.writer,
244 flush == Flush::Finish && last_block,
245 );
246 }
247 };
248
249 deflate_state.lz77_writer.clear();
251 deflate_state.lz77_state.reset_input_bytes();
254
255 if status == LZ77Status::Finished {
257 if flush == Flush::Sync {
259 write_stored_block(&[], &mut deflate_state.encoder_state.writer, false);
260 } else if !deflate_state.lz77_state.is_last_block() {
261 let es = &mut deflate_state.encoder_state;
266 es.set_huffman_to_fixed();
267 es.write_start_of_block(true, true);
268 es.write_end_of_block();
269 }
270 break;
271 }
272 }
273
274 deflate_state.encoder_state.flush();
276 let output_buf_pos = deflate_state.output_buf_pos;
279 let written_to_writer = deflate_state
280 .inner
281 .as_mut()
282 .expect("Missing writer!")
283 .write(&deflate_state.encoder_state.inner_vec()[output_buf_pos..])?;
284 if written_to_writer <
285 deflate_state
286 .output_buf()
287 .len()
288 .checked_sub(output_buf_pos)
289 .unwrap()
290 {
291 deflate_state.output_buf_pos += written_to_writer;
292 } else {
293 deflate_state.output_buf_pos = 0;
295 deflate_state.output_buf().clear();
296 }
297 Ok(bytes_written)
298}
299
300#[cfg(test)]
301mod test {
302 use super::*;
303 use test_utils::{get_test_data, decompress_to_end};
304
305 #[test]
306 fn fixed_string_mem() {
308 let test_data = String::from(" GNU GENERAL PUBLIC LICENSE").into_bytes();
309 let compressed = compress_data_fixed(&test_data);
310
311 let result = decompress_to_end(&compressed);
312
313 assert_eq!(test_data, result);
314 }
315
316 #[test]
317 fn fixed_data() {
318 let data = vec![190u8; 400];
319 let compressed = compress_data_fixed(&data);
320 let result = decompress_to_end(&compressed);
321
322 assert_eq!(data, result);
323 }
324
325 #[test]
330 fn fixed_example() {
331 let test_data = b"Deflate late";
332 let check = [
335 0x73,
336 0x49,
337 0x4d,
338 0xcb,
339 0x49,
340 0x2c,
341 0x49,
342 0x55,
343 0x00,
344 0x11,
345 0x00,
346 ];
347 let compressed = compress_data_fixed(test_data);
348 assert_eq!(&compressed, &check);
349 let decompressed = decompress_to_end(&compressed);
350 assert_eq!(&decompressed, test_data)
351 }
352
353 #[test]
354 fn fixed_string_file() {
356 let input = get_test_data();
357
358 let compressed = compress_data_fixed(&input);
359 println!("Fixed codes compressed len: {}", compressed.len());
360 let result = decompress_to_end(&compressed);
361
362 assert_eq!(input.len(), result.len());
363 assert!(input == result);
365 }
366}