diff --git a/zlib-rs/src/deflate.rs b/zlib-rs/src/deflate.rs index e256df4..726d221 100644 --- a/zlib-rs/src/deflate.rs +++ b/zlib-rs/src/deflate.rs @@ -1353,11 +1353,27 @@ impl<'a> State<'a> { #[inline(always)] pub(crate) fn quick_insert_string(&mut self, string: usize) -> u16 { match self.hash_calc_variant { - HashCalcVariant::Standard => StandardHashCalc::quick_insert_string(self, string), - // SAFETY: self.hash_calc_variant is set by HashCalcVariant::for_max_chain_length, - // which avoids choosing Crc32 if the system doesn't have support. - HashCalcVariant::Crc32 => unsafe { Crc32HashCalc::quick_insert_string(self, string) }, HashCalcVariant::Roll => RollHashCalc::quick_insert_string(self, string), + _ => { + // Standard and Crc32 both can process 4 bytes at a time. + let slice = &self.window.filled()[string..]; + let val = u32::from_le_bytes(slice[..4].try_into().unwrap()); + + let hm = match self.hash_calc_variant { + // SAFETY: self.hash_calc_variant is set by HashCalcVariant::for_max_chain_length, + // which avoids choosing Crc32 if the system doesn't have support. + HashCalcVariant::Crc32 => unsafe { Crc32HashCalc::update_hash(0, val) } + _ => StandardHashCalc::update_hash(0, val) + } as usize; + + let head = self.head.as_slice()[hm]; + if head != string as u16 { + self.prev.as_mut_slice()[string & self.w_mask] = head; + self.head.as_mut_slice()[hm] = string as u16; + } + + head + } } } diff --git a/zlib-rs/src/deflate/algorithm/quick.rs b/zlib-rs/src/deflate/algorithm/quick.rs index c7b3526..c1f471d 100644 --- a/zlib-rs/src/deflate/algorithm/quick.rs +++ b/zlib-rs/src/deflate/algorithm/quick.rs @@ -93,6 +93,8 @@ pub fn deflate_quick(stream: &mut DeflateStream, flush: DeflateFlush) -> BlockSt } if state.lookahead >= WANT_MIN_MATCH { + let slice = &state.window.filled()[state.strstart..]; + let str_prefetch = u32::from_le_bytes(slice[..4].try_into().unwrap()); let hash_head = state.quick_insert_string(state.strstart); let dist = state.strstart as isize - hash_head as isize; @@ -102,10 +104,10 @@ pub fn deflate_quick(stream: &mut DeflateStream, flush: DeflateFlush) -> BlockSt macro_rules! first_two_bytes { ($slice:expr, $offset:expr) => { - $slice[$offset] as u16 | ($slice[$offset + 1] as u16) << 8 + u16::from_le_bytes($slice[..2].try_into().unwrap()) } } - if first_two_bytes!(str_start, 0) == first_two_bytes!(match_start, 0) { + if str_prefetch as u16 == first_two_bytes!(match_start, 0) { let mut match_len = crate::deflate::compare256::compare256_slice( &str_start[2..], &match_start[2..],