@@ -4,10 +4,10 @@ use super::*;
4
4
use crate :: shared:: { update_adler32, HUFFMAN_LENGTH_ORDER } ;
5
5
use :: core:: cell:: Cell ;
6
6
7
+ use :: core:: cmp;
7
8
use :: core:: convert:: TryInto ;
8
- use :: core:: { cmp, slice} ;
9
9
10
- use self :: output_buffer:: OutputBuffer ;
10
+ use self :: output_buffer:: { InputWrapper , OutputBuffer } ;
11
11
12
12
pub const TINFL_LZ_DICT_SIZE : usize = 32_768 ;
13
13
@@ -47,7 +47,7 @@ impl HuffmanTable {
47
47
48
48
/// Get the symbol and the code length from the huffman tree.
49
49
#[ inline]
50
- fn tree_lookup ( & self , fast_symbol : i32 , bit_buf : BitBuffer , mut code_len : u32 ) -> ( i32 , u32 ) {
50
+ fn tree_lookup ( & self , fast_symbol : i32 , bit_buf : BitBuffer , mut code_len : u8 ) -> ( i32 , u32 ) {
51
51
let mut symbol = fast_symbol;
52
52
// We step through the tree until we encounter a positive value, which indicates a
53
53
// symbol.
@@ -65,7 +65,9 @@ impl HuffmanTable {
65
65
break ;
66
66
}
67
67
}
68
- ( symbol, code_len)
68
+ // Note: Using a u8 for code_len inside this function seems to improve performance, but changing it
69
+ // in localvars seems to worsen things so we convert it to a u32 here.
70
+ ( symbol, u32:: from ( code_len) )
69
71
}
70
72
71
73
#[ inline]
@@ -87,7 +89,7 @@ impl HuffmanTable {
87
89
}
88
90
} else {
89
91
// We didn't get a symbol from the fast lookup table, so check the tree instead.
90
- Some ( self . tree_lookup ( symbol, bit_buf, FAST_LOOKUP_BITS . into ( ) ) )
92
+ Some ( self . tree_lookup ( symbol, bit_buf, FAST_LOOKUP_BITS ) )
91
93
}
92
94
}
93
95
}
@@ -370,10 +372,12 @@ const DIST_BASE: [u16; 30] = [
370
372
/// Get the number of extra bits used for a distance code.
371
373
/// (Code numbers above `NUM_DISTANCE_CODES` will give some garbage
372
374
/// value.)
375
+ #[ inline( always) ]
373
376
const fn num_extra_bits_for_distance_code ( code : u8 ) -> u8 {
377
+ // TODO: Need to verify that this is faster on all platforms.
374
378
// This can be easily calculated without a lookup.
375
379
let c = code >> 1 ;
376
- c - ( c != 0 ) as u8
380
+ c. saturating_sub ( 1 )
377
381
}
378
382
379
383
/// The mask used when indexing the base/extra arrays.
@@ -392,27 +396,12 @@ fn memset<T: Copy>(slice: &mut [T], val: T) {
392
396
/// # Panics
393
397
/// Panics if there are less than two bytes left.
394
398
#[ inline]
395
- fn read_u16_le ( iter : & mut slice :: Iter < u8 > ) -> u16 {
399
+ fn read_u16_le ( iter : & mut InputWrapper ) -> u16 {
396
400
let ret = {
397
- let two_bytes = iter. as_ref ( ) [ ..2 ] . try_into ( ) . unwrap ( ) ;
401
+ let two_bytes = iter. as_slice ( ) [ ..2 ] . try_into ( ) . unwrap_or_default ( ) ;
398
402
u16:: from_le_bytes ( two_bytes)
399
403
} ;
400
- iter. nth ( 1 ) ;
401
- ret
402
- }
403
-
404
- /// Read an le u32 value from the slice iterator.
405
- ///
406
- /// # Panics
407
- /// Panics if there are less than four bytes left.
408
- #[ inline( always) ]
409
- #[ cfg( target_pointer_width = "64" ) ]
410
- fn read_u32_le ( iter : & mut slice:: Iter < u8 > ) -> u32 {
411
- let ret = {
412
- let four_bytes: [ u8 ; 4 ] = iter. as_ref ( ) [ ..4 ] . try_into ( ) . unwrap ( ) ;
413
- u32:: from_le_bytes ( four_bytes)
414
- } ;
415
- iter. nth ( 3 ) ;
404
+ iter. advance ( 2 ) ;
416
405
ret
417
406
}
418
407
@@ -423,10 +412,10 @@ fn read_u32_le(iter: &mut slice::Iter<u8>) -> u32 {
423
412
/// This function assumes that there is at least 4 bytes left in the input buffer.
424
413
#[ inline( always) ]
425
414
#[ cfg( target_pointer_width = "64" ) ]
426
- fn fill_bit_buffer ( l : & mut LocalVars , in_iter : & mut slice :: Iter < u8 > ) {
415
+ fn fill_bit_buffer ( l : & mut LocalVars , in_iter : & mut InputWrapper ) {
427
416
// Read four bytes into the buffer at once.
428
417
if l. num_bits < 30 {
429
- l. bit_buf |= BitBuffer :: from ( read_u32_le ( in_iter ) ) << l. num_bits ;
418
+ l. bit_buf |= BitBuffer :: from ( in_iter . read_u32_le ( ) ) << l. num_bits ;
430
419
l. num_bits += 32 ;
431
420
}
432
421
}
@@ -435,7 +424,7 @@ fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) {
435
424
/// Ensures at least 16 bits are present, requires at least 2 bytes in the in buffer.
436
425
#[ inline( always) ]
437
426
#[ cfg( not( target_pointer_width = "64" ) ) ]
438
- fn fill_bit_buffer ( l : & mut LocalVars , in_iter : & mut slice :: Iter < u8 > ) {
427
+ fn fill_bit_buffer ( l : & mut LocalVars , in_iter : & mut InputWrapper ) {
439
428
// If the buffer is 32-bit wide, read 2 bytes instead.
440
429
if l. num_bits < 15 {
441
430
l. bit_buf |= BitBuffer :: from ( read_u16_le ( in_iter) ) << l. num_bits ;
@@ -491,7 +480,7 @@ fn decode_huffman_code<F>(
491
480
l : & mut LocalVars ,
492
481
table : usize ,
493
482
flags : u32 ,
494
- in_iter : & mut slice :: Iter < u8 > ,
483
+ in_iter : & mut InputWrapper ,
495
484
f : F ,
496
485
) -> Action
497
486
where
@@ -501,7 +490,7 @@ where
501
490
// ready in the bit buffer to start decoding the next huffman code.
502
491
if l. num_bits < 15 {
503
492
// First, make sure there is enough data in the bit buffer to decode a huffman code.
504
- if in_iter. len ( ) < 2 {
493
+ if in_iter. bytes_left ( ) < 2 {
505
494
// If there is less than 2 bytes left in the input buffer, we try to look up
506
495
// the huffman code with what's available, and return if that doesn't succeed.
507
496
// Original explanation in miniz:
@@ -581,7 +570,7 @@ where
581
570
// Mask out the length value.
582
571
symbol &= 511 ;
583
572
} else {
584
- let res = r. tables [ table] . tree_lookup ( symbol, l. bit_buf , u32 :: from ( FAST_LOOKUP_BITS ) ) ;
573
+ let res = r. tables [ table] . tree_lookup ( symbol, l. bit_buf , FAST_LOOKUP_BITS ) ;
585
574
symbol = res. 0 ;
586
575
code_len = res. 1 ;
587
576
} ;
@@ -599,13 +588,13 @@ where
599
588
/// returning the result.
600
589
/// If reading fails, `Action::End is returned`
601
590
#[ inline]
602
- fn read_byte < F > ( in_iter : & mut slice :: Iter < u8 > , flags : u32 , f : F ) -> Action
591
+ fn read_byte < F > ( in_iter : & mut InputWrapper , flags : u32 , f : F ) -> Action
603
592
where
604
593
F : FnOnce ( u8 ) -> Action ,
605
594
{
606
- match in_iter. next ( ) {
595
+ match in_iter. read_byte ( ) {
607
596
None => end_of_input ( flags) ,
608
- Some ( & byte) => f ( byte) ,
597
+ Some ( byte) => f ( byte) ,
609
598
}
610
599
}
611
600
@@ -618,7 +607,7 @@ where
618
607
fn read_bits < F > (
619
608
l : & mut LocalVars ,
620
609
amount : u32 ,
621
- in_iter : & mut slice :: Iter < u8 > ,
610
+ in_iter : & mut InputWrapper ,
622
611
flags : u32 ,
623
612
f : F ,
624
613
) -> Action
@@ -647,7 +636,7 @@ where
647
636
}
648
637
649
638
#[ inline]
650
- fn pad_to_bytes < F > ( l : & mut LocalVars , in_iter : & mut slice :: Iter < u8 > , flags : u32 , f : F ) -> Action
639
+ fn pad_to_bytes < F > ( l : & mut LocalVars , in_iter : & mut InputWrapper , flags : u32 , f : F ) -> Action
651
640
where
652
641
F : FnOnce ( & mut LocalVars ) -> Action ,
653
642
{
@@ -854,7 +843,7 @@ struct LocalVars {
854
843
pub num_bits : u32 ,
855
844
pub dist : u32 ,
856
845
pub counter : u32 ,
857
- pub num_extra : u32 ,
846
+ pub num_extra : u8 ,
858
847
}
859
848
860
849
#[ inline]
@@ -981,7 +970,7 @@ fn apply_match(
981
970
/// and already improves decompression speed a fair bit.
982
971
fn decompress_fast (
983
972
r : & mut DecompressorOxide ,
984
- in_iter : & mut slice :: Iter < u8 > ,
973
+ in_iter : & mut InputWrapper ,
985
974
out_buf : & mut OutputBuffer ,
986
975
flags : u32 ,
987
976
local_vars : & mut LocalVars ,
@@ -1001,7 +990,7 @@ fn decompress_fast(
1001
990
// + 29 + 32 (left in bit buf, including last 13 dist extra) = 111 bits < 14 bytes
1002
991
// We need the one extra byte as we may write one length and one full match
1003
992
// before checking again.
1004
- if out_buf. bytes_left ( ) < 259 || in_iter. len ( ) < 14 {
993
+ if out_buf. bytes_left ( ) < 259 || in_iter. bytes_left ( ) < 14 {
1005
994
state = State :: DecodeLitlen ;
1006
995
break ' o TINFLStatus :: Done ;
1007
996
}
@@ -1063,18 +1052,19 @@ fn decompress_fast(
1063
1052
// The symbol was a length code.
1064
1053
// # Optimization
1065
1054
// Mask the value to avoid bounds checks
1066
- // We could use get_unchecked later if can statically verify that
1067
- // this will never go out of bounds .
1068
- l. num_extra = u32 :: from ( LENGTH_EXTRA [ ( l. counter - 257 ) as usize & BASE_EXTRA_MASK ] ) ;
1055
+ // While the maximum is checked, the compiler isn't able to know that the
1056
+ // value won't wrap around here .
1057
+ l. num_extra = LENGTH_EXTRA [ ( l. counter - 257 ) as usize & BASE_EXTRA_MASK ] ;
1069
1058
l. counter = u32:: from ( LENGTH_BASE [ ( l. counter - 257 ) as usize & BASE_EXTRA_MASK ] ) ;
1070
1059
// Length and distance codes have a number of extra bits depending on
1071
1060
// the base, which together with the base gives us the exact value.
1072
1061
1062
+ // We need to make sure we have at least 33 (so min 5 bytes) bits in the buffer at this spot.
1073
1063
fill_bit_buffer ( & mut l, in_iter) ;
1074
1064
if l. num_extra != 0 {
1075
1065
let extra_bits = l. bit_buf & ( ( 1 << l. num_extra ) - 1 ) ;
1076
1066
l. bit_buf >>= l. num_extra ;
1077
- l. num_bits -= l. num_extra ;
1067
+ l. num_bits -= u32 :: from ( l. num_extra ) ;
1078
1068
l. counter += extra_bits as u32 ;
1079
1069
}
1080
1070
@@ -1093,7 +1083,7 @@ fn decompress_fast(
1093
1083
break ' o TINFLStatus :: Failed ;
1094
1084
}
1095
1085
1096
- l. num_extra = u32 :: from ( num_extra_bits_for_distance_code ( symbol as u8 ) ) ;
1086
+ l. num_extra = num_extra_bits_for_distance_code ( symbol as u8 ) ;
1097
1087
l. dist = u32:: from ( DIST_BASE [ symbol as usize ] ) ;
1098
1088
} else {
1099
1089
state. begin ( InvalidCodeLen ) ;
@@ -1104,7 +1094,7 @@ fn decompress_fast(
1104
1094
fill_bit_buffer ( & mut l, in_iter) ;
1105
1095
let extra_bits = l. bit_buf & ( ( 1 << l. num_extra ) - 1 ) ;
1106
1096
l. bit_buf >>= l. num_extra ;
1107
- l. num_bits -= l. num_extra ;
1097
+ l. num_bits -= u32 :: from ( l. num_extra ) ;
1108
1098
l. dist += extra_bits as u32 ;
1109
1099
}
1110
1100
@@ -1194,7 +1184,7 @@ pub fn decompress(
1194
1184
return ( TINFLStatus :: BadParam , 0 , 0 ) ;
1195
1185
}
1196
1186
1197
- let mut in_iter = in_buf . iter ( ) ;
1187
+ let mut in_iter = InputWrapper :: from_slice ( in_buf ) ;
1198
1188
1199
1189
let mut state = r. state ;
1200
1190
@@ -1206,7 +1196,7 @@ pub fn decompress(
1206
1196
num_bits : r. num_bits ,
1207
1197
dist : r. dist ,
1208
1198
counter : r. counter ,
1209
- num_extra : r. num_extra ,
1199
+ num_extra : r. num_extra as u8 ,
1210
1200
} ;
1211
1201
1212
1202
let mut status = ' state_machine: loop {
@@ -1351,20 +1341,20 @@ pub fn decompress(
1351
1341
} ) ,
1352
1342
1353
1343
RawMemcpy2 => generate_state ! ( state, ' state_machine, {
1354
- if in_iter. len ( ) > 0 {
1344
+ if in_iter. bytes_left ( ) > 0 {
1355
1345
// Copy as many raw bytes as possible from the input to the output using memcpy.
1356
1346
// Raw block lengths are limited to 64 * 1024, so casting through usize and u32
1357
1347
// is not an issue.
1358
1348
let space_left = out_buf. bytes_left( ) ;
1359
1349
let bytes_to_copy = cmp:: min( cmp:: min(
1360
1350
space_left,
1361
- in_iter. len ( ) ) ,
1351
+ in_iter. bytes_left ( ) ) ,
1362
1352
l. counter as usize
1363
1353
) ;
1364
1354
1365
1355
out_buf. write_slice( & in_iter. as_slice( ) [ ..bytes_to_copy] ) ;
1366
1356
1367
- in_iter. nth ( bytes_to_copy - 1 ) ;
1357
+ in_iter. advance ( bytes_to_copy) ;
1368
1358
l. counter -= bytes_to_copy as u32 ;
1369
1359
Action :: Jump ( RawMemcpy1 )
1370
1360
} else {
@@ -1456,7 +1446,7 @@ pub fn decompress(
1456
1446
} ) ,
1457
1447
1458
1448
ReadExtraBitsCodeSize => generate_state ! ( state, ' state_machine, {
1459
- let num_extra = l. num_extra;
1449
+ let num_extra = l. num_extra. into ( ) ;
1460
1450
read_bits( & mut l, num_extra, & mut in_iter, flags, |l, mut extra_bits| {
1461
1451
// Mask to avoid a bounds check.
1462
1452
extra_bits += [ 3 , 3 , 11 ] [ ( l. dist as usize - 16 ) & 3 ] ;
@@ -1478,7 +1468,7 @@ pub fn decompress(
1478
1468
} ) ,
1479
1469
1480
1470
DecodeLitlen => generate_state ! ( state, ' state_machine, {
1481
- if in_iter. len ( ) < 4 || out_buf. bytes_left( ) < 2 {
1471
+ if in_iter. bytes_left ( ) < 4 || out_buf. bytes_left( ) < 2 {
1482
1472
// See if we can decode a literal with the data we have left.
1483
1473
// Jumps to next state (WriteSymbol) if successful.
1484
1474
decode_huffman_code(
@@ -1496,7 +1486,7 @@ pub fn decompress(
1496
1486
// If there is enough space, use the fast inner decompression
1497
1487
// function.
1498
1488
out_buf. bytes_left( ) >= 259 &&
1499
- in_iter. len ( ) >= 14
1489
+ in_iter. bytes_left ( ) >= 14
1500
1490
{
1501
1491
let ( status, new_state) = decompress_fast(
1502
1492
r,
@@ -1587,7 +1577,7 @@ pub fn decompress(
1587
1577
// We could use get_unchecked later if can statically verify that
1588
1578
// this will never go out of bounds.
1589
1579
l. num_extra =
1590
- u32 :: from ( LENGTH_EXTRA [ ( l. counter - 257 ) as usize & BASE_EXTRA_MASK ] ) ;
1580
+ LENGTH_EXTRA [ ( l. counter - 257 ) as usize & BASE_EXTRA_MASK ] ;
1591
1581
l. counter = u32 :: from( LENGTH_BASE [ ( l. counter - 257 ) as usize & BASE_EXTRA_MASK ] ) ;
1592
1582
// Length and distance codes have a number of extra bits depending on
1593
1583
// the base, which together with the base gives us the exact value.
@@ -1600,7 +1590,7 @@ pub fn decompress(
1600
1590
} ) ,
1601
1591
1602
1592
ReadExtraBitsLitlen => generate_state ! ( state, ' state_machine, {
1603
- let num_extra = l. num_extra;
1593
+ let num_extra = l. num_extra. into ( ) ;
1604
1594
read_bits( & mut l, num_extra, & mut in_iter, flags, |l, extra_bits| {
1605
1595
l. counter += extra_bits as u32 ;
1606
1596
Action :: Jump ( DecodeDistance )
@@ -1622,7 +1612,7 @@ pub fn decompress(
1622
1612
// Invalid distance code.
1623
1613
return Action :: Jump ( InvalidDist )
1624
1614
}
1625
- l. num_extra = u32 :: from ( num_extra_bits_for_distance_code( symbol as u8 ) ) ;
1615
+ l. num_extra = num_extra_bits_for_distance_code( symbol as u8 ) ;
1626
1616
l. dist = u32 :: from( DIST_BASE [ symbol] ) ;
1627
1617
if l. num_extra != 0 {
1628
1618
// ReadEXTRA_BITS_DISTACNE
@@ -1634,7 +1624,7 @@ pub fn decompress(
1634
1624
} ) ,
1635
1625
1636
1626
ReadExtraBitsDistance => generate_state ! ( state, ' state_machine, {
1637
- let num_extra = l. num_extra;
1627
+ let num_extra = l. num_extra. into ( ) ;
1638
1628
read_bits( & mut l, num_extra, & mut in_iter, flags, |l, extra_bits| {
1639
1629
l. dist += extra_bits as u32 ;
1640
1630
Action :: Jump ( HuffDecodeOuterLoop2 )
@@ -1710,9 +1700,9 @@ pub fn decompress(
1710
1700
if r. finish != 0 {
1711
1701
pad_to_bytes( & mut l, & mut in_iter, flags, |_| Action :: None ) ;
1712
1702
1713
- let in_consumed = in_buf. len( ) - in_iter. len ( ) ;
1703
+ let in_consumed = in_buf. len( ) - in_iter. bytes_left ( ) ;
1714
1704
let undo = undo_bytes( & mut l, in_consumed as u32 ) as usize ;
1715
- in_iter = in_buf[ in_consumed - undo..] . iter( ) ;
1705
+ in_iter = InputWrapper :: from_slice ( in_buf[ in_consumed - undo..] . iter( ) . as_slice ( ) ) ;
1716
1706
1717
1707
l. bit_buf &= ( ( 1 as BitBuffer ) << l. num_bits) - 1 ;
1718
1708
debug_assert_eq!( l. num_bits, 0 ) ;
@@ -1765,7 +1755,7 @@ pub fn decompress(
1765
1755
let in_undo = if status != TINFLStatus :: NeedsMoreInput
1766
1756
&& status != TINFLStatus :: FailedCannotMakeProgress
1767
1757
{
1768
- undo_bytes ( & mut l, ( in_buf. len ( ) - in_iter. len ( ) ) as u32 ) as usize
1758
+ undo_bytes ( & mut l, ( in_buf. len ( ) - in_iter. bytes_left ( ) ) as u32 ) as usize
1769
1759
} else {
1770
1760
0
1771
1761
} ;
@@ -1785,7 +1775,7 @@ pub fn decompress(
1785
1775
r. num_bits = l. num_bits ;
1786
1776
r. dist = l. dist ;
1787
1777
r. counter = l. counter ;
1788
- r. num_extra = l. num_extra ;
1778
+ r. num_extra = l. num_extra . into ( ) ;
1789
1779
1790
1780
r. bit_buf &= ( ( 1 as BitBuffer ) << r. num_bits ) - 1 ;
1791
1781
@@ -1816,7 +1806,7 @@ pub fn decompress(
1816
1806
1817
1807
(
1818
1808
status,
1819
- in_buf. len ( ) - in_iter. len ( ) - in_undo,
1809
+ in_buf. len ( ) - in_iter. bytes_left ( ) - in_undo,
1820
1810
out_buf. position ( ) - out_pos,
1821
1811
)
1822
1812
}
@@ -1911,7 +1901,7 @@ mod test {
1911
1901
num_bits : d. num_bits ,
1912
1902
dist : d. dist ,
1913
1903
counter : d. counter ,
1914
- num_extra : d. num_extra ,
1904
+ num_extra : d. num_extra as u8 ,
1915
1905
} ;
1916
1906
init_tree ( & mut d, & mut l) . unwrap ( ) ;
1917
1907
let llt = & d. tables [ LITLEN_TABLE ] ;
0 commit comments