1 use crate::bit_reverse::reverse_bits;
2 use crate::lzvalue::StoredLength;
3 use std::fmt;
4 
5 /// The number of length codes in the Huffman table
6 pub const NUM_LENGTH_CODES: usize = 29;
7 
8 /// The number of distance codes in the distance Huffman table
9 // NOTE: two mode codes are actually used when constructing codes
10 pub const NUM_DISTANCE_CODES: usize = 30;
11 
12 /// Combined number of literal and length codes
13 // NOTE: two mode codes are actually used when constructing codes
14 pub const NUM_LITERALS_AND_LENGTHS: usize = 286;
15 
16 /// The maximum length of a Huffman code
17 pub const MAX_CODE_LENGTH: usize = 15;
18 
19 /// The minimum and maximum lengths for a match according to the DEFLATE specification
20 pub const MIN_MATCH: u16 = 3;
21 pub const MAX_MATCH: u16 = 258;
22 
23 #[cfg(test)]
24 pub const MIN_DISTANCE: u16 = 1;
25 pub const MAX_DISTANCE: u16 = 32768;
26 
27 /// The position in the literal/length table of the end of block symbol
28 pub const END_OF_BLOCK_POSITION: usize = 256;
29 
30 /// Bit lengths for literal and length codes in the fixed Huffman table
31 /// The Huffman codes are generated from this and the distance bit length table
32 pub 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 
44 /// The number of extra bits for the length codes
45 const 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 
49 /// Table used to get a code from a length value (see get_distance_code_and_extra_bits)
50 const 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 
64 /// Base values to calculate the value of the bits in length codes
65 const 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 ]; // 258 - MIN_MATCh
69 
70 /// What number in the literal/length table the lengths start at
71 pub const LENGTH_BITS_START: u16 = 257;
72 
73 /// Lengths for the distance codes in the pre-defined/fixed Huffman table
74 /// (All distance codes are 5 bits long)
75 pub const FIXED_CODE_LENGTHS_DISTANCE: [u8; NUM_DISTANCE_CODES + 2] = [5; NUM_DISTANCE_CODES + 2];
76 
77 const 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 /// Number of extra bits following the distance codes
102 #[cfg(test)]
103 const 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 
108 const 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 
num_extra_bits_for_length_code(code: u8) -> u8113 pub const fn num_extra_bits_for_length_code(code: u8) -> u8 {
114     LENGTH_EXTRA_BITS_LENGTH[code as usize]
115 }
116 
117 /// Get the number of extra bits used for a distance code.
118 /// (Code numbers above `NUM_DISTANCE_CODES` will give some garbage
119 /// value.)
num_extra_bits_for_distance_code(code: u8) -> u8120 pub fn num_extra_bits_for_distance_code(code: u8) -> u8 {
121     // This can be easily calculated without a lookup.
122     //
123     let mut c = code >> 1;
124     c -= (c != 0) as u8;
125     c
126 }
127 
128 /// A struct representing the data needed to generate the bit codes for
129 /// a given value and Huffman table.
130 #[derive(Copy, Clone)]
131 struct ExtraBits {
132     /// The position of the length in the Huffman table.
133     pub code_number: u16,
134     /// Number of extra bits following the code.
135     pub num_bits: u8,
136     /// The value of the extra bits, which together with the length/distance code
137     /// allow us to calculate the exact length/distance.
138     pub value: u16,
139 }
140 
141 /// Get the length code that corresponds to the length value
142 /// Panics if length is out of range.
get_length_code(length: u16) -> usize143 pub fn get_length_code(length: u16) -> usize {
144     // Going via an u8 here helps the compiler evade bounds checking.
145     usize::from(LENGTH_CODE[(length.wrapping_sub(MIN_MATCH)) as u8 as usize])
146         + LENGTH_BITS_START as usize
147 }
148 
149 /// Get the code for the Huffman table and the extra bits for the requested length.
get_length_code_and_extra_bits(length: StoredLength) -> ExtraBits150 fn get_length_code_and_extra_bits(length: StoredLength) -> ExtraBits {
151     // Length values are stored as unsigned bytes, where the actual length is the value - 3
152     // The `StoredLength` struct takes care of this conversion for us.
153     let n = LENGTH_CODE[length.stored_length() as usize];
154 
155     // We can then get the base length from the base length table,
156     // which we use to calculate the value of the extra bits.
157     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 
166 /// Get the spot in the Huffman table for distances `distance` corresponds to
167 /// Returns 255 if the distance is invalid.
168 /// Avoiding option here for simplicity and performance) as this being called with an invalid
169 /// value would be a bug.
get_distance_code(distance: u16) -> u8170 pub fn get_distance_code(distance: u16) -> u8 {
171     let distance = distance as usize;
172 
173     match distance {
174         // Since the array starts at 0, we need to subtract 1 to get the correct code number.
175         1..=256 => DISTANCE_CODES[distance - 1],
176         // Due to the distrubution of the distance codes above 256, we can get away with only
177         // using the top bits to determine the code, rather than having a 32k long table of
178         // distance codes.
179         257..=32768 => DISTANCE_CODES[256 + ((distance - 1) >> 7)],
180         _ => 0,
181     }
182 }
183 
get_distance_code_and_extra_bits(distance: u16) -> ExtraBits184 fn 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     // FIXME: We should add 1 to the values in distance_base to avoid having to add one here
188     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)]
197 pub struct HuffmanCode {
198     pub code: u16,
199     pub length: u8,
200 }
201 
202 impl fmt::Debug for HuffmanCode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result203     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 
212 impl HuffmanCode {
213     #[inline]
214     /// Create a Huffman code value from a code and length.
new(code: u16, length: u8) -> HuffmanCode215     const fn new(code: u16, length: u8) -> HuffmanCode {
216         HuffmanCode { code, length }
217     }
218 }
219 
220 #[cfg(test)]
221 pub 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 
228 /// Counts the number of values of each length.
229 /// Returns a tuple containing the longest length value in the table, it's position,
230 /// and fills in lengths in the `len_counts` slice.
231 /// Returns an error if `table` is empty, or if any of the lengths exceed 15.
build_length_count_table(table: &[u8], len_counts: &mut [u16; 16]) -> (usize, usize)232 fn build_length_count_table(table: &[u8], len_counts: &mut [u16; 16]) -> (usize, usize) {
233     // TODO: Validate the length table properly in debug mode.
234     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         // TODO: Make sure we don't have more of one length than we can make
242         // codes for
243         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 
251 /// Generates a vector of Huffman codes given a table of bit lengths
252 /// Returns an error if any of the lengths are > 15
create_codes_in_place(code_table: &mut [u16], length_table: &[u8])253 pub 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             // The algorithm generates the code in the reverse bit order, so we need to reverse them
271             // to get the correct codes.
272             code_table[n] = reverse_bits(next_code[length], length as u8);
273             // We use wrapping here as we would otherwise overflow on the last code
274             // This should be okay as we exit the loop after this so the value is ignored
275             next_code[length] = next_code[length].wrapping_add(1);
276         }
277     }
278 }
279 
280 /// A structure containing the tables of Huffman codes for lengths, literals and distances
281 pub struct HuffmanTable {
282     // Literal, end of block and length codes
283     codes: [u16; 288],
284     code_lengths: [u8; 288],
285     // Distance codes
286     distance_codes: [u16; 32],
287     distance_code_lengths: [u8; 32],
288 }
289 
290 impl HuffmanTable {
empty() -> HuffmanTable291     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)]
from_length_tables( literals_and_lengths: &[u8; 288], distances: &[u8; 32], ) -> HuffmanTable301     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     /// Get references to the lengths of the current Huffman codes.
317     #[inline]
get_lengths(&self) -> (&[u8; 288], &[u8; 32])318     pub const fn get_lengths(&self) -> (&[u8; 288], &[u8; 32]) {
319         (&self.code_lengths, &self.distance_code_lengths)
320     }
321 
322     /// Get mutable references to the lengths of the current Huffman codes.
323     ///
324     /// Used for updating the lengths in place.
325     #[inline]
get_lengths_mut(&mut self) -> (&mut [u8; 288], &mut [u8; 32])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     /// Update the Huffman codes using the existing length values in the Huffman table.
update_from_lengths(&mut self)331     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 
set_to_fixed(&mut self)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     /// Create a `HuffmanTable` using the fixed tables specified in the DEFLATE format specification.
346     #[cfg(test)]
fixed_table() -> HuffmanTable347     pub fn fixed_table() -> HuffmanTable {
348         // This should be safe to unwrap, if it were to panic the code is wrong,
349         // tests should catch it.
350         HuffmanTable::from_length_tables(&FIXED_CODE_LENGTHS, &FIXED_CODE_LENGTHS_DISTANCE)
351     }
352 
353     #[inline]
get_ll_huff(&self, value: usize) -> HuffmanCode354     const fn get_ll_huff(&self, value: usize) -> HuffmanCode {
355         HuffmanCode::new(self.codes[value], self.code_lengths[value])
356     }
357 
358     /// Get the Huffman code from the corresponding literal value
359     #[inline]
get_literal(&self, value: u8) -> HuffmanCode360     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     /// Get the Huffman code for the end of block value
366     #[inline]
get_end_of_block(&self) -> HuffmanCode367     pub const fn get_end_of_block(&self) -> HuffmanCode {
368         self.get_ll_huff(END_OF_BLOCK_POSITION)
369     }
370 
371     /// Get the Huffman code and extra bits for the specified length
372     #[inline]
get_length_huffman(&self, length: StoredLength) -> (HuffmanCode, HuffmanCode)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     /// Get the Huffman code and extra bits for the specified distance
388     ///
389     /// Returns None if distance is 0 or above 32768
390     #[inline]
get_distance_huffman(&self, distance: u16) -> (HuffmanCode, HuffmanCode)391     pub fn get_distance_huffman(&self, distance: u16) -> (HuffmanCode, HuffmanCode) {
392         //debug_assert!(distance >= MIN_DISTANCE && distance <= MAX_DISTANCE);
393 
394         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)]
get_length_distance_code(&self, length: u16, distance: u16) -> LengthAndDistanceBits413     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)]
427 mod 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 
l(length: u16) -> StoredLength435     fn l(length: u16) -> StoredLength {
436         StoredLength::from_actual_length(length)
437     }
438 
439     #[test]
test_get_length_code()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]
test_distance_code()462     fn test_distance_code() {
463         assert_eq!(get_distance_code(1), 0);
464         // Using 0 for None at the moment
465         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]
test_distance_extra_bits()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]
test_length_table_fixed()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]
test_length_table_max_length()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]
test_empty_table()501     fn test_empty_table() {
502         let table = [];
503         build_length_count_table(&table, &mut [0; 16]);
504     }
505 
506     #[test]
make_table_fixed()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]
extra_bits_distance()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 }
541