@@ -9,6 +9,7 @@ use super::lossless::BitReader;
9
9
///
10
10
11
11
const MAX_ALLOWED_CODE_LENGTH : usize = 15 ;
12
+ const MAX_TABLE_BITS : u8 = 10 ;
12
13
13
14
#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
14
15
enum HuffmanTreeNode {
@@ -97,7 +98,7 @@ impl HuffmanTree {
97
98
}
98
99
99
100
// Populate decoding table
100
- let table_bits = max_code_length. min ( 10 ) ;
101
+ let table_bits = max_code_length. min ( MAX_TABLE_BITS as u16 ) ;
101
102
let table_size = ( 1 << table_bits) as usize ;
102
103
let table_mask = table_size as u16 - 1 ;
103
104
let mut table = vec ! [ 0 ; table_size] ;
@@ -115,38 +116,48 @@ impl HuffmanTree {
115
116
// If the longest code is larger than the table size, build a tree as a fallback.
116
117
let mut tree = Vec :: new ( ) ;
117
118
if max_code_length > table_bits {
118
- tree = vec ! [ HuffmanTreeNode :: Empty ; 2 * num_symbols - 1 ] ;
119
+ for ( symbol, ( & code, & length) ) in huff_codes. iter ( ) . zip ( code_lengths. iter ( ) ) . enumerate ( )
120
+ {
121
+ if length > table_bits {
122
+ let table_index =
123
+ ( ( u16:: reverse_bits ( code) >> ( 16 - length) ) & table_mask) as usize ;
124
+ let table_value = table[ table_index] ;
125
+
126
+ debug_assert_eq ! ( table_value >> 16 , 0 ) ;
127
+
128
+ let mut node_index = if table_value == 0 {
129
+ let node_index = tree. len ( ) ;
130
+ table[ table_index] = ( node_index + 1 ) as u32 ;
131
+ tree. push ( HuffmanTreeNode :: Empty ) ;
132
+ node_index
133
+ } else {
134
+ ( table_value - 1 ) as usize
135
+ } ;
119
136
120
- let mut num_nodes = 1 ;
121
- for ( symbol, & length) in code_lengths. iter ( ) . enumerate ( ) {
122
- let code = huff_codes[ symbol] ;
123
- let code_length = length;
124
- let symbol = symbol. try_into ( ) . unwrap ( ) ;
125
-
126
- if length > 0 {
127
- let mut node_index = 0 ;
128
137
let code = usize:: from ( code) ;
129
-
130
- for length in ( 0 ..code_length) . rev ( ) {
138
+ for depth in ( 0 ..length - table_bits) . rev ( ) {
131
139
let node = tree[ node_index] ;
132
140
133
141
let offset = match node {
134
142
HuffmanTreeNode :: Empty => {
135
143
// Turns a node from empty into a branch and assigns its children
136
- let offset_index = num_nodes - node_index;
137
- tree[ node_index] = HuffmanTreeNode :: Branch ( offset_index) ;
138
- num_nodes += 2 ;
139
- offset_index
144
+ let offset = tree. len ( ) - node_index;
145
+ tree[ node_index] = HuffmanTreeNode :: Branch ( offset) ;
146
+ tree. push ( HuffmanTreeNode :: Empty ) ;
147
+ tree. push ( HuffmanTreeNode :: Empty ) ;
148
+ offset
140
149
}
141
150
HuffmanTreeNode :: Leaf ( _) => return Err ( DecodingError :: HuffmanError ) ,
142
151
HuffmanTreeNode :: Branch ( offset) => offset,
143
152
} ;
144
153
145
- node_index += offset + ( ( code >> length ) & 1 ) ;
154
+ node_index += offset + ( ( code >> depth ) & 1 ) ;
146
155
}
147
156
148
157
match tree[ node_index] {
149
- HuffmanTreeNode :: Empty => tree[ node_index] = HuffmanTreeNode :: Leaf ( symbol) ,
158
+ HuffmanTreeNode :: Empty => {
159
+ tree[ node_index] = HuffmanTreeNode :: Leaf ( symbol as u16 )
160
+ }
150
161
HuffmanTreeNode :: Leaf ( _) => return Err ( DecodingError :: HuffmanError ) ,
151
162
HuffmanTreeNode :: Branch ( _offset) => {
152
163
return Err ( DecodingError :: HuffmanError )
@@ -187,10 +198,11 @@ impl HuffmanTree {
187
198
fn read_symbol_slowpath < R : BufRead > (
188
199
tree : & [ HuffmanTreeNode ] ,
189
200
mut v : usize ,
201
+ start_index : usize ,
190
202
bit_reader : & mut BitReader < R > ,
191
203
) -> Result < u16 , DecodingError > {
192
- let mut depth = 0 ;
193
- let mut index = 0 ;
204
+ let mut depth = MAX_TABLE_BITS ;
205
+ let mut index = start_index ;
194
206
loop {
195
207
match & tree[ index] {
196
208
HuffmanTreeNode :: Branch ( children_offset) => {
@@ -223,12 +235,17 @@ impl HuffmanTree {
223
235
} => {
224
236
let v = bit_reader. peek_full ( ) as u16 ;
225
237
let entry = table[ ( v & table_mask) as usize ] ;
226
- if entry != 0 {
238
+ if entry >> 16 != 0 {
227
239
bit_reader. consume ( ( entry >> 16 ) as u8 ) ?;
228
240
return Ok ( entry as u16 ) ;
229
241
}
230
242
231
- Self :: read_symbol_slowpath ( tree, v as usize , bit_reader)
243
+ Self :: read_symbol_slowpath (
244
+ tree,
245
+ ( v >> MAX_TABLE_BITS ) as usize ,
246
+ ( ( entry & 0xffff ) - 1 ) as usize ,
247
+ bit_reader,
248
+ )
232
249
}
233
250
HuffmanTreeInner :: Single ( symbol) => Ok ( * symbol) ,
234
251
}
0 commit comments