1use length_encode::{EncodedLength, encode_lengths_m, huffman_lengths_from_frequency_m,
2 COPY_PREVIOUS, REPEAT_ZERO_3_BITS, REPEAT_ZERO_7_BITS};
3use huffman_table::{HuffmanTable, create_codes_in_place, num_extra_bits_for_length_code,
4 num_extra_bits_for_distance_code, NUM_LITERALS_AND_LENGTHS,
5 NUM_DISTANCE_CODES, MAX_CODE_LENGTH, FIXED_CODE_LENGTHS, LENGTH_BITS_START};
6use bitstream::LsbWriter;
7use output_writer::FrequencyType;
8use stored_block::MAX_STORED_BLOCK_LENGTH;
9use deflate_state::LengthBuffers;
10
11use std::cmp;
12
13pub const MIN_NUM_LITERALS_AND_LENGTHS: usize = 257;
15pub const MIN_NUM_DISTANCES: usize = 1;
17
18const NUM_HUFFMAN_LENGTHS: usize = 19;
19
20const HUFFMAN_LENGTH_ORDER: [u8; NUM_HUFFMAN_LENGTHS] = [
24 16,
25 17,
26 18,
27 0,
28 8,
29 7,
30 9,
31 6,
32 10,
33 5,
34 11,
35 4,
36 12,
37 3,
38 13,
39 2,
40 14,
41 1,
42 15,
43];
44
45const HLIT_BITS: u8 = 5;
47const HDIST_BITS: u8 = 5;
48const HCLEN_BITS: u8 = 4;
49
50const MAX_HUFFMAN_CODE_LENGTH: usize = 7;
52
53const STORED_BLOCK_HEADER_LENGTH: u64 = 4;
55const BLOCK_MARKER_LENGTH: u8 = 3;
56
57pub fn remove_trailing_zeroes<T: From<u8> + PartialEq>(input: &[T], min_length: usize) -> &[T] {
59 let num_zeroes = input.iter().rev().take_while(|&a| *a == T::from(0)).count();
60 &input[0..cmp::max(input.len() - num_zeroes, min_length)]
61}
62
63fn extra_bits_for_huffman_length_code(code: u8) -> u8 {
65 match code {
66 16...17 => 3,
67 18 => 7,
68 _ => 0,
69 }
70}
71
72fn calculate_huffman_length(frequencies: &[FrequencyType], code_lengths: &[u8]) -> u64 {
74 frequencies.iter().zip(code_lengths).enumerate().fold(
75 0,
76 |acc, (n, (&f, &l))| {
77 acc +
78 (u64::from(f) *
79 (u64::from(l) + u64::from(extra_bits_for_huffman_length_code(n as u8))))
80 },
81 )
82}
83
84fn calculate_block_length<F>(
91 frequencies: &[FrequencyType],
92 dyn_code_lengths: &[u8],
93 get_num_extra_bits: &F,
94) -> (u64, u64)
95where
96 F: Fn(usize) -> u64,
97{
98 let mut d_ll_length = 0u64;
100 let mut s_ll_length = 0u64;
102
103 let iter = frequencies
104 .iter()
105 .zip(dyn_code_lengths.iter().zip(FIXED_CODE_LENGTHS.iter()))
106 .enumerate();
107
108 for (c, (&f, (&l, &fl))) in iter {
111 let f = u64::from(f);
113 let extra_bits_for_code = get_num_extra_bits(c);
115
116 d_ll_length += f * (u64::from(l) + extra_bits_for_code);
117 s_ll_length += f * (u64::from(fl) + extra_bits_for_code);
118
119 }
120
121 (d_ll_length, s_ll_length)
122}
123
124fn stored_padding(pending_bits: u8) -> u64 {
129 assert!(pending_bits <= 8);
130 let free_space = 8 - pending_bits;
131 if free_space >= BLOCK_MARKER_LENGTH {
132 free_space - BLOCK_MARKER_LENGTH
134 } else {
135 8 - (BLOCK_MARKER_LENGTH - free_space)
137 }.into()
138}
139
140fn stored_length(input_bytes: u64) -> u64 {
147 let num_blocks = (input_bytes
150 .checked_sub(1)
151 .expect("Underflow calculating stored block length!") /
152 MAX_STORED_BLOCK_LENGTH as u64) + 1;
153 (input_bytes + (STORED_BLOCK_HEADER_LENGTH as u64 * num_blocks) + (num_blocks - 1)) * 8
156}
157
158pub enum BlockType {
159 Stored,
160 Fixed,
161 Dynamic(DynamicBlockHeader),
162}
163
164pub struct DynamicBlockHeader {
169 pub huffman_table_lengths: Vec<u8>,
171 pub used_hclens: usize,
174}
175
176pub fn gen_huffman_lengths(
181 l_freqs: &[FrequencyType],
182 d_freqs: &[FrequencyType],
183 num_input_bytes: u64,
184 pending_bits: u8,
185 l_lengths: &mut [u8; 288],
186 d_lengths: &mut [u8; 32],
187 length_buffers: &mut LengthBuffers,
188) -> BlockType {
189 if num_input_bytes <= 4 {
193 return BlockType::Fixed;
194 };
195
196 let l_freqs = remove_trailing_zeroes(l_freqs, MIN_NUM_LITERALS_AND_LENGTHS);
197 let d_freqs = remove_trailing_zeroes(d_freqs, MIN_NUM_DISTANCES);
198
199 huffman_lengths_from_frequency_m(
208 l_freqs,
209 MAX_CODE_LENGTH,
210 &mut length_buffers.leaf_buf,
211 l_lengths,
212 );
213 huffman_lengths_from_frequency_m(
214 d_freqs,
215 MAX_CODE_LENGTH,
216 &mut length_buffers.leaf_buf,
217 d_lengths,
218 );
219
220
221 let used_lengths = l_freqs.len();
222 let used_distances = d_freqs.len();
223
224 let mut freqs = [0u16; 19];
226 encode_lengths_m(
227 l_lengths[..used_lengths]
228 .iter()
229 .chain(&d_lengths[..used_distances]),
230 &mut length_buffers.length_buf,
231 &mut freqs,
232 );
233
234 let mut huffman_table_lengths = vec![0; freqs.len()];
236 huffman_lengths_from_frequency_m(
237 &freqs,
238 MAX_HUFFMAN_CODE_LENGTH,
239 &mut length_buffers.leaf_buf,
240 huffman_table_lengths.as_mut_slice(),
241 );
242
243 let used_hclens = HUFFMAN_LENGTH_ORDER.len() -
245 HUFFMAN_LENGTH_ORDER
246 .iter()
247 .rev()
248 .take_while(|&&n| huffman_table_lengths[n as usize] == 0)
249 .count();
250
251 debug_assert!(used_hclens >= 4);
253
254 let (d_ll_length, s_ll_length) = calculate_block_length(l_freqs, l_lengths, &|c| {
259 num_extra_bits_for_length_code(c.saturating_sub(LENGTH_BITS_START as usize) as u8).into()
260 });
261
262 let (d_dist_length, s_dist_length) = calculate_block_length(d_freqs, d_lengths, &|c| {
264 num_extra_bits_for_distance_code(c as u8).into()
265 });
266
267 let huff_table_length = calculate_huffman_length(&freqs, &huffman_table_lengths);
269
270 let dynamic_length = d_ll_length + d_dist_length + huff_table_length +
272 (used_hclens as u64 * 3) + u64::from(HLIT_BITS) +
273 u64::from(HDIST_BITS) + u64::from(HCLEN_BITS);
274
275 let static_length = s_ll_length + s_dist_length;
277
278 let stored_length = stored_length(num_input_bytes) + stored_padding(pending_bits % 8);
280
281 let used_length = cmp::min(cmp::min(dynamic_length, static_length), stored_length);
282
283 if used_length == static_length {
288 BlockType::Fixed
289 } else if used_length == stored_length {
290 BlockType::Stored
291 } else {
292 BlockType::Dynamic(DynamicBlockHeader {
293 huffman_table_lengths: huffman_table_lengths,
294 used_hclens: used_hclens,
295 })
296 }
297}
298
299pub fn write_huffman_lengths(
301 header: &DynamicBlockHeader,
302 huffman_table: &HuffmanTable,
303 encoded_lengths: &[EncodedLength],
304 writer: &mut LsbWriter,
305) {
306 let (literal_len_lengths, distance_lengths) = huffman_table.get_lengths();
308 let literal_len_lengths =
309 remove_trailing_zeroes(literal_len_lengths, MIN_NUM_LITERALS_AND_LENGTHS);
310 let distance_lengths = remove_trailing_zeroes(distance_lengths, MIN_NUM_DISTANCES);
311 let huffman_table_lengths = &header.huffman_table_lengths;
312 let used_hclens = header.used_hclens;
313
314 assert!(literal_len_lengths.len() <= NUM_LITERALS_AND_LENGTHS);
315 assert!(literal_len_lengths.len() >= MIN_NUM_LITERALS_AND_LENGTHS);
316 assert!(distance_lengths.len() <= NUM_DISTANCE_CODES);
317 assert!(distance_lengths.len() >= MIN_NUM_DISTANCES);
318
319 let hlit = (literal_len_lengths.len() - MIN_NUM_LITERALS_AND_LENGTHS) as u16;
321 writer.write_bits(hlit, HLIT_BITS);
322 let hdist = (distance_lengths.len() - MIN_NUM_DISTANCES) as u16;
324 writer.write_bits(hdist, HDIST_BITS);
325
326 let hclen = used_hclens.saturating_sub(4);
328
329 writer.write_bits(hclen as u16, HCLEN_BITS);
333
334 for n in &HUFFMAN_LENGTH_ORDER[..used_hclens] {
337 writer.write_bits(huffman_table_lengths[usize::from(*n)] as u16, 3);
338 }
339
340 let mut codes = [0u16; NUM_HUFFMAN_LENGTHS];
342 create_codes_in_place(&mut codes[..], huffman_table_lengths);
343
344 for v in encoded_lengths {
346 match *v {
347 EncodedLength::Length(n) => {
348 let (c, l) = (codes[usize::from(n)], huffman_table_lengths[usize::from(n)]);
349 writer.write_bits(c, l);
350 }
351 EncodedLength::CopyPrevious(n) => {
352 let (c, l) = (codes[COPY_PREVIOUS], huffman_table_lengths[COPY_PREVIOUS]);
353 writer.write_bits(c, l);
354 debug_assert!(n >= 3);
355 debug_assert!(n <= 6);
356 writer.write_bits((n - 3).into(), 2);
357 }
358 EncodedLength::RepeatZero3Bits(n) => {
359 let (c, l) = (
360 codes[REPEAT_ZERO_3_BITS],
361 huffman_table_lengths[REPEAT_ZERO_3_BITS],
362 );
363 writer.write_bits(c, l);
364 debug_assert!(n >= 3);
365 writer.write_bits((n - 3).into(), 3);
366 }
367 EncodedLength::RepeatZero7Bits(n) => {
368 let (c, l) = (
369 codes[REPEAT_ZERO_7_BITS],
370 huffman_table_lengths[REPEAT_ZERO_7_BITS],
371 );
372 writer.write_bits(c, l);
373 debug_assert!(n >= 11);
374 debug_assert!(n <= 138);
375 writer.write_bits((n - 11).into(), 7);
376 }
377 }
378 }
379}
380
381
382#[cfg(test)]
383mod test {
384 use super::stored_padding;
385 #[test]
386 fn padding() {
387 assert_eq!(stored_padding(0), 5);
388 assert_eq!(stored_padding(1), 4);
389 assert_eq!(stored_padding(2), 3);
390 assert_eq!(stored_padding(3), 2);
391 assert_eq!(stored_padding(4), 1);
392 assert_eq!(stored_padding(5), 0);
393 assert_eq!(stored_padding(6), 7);
394 assert_eq!(stored_padding(7), 6);
395 }
396}