Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use slices rather than vectors in ZopfliHash (std only) #27

Merged
merged 10 commits into from
Jul 5, 2023
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ crc32fast = { version = "1.3.2", default-features = false, optional = true }
simd-adler32 = { version = "0.3.5", default-features = false, optional = true }
typed-arena = { version = "2.0.2", default-features = false }
log = "0.4.19"
once_cell = { version = "1.18.0", optional = true }

[dev-dependencies]
proptest = "1.2.0"
Expand All @@ -28,7 +29,7 @@ default = ["gzip", "zlib"]
gzip = ["std", "dep:crc32fast"]
zlib = ["std", "dep:simd-adler32"]

std = ["crc32fast?/std", "simd-adler32?/std"]
std = ["crc32fast?/std", "simd-adler32?/std", "dep:once_cell"]
nightly = ["crc32fast?/nightly", "simd-adler32?/nightly"]

[[bin]]
Expand Down
51 changes: 51 additions & 0 deletions src/hash.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::{
alloc::{alloc, Layout},
boxed::Box,
};

#[cfg(feature = "std")]
use once_cell::sync::Lazy;

use crate::util::{ZOPFLI_MIN_MATCH, ZOPFLI_WINDOW_MASK, ZOPFLI_WINDOW_SIZE};

Expand All @@ -11,18 +20,28 @@ pub enum Which {
Hash2,
}

#[derive(Copy, Clone)]
pub struct SmallerHashThing {
prev: u16, /* Index to index of prev. occurrence of same hash. */
hashval: Option<u16>, /* Index to hash value at this index. */
}

#[cfg(feature = "std")]
#[derive(Copy, Clone)]
pub struct HashThing {
head: [i16; 65536], /* Hash value to index of its most recent occurrence. */
prev_and_hashval: [SmallerHashThing; ZOPFLI_WINDOW_SIZE],
val: u16, /* Current hash value. */
}
#[cfg(not(feature = "std"))]
pub struct HashThing {
head: Vec<i16>, /* Hash value to index of its most recent occurrence. */
prev_and_hashval: Vec<SmallerHashThing>,
val: u16, /* Current hash value. */
}

impl HashThing {
#[cfg(not(feature = "std"))]
fn new() -> HashThing {
HashThing {
head: vec![-1; 65536],
Expand All @@ -36,6 +55,7 @@ impl HashThing {
}
}

#[cfg(not(feature = "std"))]
fn reset(&mut self) {
self.val = 0;

Expand Down Expand Up @@ -74,13 +94,38 @@ impl HashThing {
}
}

#[cfg_attr(feature = "std", derive(Copy, Clone))]
pub struct ZopfliHash {
hash1: HashThing,
hash2: HashThing,
pub same: [u16; ZOPFLI_WINDOW_SIZE], /* Amount of repetitions of same byte after this .*/
}

#[cfg(feature = "std")]
const EMPTY_ZOPFLI_HASH: Lazy<Box<ZopfliHash>> = Lazy::new(|| unsafe {
let layout = Layout::new::<ZopfliHash>();
let ptr = alloc(layout) as *mut ZopfliHash;
for i in 0..ZOPFLI_WINDOW_SIZE {
(*ptr).hash1.prev_and_hashval[i].prev = i as u16;
(*ptr).hash2.prev_and_hashval[i].prev = i as u16;
(*ptr).hash1.prev_and_hashval[i].hashval = None;
(*ptr).hash2.prev_and_hashval[i].hashval = None;
}
(*ptr).hash1.head = [-1; 65536];
(*ptr).hash2.head = [-1; 65536];
(*ptr).hash1.val = 0;
(*ptr).hash2.val = 0;
(*ptr).same = [0; ZOPFLI_WINDOW_SIZE];
Box::from_raw(ptr)
});
Pr0methean marked this conversation as resolved.
Show resolved Hide resolved

impl ZopfliHash {
#[cfg(feature = "std")]
pub fn new() -> Box<ZopfliHash> {
EMPTY_ZOPFLI_HASH.clone()
}

#[cfg(not(feature = "std"))]
pub fn new() -> ZopfliHash {
ZopfliHash {
hash1: HashThing::new(),
Expand All @@ -89,6 +134,12 @@ impl ZopfliHash {
}
}

#[cfg(feature = "std")]
pub fn reset(&mut self) {
*self = **EMPTY_ZOPFLI_HASH;
}

#[cfg(not(feature = "std"))]
pub fn reset(&mut self) {
self.hash1.reset();
self.hash2.reset();
Expand Down