Skip to content

Commit 0f173ea

Browse files
committed
feat: normal match repeated pattern
This commit adds a feature which allows the normal matcher 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
1 parent d91a7f1 commit 0f173ea

File tree

2 files changed

+73
-5
lines changed

2 files changed

+73
-5
lines changed

src/node.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,33 @@ impl<T: fmt::Debug> Node<T> {
285285
if let Some(id) = self.nodes0.as_ref().and_then(|nodes| {
286286
nodes.iter().find_map(|node| match &node.key {
287287
Key::String(s) => {
288-
bytes.iter().position(|b| s[0] == *b).and_then(|n| {
289-
node._find(start + n, &bytes[n..], ranges).map(|id| {
290-
ranges.push(start..start + n);
291-
id
288+
let mut keep_running = true;
289+
bytes
290+
.iter()
291+
// as it turns out doing .copied() here is much slower than dereferencing in the closure
292+
// https://godbolt.org/z/7dnW91T1Y
293+
.take_while(|b| {
294+
if **b == b'/' && keep_running {
295+
keep_running = false;
296+
true
297+
} else {
298+
keep_running
299+
}
300+
})
301+
.enumerate()
302+
.filter_map(
303+
|(idx, b)| if s[0] == *b { Some(idx) } else { None },
304+
)
305+
.find_map(|n| {
306+
let found = node
307+
._find(start + n, &bytes[n..], ranges)
308+
.map(|id| {
309+
ranges.push(start..start + n);
310+
id
311+
});
312+
313+
found
292314
})
293-
})
294315
}
295316
Key::Parameter(_) => unreachable!(),
296317
})

tests/tree.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,3 +2257,50 @@ fn test_dots_ext() {
22572257

22582258
assert_eq!(params.params(), &[("name", "abc.xyz")]);
22592259
}
2260+
2261+
#[test]
2262+
fn test_dots_ext_no_qualifier() {
2263+
let mut tree = PathTree::new();
2264+
let _ = tree.insert("/:name.js", 2);
2265+
let _ = tree.insert("/:name.js.gz", 1);
2266+
2267+
let result = tree.find("/node.js");
2268+
assert!(result.is_some());
2269+
2270+
let (value, params) = result.unwrap();
2271+
assert_eq!(value, &2);
2272+
2273+
assert_eq!(params.params(), &[("name", "node")]);
2274+
2275+
let result = tree.find("/path.lib.js");
2276+
assert!(result.is_some());
2277+
2278+
let (value, params) = result.unwrap();
2279+
assert_eq!(value, &2);
2280+
2281+
assert_eq!(params.params(), &[("name", "path.lib")]);
2282+
2283+
let result = tree.find("/node.js.js");
2284+
assert!(result.is_some());
2285+
2286+
let (value, params) = result.unwrap();
2287+
assert_eq!(value, &2);
2288+
2289+
assert_eq!(params.params(), &[("name", "node.js")]);
2290+
2291+
let result = tree.find("/node.js.gz");
2292+
assert!(result.is_some());
2293+
2294+
let (value, params) = result.unwrap();
2295+
assert_eq!(value, &1);
2296+
2297+
assert_eq!(params.params(), &[("name", "node")]);
2298+
2299+
let result = tree.find("/node.js.gz.js.gz");
2300+
assert!(result.is_some());
2301+
2302+
let (value, params) = result.unwrap();
2303+
assert_eq!(value, &1);
2304+
2305+
assert_eq!(params.params(), &[("name", "node.js.gz")]);
2306+
}

0 commit comments

Comments
 (0)