From 5037ff99979ace82483a502ee0271817efa5037c Mon Sep 17 00:00:00 2001 From: Mikhail Atuchin Date: Wed, 12 Nov 2025 20:31:11 +0400 Subject: [PATCH 1/2] deprecated NetworkFilter::get_id() --- src/filters/fb_network_builder.rs | 2 +- src/filters/network.rs | 11 +++++------ src/lists.rs | 3 ++- 3 files changed, 8 insertions(+), 8 deletions(-) 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..87f63587 100644 --- a/src/filters/network.rs +++ b/src/filters/network.rs @@ -860,11 +860,9 @@ 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.mask.bits() & !NetworkFilterMask::BAD_FILTER.bits(), self.filter.string_view().as_deref(), self.hostname.as_deref(), self.opt_domains.as_ref(), @@ -872,10 +870,11 @@ impl NetworkFilter { ) } + #[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.mask.bits(), self.filter.string_view().as_deref(), self.hostname.as_deref(), self.opt_domains.as_ref(), @@ -1023,13 +1022,13 @@ impl NetworkMatchable for NetworkFilter { fn compute_filter_id( modifier_option: Option<&str>, - mask: NetworkFilterMask, + mask: u32, filter: Option<&str>, hostname: Option<&str>, opt_domains: Option<&Vec>, opt_not_domains: Option<&Vec>, ) -> Hash { - let mut hash: Hash = (5408 * 33) ^ Hash::from(mask.bits()); + let mut hash: Hash = (5408 * 33) ^ Hash::from(mask); if let Some(s) = modifier_option { let chars = s.chars(); 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 From 8ece8d0f491cd9887f41dee534e017d8889a4042 Mon Sep 17 00:00:00 2001 From: Mikhail Atuchin Date: Wed, 12 Nov 2025 21:29:00 +0400 Subject: [PATCH 2/2] Use a hasher for compute_filter_id --- src/filters/network.rs | 83 ++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/src/filters/network.rs b/src/filters/network.rs index 87f63587..0051175b 100644 --- a/src/filters/network.rs +++ b/src/filters/network.rs @@ -861,24 +861,24 @@ impl NetworkFilter { pub fn get_id_without_badfilter(&self) -> Hash { compute_filter_id( - self.modifier_option.as_deref(), + &self.modifier_option, self.mask.bits() & !NetworkFilterMask::BAD_FILTER.bits(), - self.filter.string_view().as_deref(), - self.hostname.as_deref(), - self.opt_domains.as_ref(), - self.opt_not_domains.as_ref(), + &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.modifier_option, self.mask.bits(), - self.filter.string_view().as_deref(), - self.hostname.as_deref(), - self.opt_domains.as_ref(), - self.opt_not_domains.as_ref(), + &self.filter, + &self.hostname, + &self.opt_domains, + &self.opt_not_domains, ) } @@ -1020,50 +1020,61 @@ impl NetworkMatchable for NetworkFilter { // Filter parsing // --------------------------------------------------------------------------- +#[inline] fn compute_filter_id( - modifier_option: Option<&str>, + modifier_option: &Option, mask: u32, - filter: Option<&str>, - hostname: Option<&str>, - opt_domains: Option<&Vec>, - opt_not_domains: Option<&Vec>, + filter: &FilterPart, + hostname: &Option, + opt_domains: &Option>, + opt_not_domains: &Option>, ) -> Hash { - let mut hash: Hash = (5408 * 33) ^ Hash::from(mask); + 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