diff --git a/src/complevel_estimator.rs b/src/complevel_estimator.rs index fc23421..6103e84 100644 --- a/src/complevel_estimator.rs +++ b/src/complevel_estimator.rs @@ -8,16 +8,16 @@ /// Getting the parameters correct means that the resulting diff between the deflate stream /// and the predicted deflate stream will be as small as possible. use crate::{ - hash_algorithm::{ - HashAlgorithm, HashImplementation, LibdeflateRotatingHash4, MiniZHash, RandomVectorHash, - ZlibNGHash, ZlibRotatingHash, - }, - hash_chain::{DictionaryAddPolicy, HashChain, MAX_UPDATE_HASH_BATCH}, + hash_algorithm::HashAlgorithm, + hash_chain::DictionaryAddPolicy, + hash_chain_holder::{new_hash_chain_holder, HashChainHolderTrait}, preflate_constants, preflate_input::PreflateInput, + preflate_parameter_estimator::PreflateStrategy, preflate_parse_config::{FAST_PREFLATE_PARSER_SETTINGS, SLOW_PREFLATE_PARSER_SETTINGS}, preflate_token::{BlockType, PreflateToken, PreflateTokenBlock, PreflateTokenReference}, skip_length_estimator::estimate_skip_length, + token_predictor::TokenPredictorParameters, }; #[derive(Default)] @@ -37,62 +37,10 @@ pub struct CompLevelInfo { pub max_chain: u32, } -/// vtable for invoking the hash chain functions on specific implementation -/// of hash algorithm -trait HashChainInvoke { - fn invoke_update_hash( - &mut self, - len: u32, - input: &PreflateInput, - add_policy: DictionaryAddPolicy, - ); - - fn invoke_match_depth( - &mut self, - token: PreflateTokenReference, - window_size: u32, - input: &PreflateInput, - ) -> u32; -} - -/// holds the hashchain for a specific hash algorithm -struct HashChainHolder { - hash_chain: H::HashChainType, -} - -impl HashChainHolder { - fn new(hash: H) -> Box { - Box::new(HashChainHolder:: { - hash_chain: hash.new_hash_chain(), - }) - } -} - -impl HashChainInvoke for HashChainHolder { - fn invoke_update_hash( - &mut self, - len: u32, - input: &PreflateInput, - add_policy: DictionaryAddPolicy, - ) { - self.hash_chain - .update_hash_with_policy::(len, input, add_policy) - } - - fn invoke_match_depth( - &mut self, - token: PreflateTokenReference, - window_size: u32, - input: &PreflateInput, - ) -> u32 { - self.hash_chain.match_depth(&token, window_size, input) - } -} - struct CandidateInfo { hash_algorithm: HashAlgorithm, add_policy: DictionaryAddPolicy, - hash_chain: Box, + hash_chain: Box, longest_dist_at_hop_0: u32, longest_dist_at_hop_1_plus: u32, @@ -103,24 +51,29 @@ impl CandidateInfo { fn new( add_policy: DictionaryAddPolicy, hash_algorithm: HashAlgorithm, - input: &PreflateInput, + window_bits: u32, ) -> Self { - CandidateInfo { + let params = TokenPredictorParameters { + hash_algorithm, + add_policy, + matches_to_start_detected: false, + very_far_matches_detected: false, + window_bits, + strategy: PreflateStrategy::Default, + nice_length: 0, + max_token_count: 0, + zlib_compatible: false, + max_dist_3_matches: 0, + good_length: 0, + max_lazy: 0, + max_chain: 0, + min_len: 0, + }; + + Self { add_policy, hash_algorithm, - hash_chain: match hash_algorithm { - HashAlgorithm::Zlib { - hash_mask, - hash_shift, - } => HashChainHolder::new(ZlibRotatingHash { - hash_shift, - hash_mask, - }), - HashAlgorithm::MiniZFast => HashChainHolder::new(MiniZHash {}), - HashAlgorithm::Libdeflate4 => HashChainHolder::new(LibdeflateRotatingHash4 {}), - HashAlgorithm::ZlibNG => HashChainHolder::new(ZlibNGHash {}), - HashAlgorithm::RandomVector => HashChainHolder::new(RandomVectorHash {}), - }, + hash_chain: new_hash_chain_holder(¶ms), longest_dist_at_hop_0: 0, longest_dist_at_hop_1_plus: 0, max_chain_found: 0, @@ -133,9 +86,7 @@ impl CandidateInfo { window_size: u32, input: &PreflateInput, ) -> bool { - let mdepth = self - .hash_chain - .invoke_match_depth(token, window_size, input); + let mdepth = self.hash_chain.match_depth(token, window_size, input); // remove element if the match was impossible due to matching the // the hash depth or because in fast mode we can't match partial words @@ -228,7 +179,7 @@ impl<'a> CompLevelEstimatorState<'a> { candidates.push(Box::new(CandidateInfo::new( add_policy, HashAlgorithm::MiniZFast, - &input, + wbits, ))); for (hash_shift, hash_mask) in [(5, 32767), (4, 2047)] { @@ -238,7 +189,7 @@ impl<'a> CompLevelEstimatorState<'a> { hash_mask, hash_shift, }, - &input, + wbits, ))); } @@ -246,14 +197,14 @@ impl<'a> CompLevelEstimatorState<'a> { candidates.push(Box::new(CandidateInfo::new( add_policy, HashAlgorithm::Libdeflate4, - &input, + wbits, ))); // ZlibNG candidate candidates.push(Box::new(CandidateInfo::new( add_policy, HashAlgorithm::ZlibNG, - &input, + wbits, ))); CompLevelEstimatorState { @@ -269,25 +220,14 @@ impl<'a> CompLevelEstimatorState<'a> { } } - fn update_hash(&mut self, mut length: u32, override_add_policy: bool) { - while length > 0 { - let batch_len = std::cmp::min(length, MAX_UPDATE_HASH_BATCH); - - for i in &mut self.candidates { - i.hash_chain.invoke_update_hash( - batch_len, - &self.input, - if override_add_policy { - DictionaryAddPolicy::AddAll - } else { - i.add_policy - }, - ); - } - - self.input.advance(batch_len); - length -= batch_len; + fn update_hash(&mut self, length: u32, override_add_policy: bool) { + for i in &mut self.candidates { + let mut inputc = self.input.clone(); + i.hash_chain + .update_hash_with_depth(length, &mut inputc, override_add_policy); } + + self.input.advance(length); } fn check_match(&mut self, token: PreflateTokenReference) { diff --git a/src/hash_chain.rs b/src/hash_chain.rs index 359d9af..53986c6 100644 --- a/src/hash_chain.rs +++ b/src/hash_chain.rs @@ -362,13 +362,11 @@ impl HashChainNormalizeLibflate4 { // Important: total_shift starts at -8 since 0 indicates the end of the hash chain // so this means that all valid values will be >= 8, otherwise the very first hash // offset would be zero and so it would get missed - let mut c = HashChainNormalizeLibflate4 { + HashChainNormalizeLibflate4 { total_shift: -8, hash_table: HashTable::default_boxed(), hash_table_3: HashTable::default_boxed(), - }; - - c + } } } diff --git a/src/hash_chain_holder.rs b/src/hash_chain_holder.rs index 0234f5f..70c81e0 100644 --- a/src/hash_chain_holder.rs +++ b/src/hash_chain_holder.rs @@ -68,8 +68,22 @@ pub fn new_hash_chain_holder(params: &TokenPredictorParameters) -> Box HashChainHolderTrait for HashChainHolder { } } + fn update_hash_with_depth( + &mut self, + mut length: u32, + input: &mut PreflateInput, + is_literal: bool, + ) { + while length > 0 { + let batch_len = cmp::min(length, MAX_UPDATE_HASH_BATCH); + + self.hash.update_hash_with_policy::( + batch_len, + input, + if is_literal { + DictionaryAddPolicy::AddAll + } else { + self.params.add_policy + }, + ); + input.advance(batch_len); + length -= batch_len; + } + } + fn match_depth( &self, token: PreflateTokenReference, diff --git a/src/preflate_input.rs b/src/preflate_input.rs index 9284819..604bd29 100644 --- a/src/preflate_input.rs +++ b/src/preflate_input.rs @@ -3,6 +3,8 @@ * Licensed under the Apache License, Version 2.0. See LICENSE.txt in the project root for license information. * This software incorporates material from third parties. See NOTICE.txt for details. *--------------------------------------------------------------------------------------------*/ + +#[derive(Clone)] pub struct PreflateInput<'a> { data: &'a [u8], pos: i32,