1use crate::bit_reverse::reverse_bits;
2use crate::lzvalue::StoredLength;
3use std::fmt;
4
5pub const NUM_LENGTH_CODES: usize = 29;
7
8pub const NUM_DISTANCE_CODES: usize = 30;
11
12pub const NUM_LITERALS_AND_LENGTHS: usize = 286;
15
16pub const MAX_CODE_LENGTH: usize = 15;
18
19pub const MIN_MATCH: u16 = 3;
21pub const MAX_MATCH: u16 = 258;
22
23#[cfg(test)]
24pub const MIN_DISTANCE: u16 = 1;
25pub const MAX_DISTANCE: u16 = 32768;
26
27pub const END_OF_BLOCK_POSITION: usize = 256;
29
30pub static FIXED_CODE_LENGTHS: [u8; NUM_LITERALS_AND_LENGTHS + 2] = [
33 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
34 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
35 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
36 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
37 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
38 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
39 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
40 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
41 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
42];
43
44const LENGTH_EXTRA_BITS_LENGTH: [u8; NUM_LENGTH_CODES] = [
46 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
47];
48
49const LENGTH_CODE: [u8; 256] = [
51 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14,
52 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18,
53 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
54 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22,
55 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
56 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
57 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
58 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26,
59 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
60 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
61 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28,
62];
63
64const BASE_LENGTH: [u8; NUM_LENGTH_CODES] = [
66 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
67 160, 192, 224, 255,
68]; pub const LENGTH_BITS_START: u16 = 257;
72
73pub const FIXED_CODE_LENGTHS_DISTANCE: [u8; NUM_DISTANCE_CODES + 2] = [5; NUM_DISTANCE_CODES + 2];
76
77const DISTANCE_CODES: [u8; 512] = [
78 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
79 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
80 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
81 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13,
82 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
83 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
84 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
85 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
86 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
87 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
88 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
89 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24,
90 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
91 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
92 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
93 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28,
94 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
95 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
96 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
97 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
98 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
99];
100
101#[cfg(test)]
103const DISTANCE_EXTRA_BITS: [u8; NUM_DISTANCE_CODES] = [
104 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
105 13,
106];
107
108const DISTANCE_BASE: [u16; NUM_DISTANCE_CODES] = [
109 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536,
110 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576,
111];
112
113pub const fn num_extra_bits_for_length_code(code: u8) -> u8 {
114 LENGTH_EXTRA_BITS_LENGTH[code as usize]
115}
116
117pub fn num_extra_bits_for_distance_code(code: u8) -> u8 {
121 let mut c = code >> 1;
124 c -= (c != 0) as u8;
125 c
126}
127
128#[derive(Copy, Clone)]
131struct ExtraBits {
132 pub code_number: u16,
134 pub num_bits: u8,
136 pub value: u16,
139}
140
141pub fn get_length_code(length: u16) -> usize {
144 usize::from(LENGTH_CODE[(length.wrapping_sub(MIN_MATCH)) as u8 as usize])
146 + LENGTH_BITS_START as usize
147}
148
149fn get_length_code_and_extra_bits(length: StoredLength) -> ExtraBits {
151 let n = LENGTH_CODE[length.stored_length() as usize];
154
155 let base = BASE_LENGTH[n as usize];
158 let num_bits = num_extra_bits_for_length_code(n);
159 ExtraBits {
160 code_number: n as u16 + LENGTH_BITS_START,
161 num_bits,
162 value: (length.stored_length() - base) as u16,
163 }
164}
165
166pub fn get_distance_code(distance: u16) -> u8 {
171 let distance = distance as usize;
172
173 match distance {
174 1..=256 => DISTANCE_CODES[distance - 1],
176 257..=32768 => DISTANCE_CODES[256 + ((distance - 1) >> 7)],
180 _ => 0,
181 }
182}
183
184fn get_distance_code_and_extra_bits(distance: u16) -> ExtraBits {
185 let distance_code = get_distance_code(distance);
186 let extra = num_extra_bits_for_distance_code(distance_code);
187 let base = DISTANCE_BASE[distance_code as usize] + 1;
189 ExtraBits {
190 code_number: distance_code.into(),
191 num_bits: extra,
192 value: distance - base,
193 }
194}
195
196#[derive(Copy, Clone, Default)]
197pub struct HuffmanCode {
198 pub code: u16,
199 pub length: u8,
200}
201
202impl fmt::Debug for HuffmanCode {
203 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
204 write!(
205 f,
206 "HuffmanCode {{ code: {:b}, length: {}}}",
207 self.code, self.length
208 )
209 }
210}
211
212impl HuffmanCode {
213 #[inline]
214 const fn new(code: u16, length: u8) -> HuffmanCode {
216 HuffmanCode { code, length }
217 }
218}
219
220#[cfg(test)]
221pub struct LengthAndDistanceBits {
222 pub length_code: HuffmanCode,
223 pub length_extra_bits: HuffmanCode,
224 pub distance_code: HuffmanCode,
225 pub distance_extra_bits: HuffmanCode,
226}
227
228fn build_length_count_table(table: &[u8], len_counts: &mut [u16; 16]) -> (usize, usize) {
233 let max_length = (*table.iter().max().expect("BUG! Empty lengths!")).into();
235
236 assert!(max_length <= MAX_CODE_LENGTH);
237
238 let mut max_length_pos = 0;
239
240 for (n, &length) in table.iter().enumerate() {
241 if length > 0 {
244 len_counts[usize::from(length)] += 1;
245 max_length_pos = n;
246 }
247 }
248 (max_length, max_length_pos)
249}
250
251pub fn create_codes_in_place(code_table: &mut [u16], length_table: &[u8]) {
254 let mut len_counts = [0; 16];
255 let (max_length, max_length_pos) = build_length_count_table(length_table, &mut len_counts);
256 let lengths = len_counts;
257
258 let mut code = 0u16;
259 let mut next_code = Vec::with_capacity(length_table.len());
260 next_code.push(code);
261
262 for bits in 1..=max_length {
263 code = (code + lengths[bits - 1]) << 1;
264 next_code.push(code);
265 }
266
267 for n in 0..=max_length_pos {
268 let length = usize::from(length_table[n]);
269 if length != 0 {
270 code_table[n] = reverse_bits(next_code[length], length as u8);
273 next_code[length] = next_code[length].wrapping_add(1);
276 }
277 }
278}
279
280pub struct HuffmanTable {
282 codes: [u16; 288],
284 code_lengths: [u8; 288],
285 distance_codes: [u16; 32],
287 distance_code_lengths: [u8; 32],
288}
289
290impl HuffmanTable {
291 pub const fn empty() -> HuffmanTable {
292 HuffmanTable {
293 codes: [0; 288],
294 code_lengths: [0; 288],
295 distance_codes: [0; 32],
296 distance_code_lengths: [0; 32],
297 }
298 }
299
300 #[cfg(test)]
301 pub fn from_length_tables(
302 literals_and_lengths: &[u8; 288],
303 distances: &[u8; 32],
304 ) -> HuffmanTable {
305 let mut table = HuffmanTable {
306 codes: [0; 288],
307 code_lengths: *literals_and_lengths,
308 distance_codes: [0; 32],
309 distance_code_lengths: *distances,
310 };
311
312 table.update_from_lengths();
313 table
314 }
315
316 #[inline]
318 pub const fn get_lengths(&self) -> (&[u8; 288], &[u8; 32]) {
319 (&self.code_lengths, &self.distance_code_lengths)
320 }
321
322 #[inline]
326 pub fn get_lengths_mut(&mut self) -> (&mut [u8; 288], &mut [u8; 32]) {
327 (&mut self.code_lengths, &mut self.distance_code_lengths)
328 }
329
330 pub fn update_from_lengths(&mut self) {
332 create_codes_in_place(self.codes.as_mut(), &self.code_lengths[..]);
333 create_codes_in_place(
334 self.distance_codes.as_mut(),
335 &self.distance_code_lengths[..],
336 );
337 }
338
339 pub fn set_to_fixed(&mut self) {
340 self.code_lengths = FIXED_CODE_LENGTHS;
341 self.distance_code_lengths = FIXED_CODE_LENGTHS_DISTANCE;
342 self.update_from_lengths();
343 }
344
345 #[cfg(test)]
347 pub fn fixed_table() -> HuffmanTable {
348 HuffmanTable::from_length_tables(&FIXED_CODE_LENGTHS, &FIXED_CODE_LENGTHS_DISTANCE)
351 }
352
353 #[inline]
354 const fn get_ll_huff(&self, value: usize) -> HuffmanCode {
355 HuffmanCode::new(self.codes[value], self.code_lengths[value])
356 }
357
358 #[inline]
360 pub fn get_literal(&self, value: u8) -> HuffmanCode {
361 let index = usize::from(value);
362 HuffmanCode::new(self.codes[index], self.code_lengths[index])
363 }
364
365 #[inline]
367 pub const fn get_end_of_block(&self) -> HuffmanCode {
368 self.get_ll_huff(END_OF_BLOCK_POSITION)
369 }
370
371 #[inline]
373 pub fn get_length_huffman(&self, length: StoredLength) -> (HuffmanCode, HuffmanCode) {
374 let length_data = get_length_code_and_extra_bits(length);
375
376 let length_huffman_code = self.get_ll_huff(length_data.code_number as usize);
377
378 (
379 length_huffman_code,
380 HuffmanCode {
381 code: length_data.value,
382 length: length_data.num_bits,
383 },
384 )
385 }
386
387 #[inline]
391 pub fn get_distance_huffman(&self, distance: u16) -> (HuffmanCode, HuffmanCode) {
392 let distance_data = get_distance_code_and_extra_bits(distance);
395
396 let distance_huffman_code = self.distance_codes[distance_data.code_number as usize];
397 let distance_huffman_length =
398 self.distance_code_lengths[distance_data.code_number as usize];
399
400 (
401 HuffmanCode {
402 code: distance_huffman_code,
403 length: distance_huffman_length,
404 },
405 HuffmanCode {
406 code: distance_data.value,
407 length: distance_data.num_bits,
408 },
409 )
410 }
411
412 #[cfg(test)]
413 pub fn get_length_distance_code(&self, length: u16, distance: u16) -> LengthAndDistanceBits {
414 assert!(length >= MIN_MATCH && length < MAX_DISTANCE);
415 let l_codes = self.get_length_huffman(StoredLength::from_actual_length(length));
416 let d_codes = self.get_distance_huffman(distance);
417 LengthAndDistanceBits {
418 length_code: l_codes.0,
419 length_extra_bits: l_codes.1,
420 distance_code: d_codes.0,
421 distance_extra_bits: d_codes.1,
422 }
423 }
424}
425
426#[cfg(test)]
427mod test {
428 use super::*;
429 use super::{
430 build_length_count_table, get_distance_code_and_extra_bits, get_length_code_and_extra_bits,
431 };
432
433 use crate::lzvalue::StoredLength;
434
435 fn l(length: u16) -> StoredLength {
436 StoredLength::from_actual_length(length)
437 }
438
439 #[test]
440 fn test_get_length_code() {
441 let extra_bits = get_length_code_and_extra_bits(l(4));
442 assert_eq!(extra_bits.code_number, 258);
443 assert_eq!(extra_bits.num_bits, 0);
444 assert_eq!(extra_bits.value, 0);
445
446 let extra_bits = get_length_code_and_extra_bits(l(165));
447 assert_eq!(extra_bits.code_number, 282);
448 assert_eq!(extra_bits.num_bits, 5);
449 assert_eq!(extra_bits.value, 2);
450
451 let extra_bits = get_length_code_and_extra_bits(l(257));
452 assert_eq!(extra_bits.code_number, 284);
453 assert_eq!(extra_bits.num_bits, 5);
454 assert_eq!(extra_bits.value, 30);
455
456 let extra_bits = get_length_code_and_extra_bits(l(258));
457 assert_eq!(extra_bits.code_number, 285);
458 assert_eq!(extra_bits.num_bits, 0);
459 }
460
461 #[test]
462 fn test_distance_code() {
463 assert_eq!(get_distance_code(1), 0);
464 assert_eq!(get_distance_code(0), 0);
466 assert_eq!(get_distance_code(50000), 0);
467 assert_eq!(get_distance_code(6146), 25);
468 assert_eq!(get_distance_code(256), 15);
469 assert_eq!(get_distance_code(4733), 24);
470 assert_eq!(get_distance_code(257), 16);
471 }
472
473 #[test]
474 fn test_distance_extra_bits() {
475 let extra = get_distance_code_and_extra_bits(527);
476 assert_eq!(extra.value, 0b1110);
477 assert_eq!(extra.code_number, 18);
478 assert_eq!(extra.num_bits, 8);
479 let extra = get_distance_code_and_extra_bits(256);
480 assert_eq!(extra.code_number, 15);
481 assert_eq!(extra.num_bits, 6);
482 let extra = get_distance_code_and_extra_bits(4733);
483 assert_eq!(extra.code_number, 24);
484 assert_eq!(extra.num_bits, 11);
485 }
486
487 #[test]
488 fn test_length_table_fixed() {
489 let _ = build_length_count_table(&FIXED_CODE_LENGTHS, &mut [0; 16]);
490 }
491
492 #[test]
493 #[should_panic]
494 fn test_length_table_max_length() {
495 let table = [16u8; 288];
496 build_length_count_table(&table, &mut [0; 16]);
497 }
498
499 #[test]
500 #[should_panic]
501 fn test_empty_table() {
502 let table = [];
503 build_length_count_table(&table, &mut [0; 16]);
504 }
505
506 #[test]
507 fn make_table_fixed() {
508 let table = HuffmanTable::fixed_table();
509 assert_eq!(table.codes[0], 0b00001100);
510 assert_eq!(table.codes[143], 0b11111101);
511 assert_eq!(table.codes[144], 0b000010011);
512 assert_eq!(table.codes[255], 0b111111111);
513 assert_eq!(table.codes[256], 0b0000000);
514 assert_eq!(table.codes[279], 0b1110100);
515 assert_eq!(table.codes[280], 0b00000011);
516 assert_eq!(table.codes[287], 0b11100011);
517
518 assert_eq!(table.distance_codes[0], 0);
519 assert_eq!(table.distance_codes[5], 20);
520
521 let ld = table.get_length_distance_code(4, 5);
522
523 assert_eq!(ld.length_code.code, 0b00100000);
524 assert_eq!(ld.distance_code.code, 0b00100);
525 assert_eq!(ld.distance_extra_bits.length, 1);
526 assert_eq!(ld.distance_extra_bits.code, 0);
527 }
528
529 #[test]
530 fn extra_bits_distance() {
531 use std::mem::size_of;
532 for i in 0..NUM_DISTANCE_CODES {
533 assert_eq!(
534 num_extra_bits_for_distance_code(i as u8),
535 DISTANCE_EXTRA_BITS[i]
536 );
537 }
538 println!("Size of huffmanCode struct: {}", size_of::<HuffmanCode>());
539 }
540}