Skip to content

Commit 204a083

Browse files
committed
feat(libredirectionio): simplify router implementation
1 parent e10b125 commit 204a083

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1100
-4238
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ percent-encoding = "2.3.0"
4141
rand = "0.8.5"
4242
regex = "1.9.5"
4343
scraper = "0.17.1"
44-
serde = { version = "1.0", features = ["derive"] }
44+
serde = { version = "1.0", features = ["derive", "rc"] }
4545
serde_json = "1.0.107"
4646
stderrlog = "0.5.4"
4747
tracing = "0.1.37"

benches/filter_body_benchmark.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use redirectionio::api::Rule;
99
use redirectionio::http::{Header, Request};
1010
use redirectionio::router::RouterConfig;
1111
use std::io::Write;
12+
use std::sync::Arc;
1213

1314
pub const STATIC_SMALL_BODY: &str = r##"<html><body><p>hello world</p></body></html>"##;
1415

@@ -58,7 +59,7 @@ fn filter_body_inject_html_append(c: &mut Criterion) {
5859
.unwrap()
5960
.into_route(&config);
6061
let request = Request::from_config(&config, "/".to_string(), None, None, None, None, None);
61-
let action = if let (Some(action), _, _, _) = Action::from_route_rule(&rule, &request) {
62+
let action = if let (Some(action), _, _, _) = Action::from_route_rule(Arc::new(rule), &request) {
6263
action
6364
} else {
6465
panic!("Cannot create action");
@@ -115,7 +116,7 @@ fn filter_body_inject_html_prepend(c: &mut Criterion) {
115116
.unwrap()
116117
.into_route(&config);
117118
let request = Request::from_config(&config, "/".to_string(), None, None, None, None, None);
118-
let action = if let (Some(action), _, _, _) = Action::from_route_rule(&rule, &request) {
119+
let action = if let (Some(action), _, _, _) = Action::from_route_rule(Arc::new(rule), &request) {
119120
action
120121
} else {
121122
panic!("Cannot create action");
@@ -174,7 +175,7 @@ fn filter_body_inject_html_append_gzip(c: &mut Criterion) {
174175
.unwrap()
175176
.into_route(&config);
176177
let request = Request::from_config(&config, "/".to_string(), None, None, None, None, None);
177-
let action = if let (Some(action), _, _, _) = Action::from_route_rule(&rule, &request) {
178+
let action = if let (Some(action), _, _, _) = Action::from_route_rule(Arc::new(rule), &request) {
178179
action
179180
} else {
180181
panic!("Cannot create action");

src/action/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub use status_code_update::StatusCodeUpdate;
2525
use std::collections::HashMap;
2626
use std::fmt::Debug;
2727
use std::iter::FromIterator;
28+
use std::sync::Arc;
2829
#[cfg(feature = "router")]
2930
pub use trace::TraceAction;
3031

@@ -207,7 +208,7 @@ impl Action {
207208
}
208209

209210
#[cfg(feature = "router")]
210-
pub fn from_route_rule(route: &Route<Rule>, request: &Request) -> (Option<Action>, bool, bool, Option<String>) {
211+
pub fn from_route_rule(route: Arc<Route<Rule>>, request: &Request) -> (Option<Action>, bool, bool, Option<String>) {
211212
let markers_captured = route.capture(request);
212213
let variables = route.handler().variables(&markers_captured, request);
213214
let rule = route.handler();
@@ -426,7 +427,7 @@ impl Action {
426427
}
427428

428429
#[cfg(feature = "router")]
429-
pub fn from_routes_rule(mut routes: Vec<&Route<Rule>>, request: &Request, mut unit_trace: Option<&mut UnitTrace>) -> Action {
430+
pub fn from_routes_rule(mut routes: Vec<Arc<Route<Rule>>>, request: &Request, mut unit_trace: Option<&mut UnitTrace>) -> Action {
430431
let mut action = Action::default();
431432

432433
routes.sort();

src/action/trace.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ impl TraceAction {
1717
let mut routes = Trace::<Rule>::get_routes_from_traces(traces);
1818

1919
// Reverse order of sort
20-
routes.sort_by_key(|&a| a.priority());
20+
routes.sort_by_key(|a| a.priority());
2121

2222
for route in routes {
23-
let (action_rule_opt, reset, stop, _) = Action::from_route_rule(route, request);
23+
let (action_rule_opt, reset, stop, _) = Action::from_route_rule(route.clone(), request);
2424

2525
if let Some(action_rule) = action_rule_opt {
2626
if reset {

src/api/rule.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::api::{BodyFilter, DateTimeConstraint, Example, HeaderFilter, IpConstraint, Marker, Source, Variable};
22
use crate::http::Request;
33
use crate::marker::{Marker as RouteMarker, MarkerString, StaticOrDynamic, Transform};
4-
use crate::router::{Route, RouteData, RouteDateTime, RouteHeader, RouteHeaderKind, RouteIp, RouteTime, RouteWeekday, RouterConfig};
4+
use crate::router::{Route, RouteDateTime, RouteHeader, RouteHeaderKind, RouteIp, RouteTime, RouteWeekday, RouterConfig};
55
use cidr::AnyIpCidr;
66
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
77
use serde::{Deserialize, Serialize};
@@ -37,8 +37,6 @@ pub struct Rule {
3737
pub target_hash: Option<String>,
3838
}
3939

40-
impl RouteData for Rule {}
41-
4240
impl Ord for Rule {
4341
fn cmp(&self, other: &Self) -> Ordering {
4442
let order_on_rank = other.rank.cmp(&self.rank);

src/ffi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub unsafe extern "C" fn redirectionio_router_create(
2121
match serde_json::from_str(str) {
2222
Ok(value) => value,
2323
Err(error) => {
24-
error!("Unable to deserialize router config: {}", error,);
24+
error!("Unable to deserialize router_old config: {}", error,);
2525

2626
RouterConfig::default()
2727
}

src/filter/filter_body.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -216,33 +216,8 @@ mod tests {
216216
use flate2::Compression;
217217
use std::io::prelude::*;
218218

219-
fn init_logger() {
220-
struct Logger;
221-
static LOGGER: Logger = Logger;
222-
223-
impl log::Log for Logger {
224-
fn enabled(&self, _metadata: &log::Metadata) -> bool {
225-
true
226-
}
227-
228-
fn log(&self, record: &log::Record) {
229-
println!("{}", record.args());
230-
}
231-
232-
fn flush(&self) {}
233-
}
234-
235-
// If it fails, that just means we've already set it to the same value.
236-
let _ = log::set_logger(&LOGGER);
237-
log::set_max_level(log::LevelFilter::Trace);
238-
239-
println!();
240-
}
241-
242219
#[test]
243220
pub fn test_filter_gzip() {
244-
init_logger();
245-
246221
let decompressed_input = "<html><head></head><body class=\"page\"><div>Yolo</div></body></html>".to_string();
247222
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
248223
encoder.write_all(decompressed_input.as_bytes()).unwrap();
@@ -296,8 +271,6 @@ mod tests {
296271

297272
#[test]
298273
pub fn test_filter_deflate() {
299-
init_logger();
300-
301274
let decompressed_input = "<html><head></head><body class=\"page\"><div>Yolo</div></body></html>".to_string();
302275
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
303276
encoder.write_all(decompressed_input.as_bytes()).unwrap();
@@ -351,8 +324,6 @@ mod tests {
351324

352325
#[test]
353326
pub fn test_filter_brotli() {
354-
init_logger();
355-
356327
let decompressed_input = "<html><head><h2>This is stupide data to ensure compression before</H2></head><body class=\"page\"><div>Yolo</div></body></html>".to_string();
357328
let mut compressed_input = Vec::new();
358329
let mut reader = brotli::CompressorReader::new(decompressed_input.as_bytes(), 4096, 11, 22);

src/http/query.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ mod tests {
140140
let sanitized = sanitize_url(path);
141141
let url = sanitized.parse::<PathAndQuery>();
142142

143-
println!("{:#?}", url);
144-
145143
assert!(url.is_ok());
146144
}
147145

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,3 @@ mod callback_log;
2525
mod ffi;
2626
#[cfg(not(target_arch = "wasm32"))]
2727
mod ffi_helpers;
28-
mod regex_radix_tree_new;
29-
mod router_new;

src/regex_radix_tree/item.rs

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,119 @@
1-
use std::fmt::Debug;
1+
use super::leaf::Leaf;
2+
use super::node::Node;
23

3-
/// Represent an item added to the regex radix tree
4-
pub trait NodeItem: Debug + Clone + Send + Sync + 'static {
5-
/// Return the regex used by this item
4+
#[derive(Debug)]
5+
pub enum Item<V> {
6+
Empty(bool),
7+
Node(Node<V>),
8+
Leaf(Leaf<V>),
9+
}
10+
11+
impl<V> Clone for Item<V>
12+
where
13+
V: Clone,
14+
{
15+
fn clone(&self) -> Self {
16+
match self {
17+
Item::Empty(ignore_case) => Item::Empty(*ignore_case),
18+
Item::Node(node) => Item::Node(node.clone()),
19+
Item::Leaf(leaf) => Item::Leaf(leaf.clone()),
20+
}
21+
}
22+
}
23+
24+
impl<V> Item<V> {
25+
/// Insert a new item into this node
26+
pub fn insert(self, regex: &str, id: String, item: V) -> Item<V> {
27+
match self {
28+
Item::Empty(ignore_case) => Item::Leaf(Leaf::new(regex, id, item, ignore_case)),
29+
Item::Node(node) => node.insert(regex, id, item),
30+
Item::Leaf(leaf) => leaf.insert(regex, id, item),
31+
}
32+
}
33+
34+
/// Find values associated to this haystack
35+
pub fn find(&self, haystack: &str) -> Vec<&V> {
36+
match self {
37+
Item::Empty(_) => Vec::new(),
38+
Item::Node(node) => node.find(haystack),
39+
Item::Leaf(leaf) => leaf.find(haystack),
40+
}
41+
}
42+
43+
pub fn get(&self, regex: &str) -> Vec<&V> {
44+
match self {
45+
Item::Empty(_) => Vec::new(),
46+
Item::Node(node) => node.get(regex),
47+
Item::Leaf(leaf) => leaf.get(regex),
48+
}
49+
}
50+
51+
pub fn get_mut(&mut self, regex: &str) -> Vec<&mut V> {
52+
match self {
53+
Item::Empty(_) => Vec::new(),
54+
Item::Node(node) => node.get_mut(regex),
55+
Item::Leaf(leaf) => leaf.get_mut(regex),
56+
}
57+
}
58+
59+
/// Remove an item on this tree
660
///
7-
/// Regex should not contains `^` at the start and `$` at the end, those are inserted for you
8-
/// automatically
9-
fn regex(&self) -> &str;
61+
/// This method returns true if there is no more data so it can be cleaned up
62+
pub fn remove(self, id: &str) -> (Self, Option<V>) {
63+
match self {
64+
Item::Empty(_) => (self, None),
65+
Item::Node(node) => node.remove(id),
66+
Item::Leaf(leaf) => leaf.remove(id),
67+
}
68+
}
69+
70+
/// Length of node
71+
pub fn len(&self) -> usize {
72+
match self {
73+
Item::Empty(_) => 0,
74+
Item::Node(node) => node.len(),
75+
Item::Leaf(leaf) => leaf.len(),
76+
}
77+
}
78+
79+
pub fn regex(&self) -> &str {
80+
match self {
81+
Item::Empty(_) => "",
82+
Item::Node(node) => node.regex(),
83+
Item::Leaf(leaf) => leaf.regex(),
84+
}
85+
}
86+
87+
/// Cache current regex according to a limit and a level
88+
///
89+
/// This method must return new limit of element cached (passed limit minus number of element cached)
90+
/// which allow other node to avoid caching extra node
91+
///
92+
/// Implementation must not cache item if limit is equal to 0
93+
/// Implementation must not cache item if not caching on the current node level
94+
///
95+
/// Level argument allow to build cache on first level of the tree by priority
96+
/// Implementation must retain at which level this node is build and not do any caching
97+
/// if we are not on the current level
98+
pub fn cache(&mut self, left: u64, cache_level: u64, current_level: u64) -> u64 {
99+
if left <= 0 {
100+
return left;
101+
}
102+
103+
if current_level > cache_level {
104+
return left;
105+
}
10106

11-
/// Should the regex be case insensitive
12-
fn case_insensitive(&self) -> bool;
107+
match self {
108+
Item::Empty(_) => left,
109+
Item::Node(node) => node.cache(left, cache_level, current_level),
110+
Item::Leaf(leaf) => {
111+
if cache_level == current_level {
112+
leaf.cache(left)
113+
} else {
114+
left
115+
}
116+
}
117+
}
118+
}
13119
}

0 commit comments

Comments
 (0)