1use core::cell::Cell;
2
3/// make_decode_table_entry() creates a decode table entry for the given symbol
4/// by combining the static part 'decode_results[sym]' with the dynamic part
5/// 'len', which is the remaining codeword length (the codeword length for main
6/// table entries, or the codeword length minus TABLEBITS for subtable entries).
7///
8/// In all cases, we add 'len' to each of the two low-order bytes to create the
9/// appropriately-formatted decode table entry. See the definitions of the
10/// *_decode_results[] arrays below, where the entry format is described.
11pub(crate) fn make_decode_table_entry(decode_results: &[u32], sym: usize, len: u32) -> u32
12{
13 decode_results[sym] + (len << 8) + len
14}
15
16/// A safe version of src.copy_within that helps me because I tend to always
17/// confuse the arguments
18pub fn fixed_copy_within<const SIZE: usize>(dest: &mut [u8], src_offset: usize, dest_offset: usize)
19{
20 // for debug builds ensure we don't go out of bounds
21 debug_assert!(
22 dest_offset + SIZE <= dest.len(),
23 "[dst]: End position {} out of range for slice of length {}",
24 dest_offset + SIZE,
25 dest.len()
26 );
27
28 dest.copy_within(src:src_offset..src_offset + SIZE, dest_offset);
29}
30
31#[inline(always)]
32pub fn copy_rep_matches(dest: &mut [u8], offset: usize, dest_offset: usize, length: usize)
33{
34 // This is a slightly complicated rep match copier that has
35 // no bounds check.
36
37 // The only invariant we need to uphold is dest[dest_offset] should
38 // copy from dest[offset]
39 // i.e in the first iteration, the first entry in the window will point
40 // to dest[offset] and the
41 // last entry will point to dest[dest_offset]
42 // it's easy to prove dest[offset] since we take our slice
43 // from offset.
44 // but proving dest[dest_offset] is trickier
45 // If we were at offset, to get to dest_offset, we could
46 // 1. Get difference between dest_offset and offset
47 // 2. Add that difference to offset.
48 //
49
50 let diff = dest_offset - offset + 1;
51
52 // note
53 for window in Cell::from_mut(&mut dest[offset..dest_offset + length + 2])
54 .as_slice_of_cells()
55 .windows(diff)
56 {
57 window.last().unwrap().set(window[0].get());
58 }
59}
60
61/// Return the minimum of two usizes in a const context
62#[rustfmt::skip]
63pub const fn const_min_usize(a: usize, b: usize) -> usize
64{
65 if a < b { a } else { b }
66}
67
68/// Calculate the adler hash of a piece of data.
69#[inline(never)]
70#[cfg(feature = "zlib")]
71pub fn calc_adler_hash(data: &[u8]) -> u32
72{
73 use simd_adler32::Adler32;
74 let mut hasher: Adler32 = Adler32::new();
75
76 hasher.write(data);
77
78 hasher.finish()
79}
80