Coverage Report

Created: 2025-10-12 08:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fdeflate-0.3.7/src/huffman.rs
Line
Count
Source
1
use crate::decompress::{EXCEPTIONAL_ENTRY, LITERAL_ENTRY, SECONDARY_TABLE_ENTRY};
2
3
/// Return the next code, or if the codeword is already all ones (which is the final code), return
4
/// the same code again.
5
1.10M
fn next_codeword(mut codeword: u16, table_size: u16) -> u16 {
6
1.10M
    if codeword == table_size - 1 {
7
43.7k
        return codeword;
8
1.05M
    }
9
10
1.05M
    let adv = (u16::BITS - 1) - (codeword ^ (table_size - 1)).leading_zeros();
11
1.05M
    let bit = 1 << adv;
12
1.05M
    codeword &= bit - 1;
13
1.05M
    codeword |= bit;
14
1.05M
    codeword
15
1.10M
}
16
17
#[allow(clippy::needless_range_loop)]
18
50.9k
pub fn build_table(
19
50.9k
    lengths: &[u8],
20
50.9k
    entries: &[u32],
21
50.9k
    codes: &mut [u16],
22
50.9k
    primary_table: &mut [u32],
23
50.9k
    secondary_table: &mut Vec<u16>,
24
50.9k
    is_distance_table: bool,
25
50.9k
    double_literal: bool,
26
50.9k
) -> bool {
27
    // Count the number of symbols with each code length.
28
50.9k
    let mut histogram = [0; 16];
29
5.89M
    for &length in lengths {
30
5.84M
        histogram[length as usize] += 1;
31
5.84M
    }
32
33
    // Determine the maximum code length.
34
50.9k
    let mut max_length = 15;
35
592k
    while max_length > 1 && histogram[max_length] == 0 {
36
541k
        max_length -= 1;
37
541k
    }
38
39
    // Handle zero and one symbol huffman codes (which are only allowed for distance codes).
40
50.9k
    if is_distance_table {
41
13.9k
        if max_length == 0 {
42
0
            primary_table.fill(0);
43
0
            secondary_table.clear();
44
0
            return true;
45
13.9k
        } else if max_length == 1 && histogram[1] == 1 {
46
16.9k
            let symbol = lengths.iter().position(|&l| l == 1).unwrap();
47
6.72k
            codes[symbol] = 0;
48
6.72k
            let entry = entries
49
6.72k
                .get(symbol)
50
6.72k
                .cloned()
51
6.72k
                .unwrap_or((symbol as u32) << 16)
52
6.72k
                | 1;
53
1.72M
            for chunk in primary_table.chunks_mut(2) {
54
1.72M
                chunk[0] = entry;
55
1.72M
                chunk[1] = 0;
56
1.72M
            }
57
6.72k
            return true;
58
7.26k
        }
59
36.9k
    }
60
61
    // Sort symbols by code length. Given the histogram, we can determine the starting offset
62
    // for each code length.
63
44.2k
    let mut offsets = [0; 16];
64
44.2k
    let mut codespace_used = 0;
65
44.2k
    offsets[1] = histogram[0];
66
171k
    for i in 1..max_length {
67
171k
        offsets[i + 1] = offsets[i] + histogram[i];
68
171k
        codespace_used = (codespace_used << 1) + histogram[i];
69
171k
    }
70
44.2k
    codespace_used = (codespace_used << 1) + histogram[max_length];
71
72
    // Check that the provided lengths form a valid Huffman tree.
73
44.2k
    if codespace_used != (1 << max_length) {
74
493
        return false;
75
43.7k
    }
76
77
    // Sort the symbols by code length.
78
43.7k
    let mut next_index = offsets;
79
43.7k
    let mut sorted_symbols = [0; 288];
80
5.58M
    for symbol in 0..lengths.len() {
81
5.58M
        let length = lengths[symbol];
82
5.58M
        sorted_symbols[next_index[length as usize]] = symbol;
83
5.58M
        next_index[length as usize] += 1;
84
5.58M
    }
85
86
43.7k
    let mut codeword = 0u16;
87
43.7k
    let mut i = histogram[0];
88
89
    // Populate the primary decoding table
90
43.7k
    let primary_table_bits = primary_table.len().ilog2() as usize;
91
43.7k
    let primary_table_mask = (1 << primary_table_bits) - 1;
92
410k
    for length in 1..=primary_table_bits {
93
410k
        let current_table_end = 1 << length;
94
95
        // Loop over all symbols with the current code length and set their table entries.
96
853k
        for _ in 0..histogram[length] {
97
853k
            let symbol = sorted_symbols[i];
98
853k
            i += 1;
99
853k
100
853k
            primary_table[codeword as usize] = entries
101
853k
                .get(symbol)
102
853k
                .cloned()
103
853k
                .unwrap_or((symbol as u32) << 16)
104
853k
                | length as u32;
105
853k
106
853k
            codes[symbol] = codeword;
107
853k
            codeword = next_codeword(codeword, current_table_end as u16);
108
853k
        }
109
110
410k
        if double_literal {
111
994k
            for len1 in 1..(length - 1) {
112
994k
                let len2 = length - len1;
113
1.64M
                for sym1_index in offsets[len1]..next_index[len1] {
114
2.81M
                    for sym2_index in offsets[len2]..next_index[len2] {
115
2.81M
                        let sym1 = sorted_symbols[sym1_index];
116
2.81M
                        let sym2 = sorted_symbols[sym2_index];
117
2.81M
                        if sym1 < 256 && sym2 < 256 {
118
1.95M
                            let codeword1 = codes[sym1];
119
1.95M
                            let codeword2 = codes[sym2];
120
1.95M
                            let codeword = codeword1 | (codeword2 << len1);
121
1.95M
                            let entry = (sym1 as u32) << 16
122
1.95M
                                | (sym2 as u32) << 24
123
1.95M
                                | LITERAL_ENTRY
124
1.95M
                                | (2 << 8);
125
1.95M
                            primary_table[codeword as usize] = entry | (length as u32);
126
1.95M
                        }
127
                    }
128
                }
129
            }
130
193k
        }
131
132
        // If we aren't at the maximum table size, double the size of the table.
133
410k
        if length < primary_table_bits {
134
366k
            primary_table.copy_within(0..current_table_end, current_table_end);
135
366k
        }
136
    }
137
138
    // Populate the secondary decoding table.
139
43.7k
    secondary_table.clear();
140
43.7k
    if max_length > primary_table_bits {
141
4.91k
        let mut subtable_start = 0;
142
4.91k
        let mut subtable_prefix = !0;
143
10.1k
        for length in (primary_table_bits + 1)..=max_length {
144
10.1k
            let subtable_size = 1 << (length - primary_table_bits);
145
10.1k
            for _ in 0..histogram[length] {
146
                // If the codeword's prefix doesn't match the current subtable, create a new
147
                // subtable.
148
248k
                if codeword & primary_table_mask != subtable_prefix {
149
83.7k
                    subtable_prefix = codeword & primary_table_mask;
150
83.7k
                    subtable_start = secondary_table.len();
151
83.7k
                    primary_table[subtable_prefix as usize] = ((subtable_start as u32) << 16)
152
83.7k
                        | EXCEPTIONAL_ENTRY
153
83.7k
                        | SECONDARY_TABLE_ENTRY
154
83.7k
                        | (subtable_size as u32 - 1);
155
83.7k
                    secondary_table.resize(subtable_start + subtable_size, 0);
156
164k
                }
157
158
                // Lookup the symbol.
159
248k
                let symbol = sorted_symbols[i];
160
248k
                i += 1;
161
162
                // Insert the symbol into the secondary table and advance to the next codeword.
163
248k
                codes[symbol] = codeword;
164
248k
                secondary_table[subtable_start + (codeword >> primary_table_bits) as usize] =
165
248k
                    ((symbol as u16) << 4) | (length as u16);
166
248k
                codeword = next_codeword(codeword, 1 << length);
167
            }
168
169
            // If there are more codes with the same subtable prefix, extend the subtable.
170
10.1k
            if length < max_length && codeword & primary_table_mask == subtable_prefix {
171
3.60k
                secondary_table.extend_from_within(subtable_start..);
172
3.60k
                let subtable_size = secondary_table.len() - subtable_start;
173
3.60k
                primary_table[subtable_prefix as usize] = ((subtable_start as u32) << 16)
174
3.60k
                    | EXCEPTIONAL_ENTRY
175
3.60k
                    | SECONDARY_TABLE_ENTRY
176
3.60k
                    | (subtable_size as u32 - 1);
177
6.50k
            }
178
        }
179
38.7k
    }
180
181
43.7k
    true
182
50.9k
}