Skip to content

Commit cacfcc6

Browse files
committed
Added EngineSerializer trait
1 parent cbbcb10 commit cacfcc6

18 files changed

+215
-138
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ harness = false
8080
name = "bench_memory"
8181
harness = false
8282

83+
[[bench]]
84+
name = "bench_serialization"
85+
harness = false
86+
8387
# Currently disabled, as cosmetic filter internals
8488
# are no longer part of the crate's public API
8589
#[[bench]]

benches/bench_matching.rs

-77
Original file line numberDiff line numberDiff line change
@@ -205,81 +205,6 @@ fn rule_match_parsed_elep_slimlist(c: &mut Criterion) {
205205
group.finish();
206206
}
207207

208-
fn serialization(c: &mut Criterion) {
209-
let mut group = c.benchmark_group("blocker-serialization");
210-
211-
group.sample_size(20);
212-
213-
group.bench_function("el+ep", move |b| {
214-
let full_rules = rules_from_lists(&[
215-
"data/easylist.to/easylist/easylist.txt",
216-
"data/easylist.to/easylist/easyprivacy.txt",
217-
]);
218-
219-
let engine = Engine::from_rules(full_rules, Default::default());
220-
b.iter(|| assert!(engine.serialize_raw().unwrap().len() > 0))
221-
});
222-
group.bench_function("el", move |b| {
223-
let full_rules = rules_from_lists(&["data/easylist.to/easylist/easylist.txt"]);
224-
225-
let engine = Engine::from_rules(full_rules, Default::default());
226-
b.iter(|| assert!(engine.serialize_raw().unwrap().len() > 0))
227-
});
228-
group.bench_function("slimlist", move |b| {
229-
let full_rules = rules_from_lists(&["data/slim-list.txt"]);
230-
231-
let engine = Engine::from_rules(full_rules, Default::default());
232-
b.iter(|| assert!(engine.serialize_raw().unwrap().len() > 0))
233-
});
234-
235-
group.finish();
236-
}
237-
238-
fn deserialization(c: &mut Criterion) {
239-
let mut group = c.benchmark_group("blocker-deserialization");
240-
241-
group.sample_size(20);
242-
243-
group.bench_function("el+ep", move |b| {
244-
let full_rules = rules_from_lists(&[
245-
"data/easylist.to/easylist/easylist.txt",
246-
"data/easylist.to/easylist/easyprivacy.txt",
247-
]);
248-
249-
let engine = Engine::from_rules(full_rules, Default::default());
250-
let serialized = engine.serialize_raw().unwrap();
251-
252-
b.iter(|| {
253-
let mut deserialized = Engine::default();
254-
assert!(deserialized.deserialize(&serialized).is_ok());
255-
})
256-
});
257-
group.bench_function("el", move |b| {
258-
let full_rules = rules_from_lists(&["data/easylist.to/easylist/easylist.txt"]);
259-
260-
let engine = Engine::from_rules(full_rules, Default::default());
261-
let serialized = engine.serialize_raw().unwrap();
262-
263-
b.iter(|| {
264-
let mut deserialized = Engine::default();
265-
assert!(deserialized.deserialize(&serialized).is_ok());
266-
})
267-
});
268-
group.bench_function("slimlist", move |b| {
269-
let full_rules = rules_from_lists(&["data/slim-list.txt"]);
270-
271-
let engine = Engine::from_rules(full_rules, Default::default());
272-
let serialized = engine.serialize_raw().unwrap();
273-
274-
b.iter(|| {
275-
let mut deserialized = Engine::default();
276-
assert!(deserialized.deserialize(&serialized).is_ok());
277-
})
278-
});
279-
280-
group.finish();
281-
}
282-
283208
fn rule_match_browserlike_comparable(c: &mut Criterion) {
284209
let mut group = c.benchmark_group("rule-match-browserlike");
285210

@@ -395,7 +320,5 @@ criterion_group!(
395320
rule_match_parsed_elep_slimlist,
396321
rule_match_browserlike_comparable,
397322
rule_match_first_request,
398-
serialization,
399-
deserialization
400323
);
401324
criterion_main!(benches);

benches/bench_serialization.rs

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use criterion::*;
2+
3+
use adblock::{Engine, EngineSerializer};
4+
5+
#[path = "../tests/test_utils.rs"]
6+
mod test_utils;
7+
use test_utils::rules_from_lists;
8+
9+
fn serialization(c: &mut Criterion) {
10+
let mut group = c.benchmark_group("blocker-serialization");
11+
12+
group.sample_size(20);
13+
14+
group.bench_function("el+ep", move |b| {
15+
let full_rules = rules_from_lists(&[
16+
"data/easylist.to/easylist/easylist.txt",
17+
"data/easylist.to/easylist/easyprivacy.txt",
18+
]);
19+
20+
let engine = Engine::from_rules(full_rules, Default::default());
21+
b.iter(|| assert!(engine.serialize_raw().unwrap().len() > 0))
22+
});
23+
group.bench_function("el", move |b| {
24+
let full_rules = rules_from_lists(&["data/easylist.to/easylist/easylist.txt"]);
25+
26+
let engine = Engine::from_rules(full_rules, Default::default());
27+
b.iter(|| assert!(engine.serialize_raw().unwrap().len() > 0))
28+
});
29+
group.bench_function("slimlist", move |b| {
30+
let full_rules = rules_from_lists(&["data/slim-list.txt"]);
31+
32+
let engine = Engine::from_rules(full_rules, Default::default());
33+
b.iter(|| assert!(engine.serialize_raw().unwrap().len() > 0))
34+
});
35+
36+
group.finish();
37+
}
38+
39+
fn deserialization(c: &mut Criterion) {
40+
let mut group = c.benchmark_group("blocker-deserialization");
41+
42+
group.sample_size(20);
43+
44+
group.bench_function("el+ep", move |b| {
45+
let full_rules = rules_from_lists(&[
46+
"data/easylist.to/easylist/easylist.txt",
47+
"data/easylist.to/easylist/easyprivacy.txt",
48+
]);
49+
50+
let engine = Engine::from_rules(full_rules, Default::default());
51+
let serialized = engine.serialize_raw().unwrap();
52+
53+
b.iter(|| {
54+
let mut deserialized = Engine::default();
55+
assert!(deserialized.deserialize(&serialized).is_ok());
56+
})
57+
});
58+
group.bench_function("el", move |b| {
59+
let full_rules = rules_from_lists(&["data/easylist.to/easylist/easylist.txt"]);
60+
61+
let engine = Engine::from_rules(full_rules, Default::default());
62+
let serialized = engine.serialize_raw().unwrap();
63+
64+
b.iter(|| {
65+
let mut deserialized = Engine::default();
66+
assert!(deserialized.deserialize(&serialized).is_ok());
67+
})
68+
});
69+
group.bench_function("slimlist", move |b| {
70+
let full_rules = rules_from_lists(&["data/slim-list.txt"]);
71+
72+
let engine = Engine::from_rules(full_rules, Default::default());
73+
let serialized = engine.serialize_raw().unwrap();
74+
75+
b.iter(|| {
76+
let mut deserialized = Engine::default();
77+
assert!(deserialized.deserialize(&serialized).is_ok());
78+
})
79+
});
80+
81+
group.finish();
82+
}
83+
84+
criterion_group!(benches, serialization, deserialization);
85+
criterion_main!(benches);

examples/deserialization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use adblock::{request::Request, Engine};
1+
use adblock::{request::Request, Engine, EngineSerializer};
22

33
use serde::Deserialize;
44

examples/generate-dat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use adblock::{request::Request, Engine};
1+
use adblock::{request::Request, Engine, EngineSerializer};
22

33
use std::fs::File;
44
use std::io::prelude::*;

examples/use-dat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use adblock::{request::Request, Engine};
1+
use adblock::{request::Request, Engine, EngineSerializer};
22

33
use std::fs::File;
44
use std::io::prelude::*;

js/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::cell::RefCell;
55
use std::sync::Mutex;
66
use std::path::Path;
77
use adblock::Engine as EngineInternal;
8+
use adblock::EngineSerializer as EngineSerializerInternal;
89
use adblock::lists::{RuleTypes, FilterFormat, FilterListMetadata, FilterSet as FilterSetInternal, ParseOptions};
910
use adblock::resources::Resource;
1011
use adblock::resources::resource_assembler::assemble_web_accessible_resources;

src/data_format/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
//! serialization/deserialization implementations and can automatically dispatch to the appropriate
66
//! one.
77
8+
#![allow(dead_code)]
9+
810
mod v0;
911

1012
pub(crate) mod utils;

src/engine.rs

+2-28
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ use std::collections::HashSet;
4343
/// [`Engine::hidden_class_id_selectors`] on an ongoing basis to determine additional elements that
4444
/// should be hidden dynamically.
4545
pub struct Engine {
46-
blocker: Blocker,
47-
cosmetic_cache: CosmeticFilterCache,
46+
pub(crate) blocker: Blocker,
47+
pub(crate) cosmetic_cache: CosmeticFilterCache,
4848
resources: ResourceStorage,
4949
}
5050

@@ -121,32 +121,6 @@ impl Engine {
121121
}
122122
}
123123

