Skip to content

Commit

Permalink
feat: normal match repeated pattern
Browse files Browse the repository at this point in the history
This commit adds a feature which allows the normal matcher to match
paths like `/:file.gz` or `/:lib.js.gz`

Previously this would have found no routes on paths like
`/node.js.gz`

Now `/:file.gz` matches `/node.js.gz` where "name" => "node.js"
And `/:lib.js.gz` matches `/node.js.gz` where "lib" => "node"

Which to me seems like the correct result in these cases.

fixes: #36
  • Loading branch information
TroyKomodo committed Jan 1, 2024
1 parent d91a7f1 commit bed678c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 5 deletions.
31 changes: 26 additions & 5 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,33 @@ impl<T: fmt::Debug> Node<T> {
if let Some(id) = self.nodes0.as_ref().and_then(|nodes| {
nodes.iter().find_map(|node| match &node.key {
Key::String(s) => {
bytes.iter().position(|b| s[0] == *b).and_then(|n| {
node._find(start + n, &bytes[n..], ranges).map(|id| {
ranges.push(start..start + n);
id
let mut keep_running = true;
bytes
.iter()
// as it turns out doing .copied() here is much slower than dereferencing in the closure
// https://godbolt.org/z/7dnW91T1Y
.take_while(|b| {
if **b == b'/' && keep_running {
keep_running = false;
true
} else {
keep_running
}
})
.enumerate()
.filter_map(
|(idx, b)| if s[0] == *b { Some(idx) } else { None },
)
.find_map(|n| {
let found = node
._find(start + n, &bytes[n..], ranges)
.map(|id| {
ranges.push(start..start + n);
id
});

found
})
})
}
Key::Parameter(_) => unreachable!(),
})
Expand Down
47 changes: 47 additions & 0 deletions tests/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2257,3 +2257,50 @@ fn test_dots_ext() {

assert_eq!(params.params(), &[("name", "abc.xyz")]);
}

#[test]
fn test_dots_ext_no_qualifier() {
let mut tree = PathTree::new();
let _ = tree.insert("/:name.js", 2);
let _ = tree.insert("/:name.js.gz", 1);

let result = tree.find("/node.js");
assert!(result.is_some());

let (value, params) = result.unwrap();
assert_eq!(value, &2);

assert_eq!(params.params(), &[("name", "node")]);

let result = tree.find("/path.lib.js");
assert!(result.is_some());

let (value, params) = result.unwrap();
assert_eq!(value, &2);

assert_eq!(params.params(), &[("name", "path.lib")]);

let result = tree.find("/node.js.js");
assert!(result.is_some());

let (value, params) = result.unwrap();
assert_eq!(value, &2);

assert_eq!(params.params(), &[("name", "node.js")]);

let result = tree.find("/node.js.gz");
assert!(result.is_some());

let (value, params) = result.unwrap();
assert_eq!(value, &1);

assert_eq!(params.params(), &[("name", "node")]);

let result = tree.find("/node.js.gz.js.gz");
assert!(result.is_some());

let (value, params) = result.unwrap();
assert_eq!(value, &1);

assert_eq!(params.params(), &[("name", "node.js.gz")]);
}

0 comments on commit bed678c

Please sign in to comment.