diff --git a/src/filters/fb_network_builder.rs b/src/filters/fb_network_builder.rs index e569a3fb..877bd124 100644 --- a/src/filters/fb_network_builder.rs +++ b/src/filters/fb_network_builder.rs @@ -232,7 +232,7 @@ impl NetworkRulesBuilder { for filter in network_filters.into_iter() { // skip any bad filters - let filter_id = filter.get_id(); + let filter_id = filter.get_id_without_badfilter(); if badfilter_ids.contains(&filter_id) || filter.is_badfilter() { continue; } diff --git a/src/filters/network.rs b/src/filters/network.rs index 043b7825..0051175b 100644 --- a/src/filters/network.rs +++ b/src/filters/network.rs @@ -860,26 +860,25 @@ impl NetworkFilter { } pub fn get_id_without_badfilter(&self) -> Hash { - let mut mask = self.mask; - mask.set(NetworkFilterMask::BAD_FILTER, false); compute_filter_id( - self.modifier_option.as_deref(), - mask, - self.filter.string_view().as_deref(), - self.hostname.as_deref(), - self.opt_domains.as_ref(), - self.opt_not_domains.as_ref(), + &self.modifier_option, + self.mask.bits() & !NetworkFilterMask::BAD_FILTER.bits(), + &self.filter, + &self.hostname, + &self.opt_domains, + &self.opt_not_domains, ) } + #[deprecated(since = "0.11.2", note = "use get_id_without_badfilter instead")] pub fn get_id(&self) -> Hash { compute_filter_id( - self.modifier_option.as_deref(), - self.mask, - self.filter.string_view().as_deref(), - self.hostname.as_deref(), - self.opt_domains.as_ref(), - self.opt_not_domains.as_ref(), + &self.modifier_option, + self.mask.bits(), + &self.filter, + &self.hostname, + &self.opt_domains, + &self.opt_not_domains, ) } @@ -1021,50 +1020,61 @@ impl NetworkMatchable for NetworkFilter { // Filter parsing // --------------------------------------------------------------------------- +#[inline] fn compute_filter_id( - modifier_option: Option<&str>, - mask: NetworkFilterMask, - filter: Option<&str>, - hostname: Option<&str>, - opt_domains: Option<&Vec>, - opt_not_domains: Option<&Vec>, + modifier_option: &Option, + mask: u32, + filter: &FilterPart, + hostname: &Option, + opt_domains: &Option>, + opt_not_domains: &Option>, ) -> Hash { - let mut hash: Hash = (5408 * 33) ^ Hash::from(mask.bits()); + use rustc_hash::FxHasher; + use std::hash::Hasher; + + let mut hasher = FxHasher::default(); + // Hash the mask first + hasher.write_u32(mask); + + // Hash modifier_option if let Some(s) = modifier_option { - let chars = s.chars(); - for c in chars { - hash = hash.wrapping_mul(33) ^ (c as Hash); - } - }; + hasher.write(s.as_bytes()); + } + // Hash domains if let Some(domains) = opt_domains { - for d in domains { - hash = hash.wrapping_mul(33) ^ d; + hasher.write_u32(domains.len() as u32); + for &d in domains { + hasher.write_u64(d); } - }; + } + // Hash not_domains if let Some(domains) = opt_not_domains { - for d in domains { - hash = hash.wrapping_mul(33) ^ d; + hasher.write_u32(domains.len() as u32); + for &d in domains { + hasher.write_u64(d); } } - - if let Some(s) = filter { - let chars = s.chars(); - for c in chars { - hash = hash.wrapping_mul(33) ^ (c as Hash); + // Hash filter + if let FilterPart::Simple(s) = filter { + hasher.write(s.as_bytes()); + } else if let FilterPart::AnyOf(s) = filter { + for d in s { + hasher.write(d.as_bytes()); + hasher.write_u8(0); } + } else { + hasher.write_u32(0); } + // Hash hostname if let Some(s) = hostname { - let chars = s.chars(); - for c in chars { - hash = hash.wrapping_mul(33) ^ (c as Hash); - } + hasher.write(s.as_bytes()); } - hash + hasher.finish() } /// Check if the sub-string contained between the indices start and end is a diff --git a/src/lists.rs b/src/lists.rs index 857b41e8..fcd82720 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -307,7 +307,8 @@ impl FilterSet { self.network_filters.into_iter().for_each(|filter| { // Don't process bad filter rules or matching bad filter rules. - if bad_filter_ids.contains(&filter.get_id()) || filter.is_badfilter() { + if bad_filter_ids.contains(&filter.get_id_without_badfilter()) || filter.is_badfilter() + { return; } let original_rule = *filter