| 1 | use 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. |
| 11 | pub(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 |
| 18 | pub 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)] |
| 32 | pub 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] |
| 63 | pub 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" )] |
| 71 | pub 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 | |