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