124-
/// Serializes the `Engine` into a binary format so that it can be quickly reloaded later.
125-
pub fn serialize_raw(&self) -> Result<Vec<u8>, crate::data_format::SerializationError> {
126-
use crate::data_format::SerializeFormat;
127-
128-
let serialize_format = SerializeFormat::build(&self.blocker, &self.cosmetic_cache);
129-
130-
serialize_format.serialize()
131-
}
132-
133-
/// Deserialize the `Engine` from the binary format generated by `Engine::serialize_raw`. The
134-
/// method will automatically select the correct deserialization implementation.
135-
pub fn deserialize(
136-
&mut self,
137-
serialized: &[u8],
138-
) -> Result<(), crate::data_format::DeserializationError> {
139-
use crate::data_format::DeserializeFormat;
140-
let current_tags = self.blocker.tags_enabled();
141-
let deserialize_format = DeserializeFormat::deserialize(serialized)?;
142-
let (blocker, cosmetic_cache) = deserialize_format.build();
143-
self.blocker = blocker;
144-
self.blocker
145-
.use_tags(&current_tags.iter().map(|s| &**s).collect::<Vec<_>>());
146-
self.cosmetic_cache = cosmetic_cache;
147-
Ok(())
148-
}
149-
150124
/// Check if a request for a network resource from `url`, of type `request_type`, initiated by
151125
/// `source_url`, should be blocked.
152126
pub fn check_network_request(&self, request: &Request) -> BlockerResult {

src/engine_serializer.rs

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use crate::engine::Engine;
2+
3+
#[derive(Debug)]
4+
#[cfg(not(feature = "flatbuffers-storage"))]
5+
pub enum SerializeError {
6+
DataFormatError(crate::data_format::SerializationError),
7+
}
8+
9+
#[derive(Debug)]
10+
#[cfg(feature = "flatbuffers-storage")]
11+
pub enum SerializeError {
12+
FlatbuffersError(),
13+
}
14+
15+
#[derive(Debug)]
16+
#[cfg(not(feature = "flatbuffers-storage"))]
17+
pub enum DeserializeError {
18+
DataFormatError(crate::data_format::DeserializationError),
19+
}
20+
21+
#[derive(Debug)]
22+
#[cfg(feature = "flatbuffers-storage")]
23+
pub enum DeserializeError {
24+
FlatbuffersError(),
25+
}
26+
27+
#[cfg(not(feature = "flatbuffers-storage"))]
28+
impl From<crate::data_format::SerializationError> for SerializeError {
29+
fn from(value: crate::data_format::SerializationError) -> Self {
30+
SerializeError::DataFormatError(value)
31+
}
32+
}
33+
34+
#[cfg(not(feature = "flatbuffers-storage"))]
35+
impl From<crate::data_format::DeserializationError> for DeserializeError {
36+
fn from(value: crate::data_format::DeserializationError) -> Self {
37+
DeserializeError::DataFormatError(value)
38+
}
39+
}
40+
41+
pub trait EngineSerializer {
42+
fn serialize_raw(&self) -> Result<Vec<u8>, SerializeError>;
43+
fn deserialize(&mut self, serialized: &[u8]) -> Result<(), DeserializeError>;
44+
}
45+
46+
#[cfg(feature = "flatbuffers-storage")]
47+
impl EngineSerializer for Engine {
48+
fn serialize_raw(&self) -> Result<Vec<u8>, SerializeError> {
49+
Err(SerializeError::FlatbuffersError())
50+
}
51+
52+
fn deserialize(&mut self, _serialized: &[u8]) -> Result<(), DeserializeError> {
53+
Err(DeserializeError::FlatbuffersError())
54+
}
55+
}
56+
57+
#[cfg(not(feature = "flatbuffers-storage"))]
58+
impl EngineSerializer for Engine {
59+
/// Serializes the `Engine` into a binary format so that it can be quickly reloaded later.
60+
fn serialize_raw(&self) -> Result<Vec<u8>, SerializeError> {
61+
use crate::data_format::SerializeFormat;
62+
63+
let serialize_format = SerializeFormat::build(&self.blocker, &self.cosmetic_cache);
64+
65+
let result = serialize_format.serialize()?;
66+
Ok(result)
67+
}
68+
69+
/// Deserialize the `Engine` from the binary format generated by `Engine::serialize_raw`. The
70+
/// method will automatically select the correct deserialization implementation.
71+
fn deserialize(&mut self, serialized: &[u8]) -> Result<(), DeserializeError> {
72+
use crate::data_format::DeserializeFormat;
73+
let current_tags = self.blocker.tags_enabled();
74+
let deserialize_format = DeserializeFormat::deserialize(serialized)?;
75+
let (blocker, cosmetic_cache) = deserialize_format.build();
76+
self.blocker = blocker;
77+
self.blocker
78+
.use_tags(&current_tags.iter().map(|s| &**s).collect::<Vec<_>>());
79+
self.cosmetic_cache = cosmetic_cache;
80+
Ok(())
81+
}
82+
}

src/flat_network_filter_list.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl NetworkFilterListTrait for FlatNetworkFilterList {
7272

7373
if optimize {
7474
for (token, v) in optimizable {
75-
let optimized = optimizer::optimize_by_groupping_patterns(v);
75+
let optimized = optimizer::optimize(v);
7676

7777
for filter in optimized {
7878
let index = flat_builder.add(&filter);

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub mod content_blocking;
2222
pub mod cosmetic_filter_cache;
2323
mod data_format;
2424
mod engine;
25+
mod engine_serializer;
2526
pub mod filters;
2627
pub mod lists;
2728
mod network_filter_list;
@@ -39,6 +40,7 @@ pub mod utils;
3940

4041
#[doc(inline)]
4142
pub use engine::Engine;
43+
pub use engine_serializer::EngineSerializer;
4244
#[doc(inline)]
4345
pub use lists::FilterSet;
4446

src/optimizer.rs

-15
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,6 @@ pub fn is_filter_optimizable_by_patterns(filter: &NetworkFilter) -> bool {
1818
&& !filter.is_csp()
1919
}
2020

21-
pub fn optimize_by_groupping_patterns(filters: Vec<NetworkFilter>) -> Vec<NetworkFilter> {
22-
let mut optimized: Vec<NetworkFilter> = Vec::new();
23-
24-
let simple_pattern_group = SimplePatternGroup {};
25-
let (mut fused, mut unfused) = apply_optimisation(&simple_pattern_group, filters);
26-
optimized.append(&mut fused);
27-
28-
// Append whatever is still left unfused
29-
optimized.append(&mut unfused);
30-
31-
// Re-sort the list, now that the order has been perturbed
32-
optimized.sort_by_key(|f| f.id);
33-
optimized
34-
}
35-
3621
/// Fuse `NetworkFilter`s together by applying optimizations sequentially.
3722
pub fn optimize(filters: Vec<NetworkFilter>) -> Vec<NetworkFilter> {
3823
let mut optimized: Vec<NetworkFilter> = Vec::new();

0 commit comments

Comments
 (0)