@@ -99,7 +99,7 @@ const MAX_HUFF_SYMBOLS_0: usize = 288;
99
99
/// The length of the second (distance) huffman table.
100
100
const MAX_HUFF_SYMBOLS_1 : usize = 32 ;
101
101
/// The length of the last (huffman code length) huffman table.
102
- const _MAX_HUFF_SYMBOLS_2: usize = 19 ;
102
+ // const _MAX_HUFF_SYMBOLS_2: usize = 19;
103
103
/// The maximum length of a code that can be looked up in the fast lookup table.
104
104
const FAST_LOOKUP_BITS : u8 = 10 ;
105
105
/// The size of the fast lookup table.
@@ -337,7 +337,6 @@ impl State {
337
337
338
338
use self :: State :: * ;
339
339
340
- // Not sure why miniz uses 32-bit values for these, maybe alignment/cache again?
341
340
// # Optimization
342
341
// We add a extra value at the end and make the tables 32 elements long
343
342
// so we can use a mask to avoid bounds checks.
@@ -362,18 +361,20 @@ const LENGTH_EXTRA: [u8; 32] = [
362
361
363
362
/// Base length for each distance code.
364
363
#[ rustfmt:: skip]
365
- const DIST_BASE : [ u16 ; 32 ] = [
364
+ const DIST_BASE : [ u16 ; 30 ] = [
366
365
1 , 2 , 3 , 4 , 5 , 7 , 9 , 13 , 17 , 25 , 33 ,
367
366
49 , 65 , 97 , 129 , 193 , 257 , 385 , 513 , 769 , 1025 , 1537 ,
368
- 2049 , 3073 , 4097 , 6145 , 8193 , 12_289 , 16_385 , 24_577 , 32_768 , 32_768
367
+ 2049 , 3073 , 4097 , 6145 , 8193 , 12_289 , 16_385 , 24_577
369
368
] ;
370
369
371
- /// Number of extra bits for each distance code.
372
- #[ rustfmt:: skip]
373
- const DIST_EXTRA : [ u8 ; 32 ] = [
374
- 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 , 3 , 3 , 4 , 4 , 5 , 5 , 6 , 6 ,
375
- 7 , 7 , 8 , 8 , 9 , 9 , 10 , 10 , 11 , 11 , 12 , 12 , 13 , 13 , 13 , 13
376
- ] ;
370
+ /// Get the number of extra bits used for a distance code.
371
+ /// (Code numbers above `NUM_DISTANCE_CODES` will give some garbage
372
+ /// value.)
373
+ const fn num_extra_bits_for_distance_code ( code : u8 ) -> u8 {
374
+ // This can be easily calculated without a lookup.
375
+ let c = code >> 1 ;
376
+ c - ( c != 0 ) as u8
377
+ }
377
378
378
379
/// The mask used when indexing the base/extra arrays.
379
380
const BASE_EXTRA_MASK : usize = 32 - 1 ;
@@ -1092,7 +1093,7 @@ fn decompress_fast(
1092
1093
break ' o TINFLStatus :: Failed ;
1093
1094
}
1094
1095
1095
- l. num_extra = u32:: from ( DIST_EXTRA [ symbol as usize ] ) ;
1096
+ l. num_extra = u32:: from ( num_extra_bits_for_distance_code ( symbol as u8 ) ) ;
1096
1097
l. dist = u32:: from ( DIST_BASE [ symbol as usize ] ) ;
1097
1098
} else {
1098
1099
state. begin ( InvalidCodeLen ) ;
@@ -1149,18 +1150,18 @@ fn decompress_fast(
1149
1150
///
1150
1151
/// * The offset given by `out_pos` indicates where in the output buffer slice writing should start.
1151
1152
/// * If [`TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF`] is not set, the output buffer is used in a
1152
- /// wrapping manner, and it's size is required to be a power of 2.
1153
+ /// wrapping manner, and it's size is required to be a power of 2.
1153
1154
/// * The decompression function normally needs access to 32KiB of the previously decompressed data
1154
- ///(or to the beginning of the decompressed data if less than 32KiB has been decompressed.)
1155
+ /// (or to the beginning of the decompressed data if less than 32KiB has been decompressed.)
1155
1156
/// - If this data is not available, decompression may fail.
1156
1157
/// - Some deflate compressors allow specifying a window size which limits match distances to
1157
- /// less than this, or alternatively an RLE mode where matches will only refer to the previous byte
1158
- /// and thus allows a smaller output buffer. The window size can be specified in the zlib
1159
- /// header structure, however, the header data should not be relied on to be correct.
1158
+ /// less than this, or alternatively an RLE mode where matches will only refer to the previous byte
1159
+ /// and thus allows a smaller output buffer. The window size can be specified in the zlib
1160
+ /// header structure, however, the header data should not be relied on to be correct.
1160
1161
///
1161
1162
/// `flags` indicates settings and status to the decompression function.
1162
1163
/// * The [`TINFL_FLAG_HAS_MORE_INPUT`] has to be specified if more compressed data is to be provided
1163
- /// in a subsequent call to this function.
1164
+ /// in a subsequent call to this function.
1164
1165
/// * See the the [`inflate_flags`] module for details on other flags.
1165
1166
///
1166
1167
/// # Returns
@@ -1177,7 +1178,7 @@ pub fn decompress(
1177
1178
flags : u32 ,
1178
1179
) -> ( TINFLStatus , usize , usize ) {
1179
1180
let out_buf_size_mask = if flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0 {
1180
- usize:: max_value ( )
1181
+ usize:: MAX
1181
1182
} else {
1182
1183
// In the case of zero len, any attempt to write would produce HasMoreOutput,
1183
1184
// so to gracefully process the case of there really being no output,
@@ -1610,16 +1611,19 @@ pub fn decompress(
1610
1611
// Try to read a huffman code from the input buffer and look up what
1611
1612
// length code the decoded symbol refers to.
1612
1613
decode_huffman_code( r, & mut l, DIST_TABLE , flags, & mut in_iter, |_r, l, symbol| {
1614
+ // # Optimizaton - transform the value into usize here before the check so
1615
+ // the compiler can optimize the bounds check later - ideally it should
1616
+ // know that the value can't be negative from earlier in the
1617
+ // decode_huffman_code function but it seems it may not be able
1618
+ // to make the assumption that it can't be negative and thus
1619
+ // overflow if it's converted after the check.
1620
+ let symbol = symbol as usize ;
1613
1621
if symbol > 29 {
1614
1622
// Invalid distance code.
1615
1623
return Action :: Jump ( InvalidDist )
1616
1624
}
1617
- // # Optimization
1618
- // Mask the value to avoid bounds checks
1619
- // We could use get_unchecked later if can statically verify that
1620
- // this will never go out of bounds.
1621
- l. num_extra = u32 :: from( DIST_EXTRA [ symbol as usize & BASE_EXTRA_MASK ] ) ;
1622
- l. dist = u32 :: from( DIST_BASE [ symbol as usize & BASE_EXTRA_MASK ] ) ;
1625
+ l. num_extra = u32 :: from( num_extra_bits_for_distance_code( symbol as u8 ) ) ;
1626
+ l. dist = u32 :: from( DIST_BASE [ symbol] ) ;
1623
1627
if l. num_extra != 0 {
1624
1628
// ReadEXTRA_BITS_DISTACNE
1625
1629
Action :: Jump ( ReadExtraBitsDistance )
@@ -2051,4 +2055,18 @@ mod test {
2051
2055
let res = decompress ( & mut r, & encoded, & mut output_buf, 0 , flags) ;
2052
2056
assert_eq ! ( res, ( TINFLStatus :: HasMoreOutput , 2 , 0 ) ) ;
2053
2057
}
2058
+
2059
+ #[ test]
2060
+ fn dist_extra_bits ( ) {
2061
+ use self :: num_extra_bits_for_distance_code;
2062
+ // Number of extra bits for each distance code.
2063
+ const DIST_EXTRA : [ u8 ; 29 ] = [
2064
+ 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 ,
2065
+ 12 , 13 ,
2066
+ ] ;
2067
+
2068
+ for ( i, & dist) in DIST_EXTRA . iter ( ) . enumerate ( ) {
2069
+ assert_eq ! ( dist, num_extra_bits_for_distance_code( i as u8 ) ) ;
2070
+ }
2071
+ }
2054
2072
}
0 commit comments