From 02687bff4b25848f9267292a4ae1dfbebc313c36 Mon Sep 17 00:00:00 2001 From: Cathal Mullan Date: Sat, 7 Sep 2024 21:16:12 +0100 Subject: [PATCH] Rearchitect router internals. --- CHANGELOG.md | 1 + README.md | 56 +-- examples/oci/src/router.rs | 4 +- src/node.rs | 18 +- src/node/search.rs | 11 +- src/router.rs | 39 +- tests/common.rs | 26 +- tests/constraints.rs | 24 +- tests/encoding.rs | 60 +-- tests/matchit_matches.rs | 856 ++++++++++++++++++------------------- tests/path_tree.rs | 484 ++++++++++----------- tests/poem.rs | 88 ++-- tests/uncommon.rs | 104 ++--- 13 files changed, 904 insertions(+), 867 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1720b1b..791f336d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Router display now uses different characters to represent root and matchable nodes. +- Successful matches now return a flattened representation of node data. ## [0.2.1] - 2024-09-04 diff --git a/README.md b/README.md index 0409ce85..08976245 100644 --- a/README.md +++ b/README.md @@ -47,15 +47,15 @@ fn main() -> Result<(), Box> { let path = Path::new("/users/123")?; let search = router.search(&path)?.unwrap(); - assert_eq!(search.data.value, 1); - assert_eq!(search.data.path, "/users/{id}".into()); + assert_eq!(*search.data, 1); + assert_eq!(search.route, "/users/{id}".into()); assert_eq!(search.parameters[0].key, "id"); assert_eq!(search.parameters[0].value, "123"); let path = Path::new("/users/123/files/my.document.pdf")?; let search = router.search(&path)?.unwrap(); - assert_eq!(search.data.value, 2); - assert_eq!(search.data.path, "/users/{id}/files/{filename}.{extension}".into()); + assert_eq!(*search.data, 2); + assert_eq!(search.route, "/users/{id}/files/{filename}.{extension}".into()); assert_eq!(search.parameters[0].key, "id"); assert_eq!(search.parameters[0].value, "123"); assert_eq!(search.parameters[1].key, "filename"); @@ -88,15 +88,15 @@ fn main() -> Result<(), Box> { let path = Path::new("/files/documents/reports/annual.pdf/delete")?; let search = router.search(&path)?.unwrap(); - assert_eq!(search.data.value, 1); - assert_eq!(search.data.path, "/files/{*slug}/delete".into()); + assert_eq!(*search.data, 1); + assert_eq!(search.route, "/files/{*slug}/delete".into()); assert_eq!(search.parameters[0].key, "slug"); assert_eq!(search.parameters[0].value, "documents/reports/annual.pdf"); let path = Path::new("/any/other/path")?; let search = router.search(&path)?.unwrap(); - assert_eq!(search.data.value, 2); - assert_eq!(search.data.path, "/{*catch_all}".into()); + assert_eq!(*search.data, 2); + assert_eq!(search.route, "/{*catch_all}".into()); assert_eq!(search.parameters[0].key, "catch_all"); assert_eq!(search.parameters[0].value, "any/other/path"); @@ -179,13 +179,13 @@ fn main() -> Result<(), Box> { let path = Path::new("/v2")?; let search = router.search(&path)?.unwrap(); - assert_eq!(search.data.value, 1); - assert_eq!(search.data.path, "/v2".into()); + assert_eq!(*search.data, 1); + assert_eq!(search.route, "/v2".into()); let path = Path::new("/v2/my-org/my-repo/blobs/sha256:1234567890")?; let search = router.search(&path)?.unwrap(); - assert_eq!(search.data.value, 2); - assert_eq!(search.data.path, "/v2/{*name:namespace}/blobs/{type}:{digest}".into()); + assert_eq!(*search.data, 2); + assert_eq!(search.route, "/v2/{*name:namespace}/blobs/{type}:{digest}".into()); assert_eq!(search.parameters[0].key, "name"); assert_eq!(search.parameters[0].value, "my-org/my-repo"); assert_eq!(search.parameters[1].key, "type"); @@ -347,14 +347,14 @@ In a router of 130 routes, benchmark matching 4 paths. | Library | Time | Alloc Count | Alloc Size | Dealloc Count | Dealloc Size | |:-----------------|----------:|------------:|-----------:|--------------:|-------------:| -| matchit | 462.33 ns | 4 | 416 B | 4 | 448 B | -| wayfind | 483.07 ns | 7 | 649 B | 7 | 649 B | -| xitca-router | 562.71 ns | 7 | 800 B | 7 | 832 B | -| path-tree | 572.69 ns | 4 | 416 B | 4 | 448 B | -| ntex-router | 1.7347 µs | 18 | 1.248 KB | 18 | 1.28 KB | -| route-recognizer | 4.6183 µs | 160 | 8.515 KB | 160 | 8.547 KB | -| routefinder | 6.5185 µs | 67 | 5.024 KB | 67 | 5.056 KB | -| actix-router | 21.268 µs | 214 | 13.93 KB | 214 | 13.96 KB | +| matchit | 484.35 ns | 4 | 416 B | 4 | 448 B | +| wayfind | 513.07 ns | 7 | 649 B | 7 | 649 B | +| xitca-router | 556.80 ns | 7 | 800 B | 7 | 832 B | +| path-tree | 576.46 ns | 4 | 416 B | 4 | 448 B | +| ntex-router | 1.7798 µs | 18 | 1.248 KB | 18 | 1.28 KB | +| route-recognizer | 4.7831 µs | 160 | 8.515 KB | 160 | 8.547 KB | +| routefinder | 6.4484 µs | 67 | 5.024 KB | 67 | 5.056 KB | +| actix-router | 22.061 µs | 214 | 13.93 KB | 214 | 13.96 KB | #### `path-tree` inspired benches @@ -362,14 +362,14 @@ In a router of 320 routes, benchmark matching 80 paths. | Library | Time | Alloc Count | Alloc Size | Dealloc Count | Dealloc Size | |:-----------------|----------:|------------:|-----------:|--------------:|-------------:| -| wayfind | 7.0411 µs | 117 | 9.991 KB | 117 | 9.991 KB | -| matchit | 8.8426 µs | 140 | 17.81 KB | 140 | 17.83 KB | -| path-tree | 9.2876 µs | 59 | 7.447 KB | 59 | 7.47 KB | -| xitca-router | 10.888 µs | 209 | 25.51 KB | 209 | 25.53 KB | -| ntex-router | 30.283 µs | 201 | 19.54 KB | 201 | 19.56 KB | -| routefinder | 99.873 µs | 525 | 48.4 KB | 525 | 48.43 KB | -| route-recognizer | 107.16 µs | 2872 | 191.8 KB | 2872 | 205 KB | -| actix-router | 192.44 µs | 2201 | 128.8 KB | 2201 | 128.8 KB | +| wayfind | 7.4842 µs | 117 | 9.991 KB | 117 | 9.991 KB | +| matchit | 8.8485 µs | 140 | 17.81 KB | 140 | 17.83 KB | +| path-tree | 9.2987 µs | 59 | 7.447 KB | 59 | 7.47 KB | +| xitca-router | 10.813 µs | 209 | 25.51 KB | 209 | 25.53 KB | +| ntex-router | 29.732 µs | 201 | 19.54 KB | 201 | 19.56 KB | +| route-recognizer | 91.251 µs | 2872 | 191.8 KB | 2872 | 205 KB | +| routefinder | 99.015 µs | 525 | 48.4 KB | 525 | 48.43 KB | +| actix-router | 180.71 µs | 2201 | 128.8 KB | 2201 | 128.8 KB | ## License diff --git a/examples/oci/src/router.rs b/examples/oci/src/router.rs index 5562fbf6..41b13833 100644 --- a/examples/oci/src/router.rs +++ b/examples/oci/src/router.rs @@ -94,9 +94,9 @@ impl AppRouter { return StatusCode::NOT_FOUND.into_response(); }; - let handler = &search.data.value; + let handler = &search.data; - let route = search.data.path.to_string(); + let route = search.route.to_string(); let route = RouteInner(route); let parameters: Vec<(String, String)> = search diff --git a/src/node.rs b/src/node.rs index e014b171..c740f805 100644 --- a/src/node.rs +++ b/src/node.rs @@ -27,11 +27,19 @@ pub enum NodeKind { /// Holds data associated with a given node. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct NodeData { - /// The full path from the root to this node. - pub path: Arc, - /// The value associated with this node. - pub value: T, +pub enum NodeData { + /// Data is stored inline. + Inline { + /// The original route path. + route: Arc, + + /// The associated data. + value: T, + }, + + /// Data is stored at the router level, as it's shared between 2 or more nodes. + #[allow(dead_code)] + Reference(Arc), } /// Represents a node in the tree structure. diff --git a/src/node/search.rs b/src/node/search.rs index 0dbdac4b..0e1f1748 100644 --- a/src/node/search.rs +++ b/src/node/search.rs @@ -1,12 +1,15 @@ -use super::{Node, NodeData}; +use super::Node; use crate::{errors::SearchError, router::StoredConstraint}; -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; /// Stores data from a successful router match. #[derive(Debug, Eq, PartialEq)] pub struct Match<'router, 'path, T> { - /// A reference to the data stored at the end matching node. - pub data: &'router NodeData, + /// The matching route. + pub route: Arc, + + /// A reference to the matching route data. + pub data: &'router T, /// Key-value pairs of parameters, extracted from the route. pub parameters: Vec>, diff --git a/src/router.rs b/src/router.rs index 2082ae34..9ee256cc 100644 --- a/src/router.rs +++ b/src/router.rs @@ -30,6 +30,10 @@ pub struct Router { /// A map of constraint names to [`StoredConstraint`]. constraints: HashMap, StoredConstraint>, + + /// Shared route data. + /// Only used when multiple nodes require the same data storage. + data: HashMap, T>, } impl Router { @@ -56,6 +60,7 @@ impl Router { quick_dynamic: false, }, constraints: HashMap::new(), + data: HashMap::new(), }; router.constraint::().unwrap(); @@ -138,15 +143,15 @@ impl Router { /// router.insert("/hello/{world}", 2).unwrap(); /// ``` pub fn insert(&mut self, route: &str, value: T) -> Result<(), InsertError> { - let path = Path::new(route)?; - if route.as_bytes() != path.decoded_bytes() { + let route_path = Path::new(route)?; + if route.as_bytes() != route_path.decoded_bytes() { return Err(InsertError::EncodedPath { input: route.to_string(), - decoded: String::from_utf8_lossy(path.decoded_bytes()).to_string(), + decoded: String::from_utf8_lossy(route_path.decoded_bytes()).to_string(), }); } - let path = Arc::from(route); + let route_arc = Arc::from(route); let mut parts = Parts::new(route.as_bytes())?; for part in &parts { @@ -167,7 +172,13 @@ impl Router { } } - self.root.insert(&mut parts, NodeData { path, value }) + // TODO: Using Parts, determine whether we need to store inline or not. + let node_data = NodeData::Inline { + route: Arc::clone(&route_arc), + value, + }; + + self.root.insert(&mut parts, node_data) } /// Deletes a route from the router. @@ -224,11 +235,23 @@ impl Router { return Ok(None); }; - let Some(data) = node.data.as_ref() else { - return Ok(None); + let (route, data) = match &node.data { + Some(NodeData::Inline { route, value }) => (Arc::clone(route), value), + Some(NodeData::Reference(key)) => { + let Some(data) = self.data.get(key) else { + return Ok(None); + }; + + (Arc::clone(key), data) + } + None => return Ok(None), }; - Ok(Some(Match { data, parameters })) + Ok(Some(Match { + route, + data, + parameters, + })) } } diff --git a/tests/common.rs b/tests/common.rs index e392249e..dd7deef7 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -13,15 +13,15 @@ macro_rules! assert_router_matches { }; (@parse_expected { - path: $path:expr, - value: $value:expr + route: $route:expr, + data: $data:expr $(, params: { $($param_key:expr => $param_value:expr),+ })? }) => { Some($crate::common::ExpectedMatch { - path: std::sync::Arc::from($path), - value: $value, + route: std::sync::Arc::from($route), + data: $data, params: vec![ $( $( wayfind::Parameter { @@ -39,8 +39,8 @@ macro_rules! assert_router_matches { } pub struct ExpectedMatch<'k, 'v, T> { - pub path: Arc, - pub value: T, + pub route: Arc, + pub data: T, pub params: Vec>, } @@ -51,17 +51,19 @@ pub fn assert_router_match<'a, T: PartialEq + Debug>( expected: Option>, ) { let path = Path::new(input).expect("Invalid path!"); - let Ok(Some(Match { data, parameters })) = router.search(&path) else { + let Ok(Some(Match { + route, + data, + parameters, + })) = router.search(&path) + else { assert!(expected.is_none(), "No match found for input: {input}"); return; }; if let Some(expected) = expected { - assert_eq!(data.path, expected.path, "Path mismatch for input: {input}"); - assert_eq!( - data.value, expected.value, - "Value mismatch for input: {input}" - ); + assert_eq!(route, expected.route, "Path mismatch for input: {input}"); + assert_eq!(*data, expected.data, "Value mismatch for input: {input}"); assert_eq!( parameters, expected.params, "Parameters mismatch for input: {input}" diff --git a/tests/constraints.rs b/tests/constraints.rs index e9e86b20..37973295 100644 --- a/tests/constraints.rs +++ b/tests/constraints.rs @@ -95,16 +95,16 @@ fn test_multiple_constraints() -> Result<(), Box> { assert_router_matches!(router, { "/user/john/1234" => { - path: "/user/{name:length_3_to_10}/{id:year_1000_to_10000}", - value: 1, + route: "/user/{name:length_3_to_10}/{id:year_1000_to_10000}", + data: 1, params: { "name" => "john", "id" => "1234" } } "/user/johndoe/10000" => { - path: "/user/{name:length_3_to_10}/{id:year_1000_to_10000}", - value: 1, + route: "/user/{name:length_3_to_10}/{id:year_1000_to_10000}", + data: 1, params: { "name" => "johndoe", "id" => "10000" @@ -116,16 +116,16 @@ fn test_multiple_constraints() -> Result<(), Box> { "/user/john/10001" => None "/profile/alice.png" => { - path: "/profile/{username:length_3_to_10}.{ext:png_or_jpg}", - value: 2, + route: "/profile/{username:length_3_to_10}.{ext:png_or_jpg}", + data: 2, params: { "username" => "alice", "ext" => "png" } } "/profile/bob.jpg" => { - path: "/profile/{username:length_3_to_10}.{ext:png_or_jpg}", - value: 2, + route: "/profile/{username:length_3_to_10}.{ext:png_or_jpg}", + data: 2, params: { "username" => "bob", "ext" => "jpg" @@ -136,16 +136,16 @@ fn test_multiple_constraints() -> Result<(), Box> { "/profile/alice.gif" => None "/posts/2022/hello" => { - path: "/posts/{year:even_year}/{slug:valid_slug}", - value: 3, + route: "/posts/{year:even_year}/{slug:valid_slug}", + data: 3, params: { "year" => "2022", "slug" => "hello" } } "/posts/2024/test-123" => { - path: "/posts/{year:even_year}/{slug:valid_slug}", - value: 3, + route: "/posts/{year:even_year}/{slug:valid_slug}", + data: 3, params: { "year" => "2024", "slug" => "test-123" diff --git a/tests/encoding.rs b/tests/encoding.rs index 4341678d..29a66408 100644 --- a/tests/encoding.rs +++ b/tests/encoding.rs @@ -18,64 +18,64 @@ fn percent_encoding() -> Result<(), Box> { assert_router_matches!(router, { "/hello%40world" => { - path: "/hello@world", - value: 1 + route: "/hello@world", + data: 1 } "/hello@world" => { - path: "/hello@world", - value: 1 + route: "/hello@world", + data: 1 } "/hello-world.com" => { - path: "/hello-world.com", - value: 2 + route: "/hello-world.com", + data: 2 } "/hello%20world" => { - path: "/hello world", - value: 3 + route: "/hello world", + data: 3 } "/hello world" => { - path: "/hello world", - value: 3 + route: "/hello world", + data: 3 } "/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF" => { - path: "/こんにちは", - value: 4 + route: "/こんにちは", + data: 4 } "/こんにちは" => { - path: "/こんにちは", - value: 4 + route: "/こんにちは", + data: 4 } "/50%25" => { - path: "/50%", - value: 5 + route: "/50%", + data: 5 } "/50%" => { - path: "/50%", - value: 5 + route: "/50%", + data: 5 } "/hello%20world%40example.com" => { - path: "/hello world@example.com", - value: 6 + route: "/hello world@example.com", + data: 6 } "/hello world@example.com" => { - path: "/hello world@example.com", - value: 6 + route: "/hello world@example.com", + data: 6 } "/path/to/resource%20with%20spaces" => { - path: "/path/to/resource with spaces", - value: 7 + route: "/path/to/resource with spaces", + data: 7 } "/path/to/resource with spaces" => { - path: "/path/to/resource with spaces", - value: 7 + route: "/path/to/resource with spaces", + data: 7 } "/encoded%2Fslash" => { - path: "/encoded/slash", - value: 8 + route: "/encoded/slash", + data: 8 } "/encoded/slash" => { - path: "/encoded/slash", - value: 8 + route: "/encoded/slash", + data: 8 } }); diff --git a/tests/matchit_matches.rs b/tests/matchit_matches.rs index 2a5b191a..b6a70b48 100644 --- a/tests/matchit_matches.rs +++ b/tests/matchit_matches.rs @@ -60,19 +60,19 @@ fn wildcard_overlap() -> Result<(), Box> { assert_router_matches!(router, { "/path/foo" => { - path: "/path/foo", - value: "foo" + route: "/path/foo", + data: "foo" } "/path/bar" => { - path: "/path/{*rest}", - value: "wildcard", + route: "/path/{*rest}", + data: "wildcard", params: { "rest" => "bar" } } "/path/foo/" => { - path: "/path/{*rest}", - value: "wildcard", + route: "/path/{*rest}", + data: "wildcard", params: { "rest" => "foo/" } @@ -93,22 +93,22 @@ fn wildcard_overlap() -> Result<(), Box> { assert_router_matches!(router, { "/path/foo/myarg" => { - path: "/path/foo/{arg}", - value: "foo", + route: "/path/foo/{arg}", + data: "foo", params: { "arg" => "myarg" } } "/path/foo/myarg/" => { - path: "/path/{*rest}", - value: "wildcard", + route: "/path/{*rest}", + data: "wildcard", params: { "rest" => "foo/myarg/" } } "/path/foo/myarg/bar/baz" => { - path: "/path/{*rest}", - value: "wildcard", + route: "/path/{*rest}", + data: "wildcard", params: { "rest" => "foo/myarg/bar/baz" } @@ -138,23 +138,23 @@ fn overlapping_param_backtracking() -> Result<(), Box> { assert_router_matches!(router, { "/secret/978/path" => { - path: "/secret/{id}/path", - value: "secret with id and path", + route: "/secret/{id}/path", + data: "secret with id and path", params: { "id" => "978" } } "/something/978" => { - path: "/{object}/{id}", - value: "object with id", + route: "/{object}/{id}", + data: "object with id", params: { "object" => "something", "id" => "978" } } "/secret/978" => { - path: "/{object}/{id}", - value: "object with id", + route: "/{object}/{id}", + data: "object with id", params: { "object" => "secret", "id" => "978" @@ -181,29 +181,29 @@ fn bare_catchall() -> Result<(), Box> { assert_router_matches!(router, { "x/y" => { - path: "{*foo}", - value: 1, + route: "{*foo}", + data: 1, params: { "foo" => "x/y" } } "/x/y" => { - path: "{*foo}", - value: 1, + route: "{*foo}", + data: 1, params: { "foo" => "/x/y" } } "/foo/x/y" => { - path: "{*foo}", - value: 1, + route: "{*foo}", + data: 1, params: { "foo" => "/foo/x/y" } } "foo/x/y" => { - path: "foo/{*bar}", - value: 2, + route: "foo/{*bar}", + data: 2, params: { "bar" => "x/y" } @@ -270,53 +270,53 @@ fn normalized() -> Result<(), Box> { assert_router_matches!(router, { "/x/foo/bar" => { - path: "/x/{foo}/bar", - value: 1, + route: "/x/{foo}/bar", + data: 1, params: { "foo" => "foo" } } "/x/foo/baz" => { - path: "/x/{bar}/baz", - value: 2, + route: "/x/{bar}/baz", + data: 2, params: { "bar" => "foo" } } "/y/foo/baz" => { - path: "/{foo}/{bar}/baz", - value: 4, + route: "/{foo}/{bar}/baz", + data: 4, params: { "foo" => "y", "bar" => "foo" } } "/y/foo/bax" => { - path: "/{foo}/{baz}/bax", - value: 3, + route: "/{foo}/{baz}/bax", + data: 3, params: { "foo" => "y", "baz" => "foo" } } "/y/baz/baz" => { - path: "/{foo}/{bar}/baz", - value: 4, + route: "/{foo}/{bar}/baz", + data: 4, params: { "foo" => "y", "bar" => "baz" } } "/y/baz/bax/foo" => { - path: "/{fod}/baz/bax/foo", - value: 6, + route: "/{fod}/baz/bax/foo", + data: 6, params: { "fod" => "y" } } "/y/baz/b/foo" => { - path: "/{fod}/{baz}/{bax}/foo", - value: 5, + route: "/{fod}/{baz}/{bax}/foo", + data: 5, params: { "fod" => "y", "baz" => "baz", @@ -324,46 +324,46 @@ fn normalized() -> Result<(), Box> { } } "/y/baz/bax" => { - path: "/{foo}/baz/bax", - value: 7, + route: "/{foo}/baz/bax", + data: 7, params: { "foo" => "y" } } "/z/bar/bay" => { - path: "/{bar}/{bay}/bay", - value: 8, + route: "/{bar}/{bay}/bay", + data: 8, params: { "bar" => "z", "bay" => "bar" } } "/s" => { - path: "/s", - value: 9 + route: "/s", + data: 9 } "/s/s" => { - path: "/s/s", - value: 10 + route: "/s/s", + data: 10 } "/s/s/s" => { - path: "/s/s/s", - value: 11 + route: "/s/s/s", + data: 11 } "/s/s/s/s" => { - path: "/s/s/s/s", - value: 12 + route: "/s/s/s/s", + data: 12 } "/s/s/s/x" => { - path: "/s/s/{s}/x", - value: 13, + route: "/s/s/{s}/x", + data: 13, params: { "s" => "s" } } "/s/s/s/d" => { - path: "/s/s/{y}/d", - value: 14, + route: "/s/s/{y}/d", + data: 14, params: { "y" => "s" } @@ -402,15 +402,15 @@ fn blog() -> Result<(), Box> { assert_router_matches!(router, { "/about" => { - path: "/{page}", - value: 1, + route: "/{page}", + data: 1, params: { "page" => "about" } } "/posts/2021/01/rust" => { - path: "/posts/{year}/{month}/{post}", - value: 2, + route: "/posts/{year}/{month}/{post}", + data: 2, params: { "year" => "2021", "month" => "01", @@ -418,30 +418,30 @@ fn blog() -> Result<(), Box> { } } "/posts/2021/01/index" => { - path: "/posts/{year}/{month}/index", - value: 3, + route: "/posts/{year}/{month}/index", + data: 3, params: { "year" => "2021", "month" => "01" } } "/posts/2021/top" => { - path: "/posts/{year}/top", - value: 4, + route: "/posts/{year}/top", + data: 4, params: { "year" => "2021" } } "/static/foo.png" => { - path: "/static/{*path}", - value: 5, + route: "/static/{*path}", + data: 5, params: { "path" => "foo.png" } } "/favicon.ico" => { - path: "/favicon.ico", - value: 6 + route: "/favicon.ico", + data: 6 } }); @@ -482,28 +482,28 @@ fn double_overlap() -> Result<(), Box> { assert_router_matches!(router, { "/secret/978/path" => { - path: "/secret/{id}/path", - value: 2, + route: "/secret/{id}/path", + data: 2, params: { "id" => "978" } } "/some_object/978" => { - path: "/{object}/{id}", - value: 1, + route: "/{object}/{id}", + data: 1, params: { "object" => "some_object", "id" => "978" } } "/secret/978" => { - path: "/secret/978", - value: 3 + route: "/secret/978", + data: 3 } "/super_secret/978/" => None "/other/object/1/" => { - path: "/other/{object}/{id}/", - value: 4, + route: "/other/{object}/{id}/", + data: 4, params: { "object" => "object", "id" => "1" @@ -511,19 +511,19 @@ fn double_overlap() -> Result<(), Box> { } "/other/object/1/2" => None "/other/an_object/1" => { - path: "/other/an_object/{id}", - value: 5, + route: "/other/an_object/{id}", + data: 5, params: { "id" => "1" } } "/other/static/path" => { - path: "/other/static/path", - value: 6 + route: "/other/static/path", + data: 6 } "/other/long/static/path/" => { - path: "/other/long/static/path/", - value: 7 + route: "/other/long/static/path/", + data: 7 } }); @@ -552,23 +552,23 @@ fn catchall_off_by_one() -> Result<(), Box> { "/foo" => None "/foo/" => None "/foo/x" => { - path: "/foo/{*catchall}", - value: 1, + route: "/foo/{*catchall}", + data: 1, params: { "catchall" => "x" } } "/bar" => { - path: "/bar", - value: 2 + route: "/bar", + data: 2 } "/bar/" => { - path: "/bar/", - value: 3 + route: "/bar/", + data: 3 } "/bar/x" => { - path: "/bar/{*catchall}", - value: 4, + route: "/bar/{*catchall}", + data: 4, params: { "catchall" => "x" } @@ -609,51 +609,51 @@ fn overlap() -> Result<(), Box> { assert_router_matches!(router, { "/foo" => { - path: "/foo", - value: 1 + route: "/foo", + data: 1 } "/bar" => { - path: "/bar", - value: 2 + route: "/bar", + data: 2 } "/baz" => { - path: "/baz", - value: 4 + route: "/baz", + data: 4 } "/baz/" => { - path: "/baz/", - value: 5 + route: "/baz/", + data: 5 } "/baz/x" => { - path: "/baz/x", - value: 6 + route: "/baz/x", + data: 6 } "/???" => { - path: "/{*bar}", - value: 3, + route: "/{*bar}", + data: 3, params: { "bar" => "???" } } "/" => { - path: "/", - value: 8 + route: "/", + data: 8 } "" => None "/xxx/y" => { - path: "/xxx/{*x}", - value: 9, + route: "/xxx/{*x}", + data: 9, params: { "x" => "y" } } "/xxx/" => { - path: "/xxx/", - value: 10 + route: "/xxx/", + data: 10 } "/xxx" => { - path: "/{*bar}", - value: 3, + route: "/{*bar}", + data: 3, params: { "bar" => "xxx" } @@ -682,12 +682,12 @@ fn missing_trailing_slash_param() -> Result<(), Box> { assert_router_matches!(router, { "/foo/secret/978/" => { - path: "/foo/secret/978/", - value: 3 + route: "/foo/secret/978/", + data: 3 } "/foo/secret/978" => { - path: "/foo/{object}/{id}", - value: 1, + route: "/foo/{object}/{id}", + data: 1, params: { "object" => "secret", "id" => "978" @@ -718,8 +718,8 @@ fn extra_trailing_slash_param() -> Result<(), Box> { assert_router_matches!(router, { "/foo/secret/978/" => None "/foo/secret/978" => { - path: "/foo/secret/978", - value: 3 + route: "/foo/secret/978", + data: 3 } }); @@ -743,15 +743,15 @@ fn missing_trailing_slash_catch_all() -> Result<(), Box> { assert_router_matches!(router, { "/foo/secret/978" => { - path: "/foo/{*bar}", - value: 1, + route: "/foo/{*bar}", + data: 1, params: { "bar" => "secret/978" } } "/foo/secret/978/" => { - path: "/foo/secret/978/", - value: 3 + route: "/foo/secret/978/", + data: 3 } }); @@ -775,15 +775,15 @@ fn extra_trailing_slash_catch_all() -> Result<(), Box> { assert_router_matches!(router, { "/foo/secret/978/" => { - path: "/foo/{*bar}", - value: 1, + route: "/foo/{*bar}", + data: 1, params: { "bar" => "secret/978/" } } "/foo/secret/978" => { - path: "/foo/secret/978", - value: 3 + route: "/foo/secret/978", + data: 3 } }); @@ -829,16 +829,16 @@ fn double_overlap_trailing_slash() -> Result<(), Box> { "/other/object/1" => None "/other/object/1/2" => None "/other/an_object/1/" => { - path: "/other/{object}/{id}/", - value: 4, + route: "/other/{object}/{id}/", + data: 4, params: { "object" => "an_object", "id" => "1" } } "/other/static/path/" => { - path: "/other/{object}/{id}/", - value: 4, + route: "/other/{object}/{id}/", + data: 4, params: { "object" => "static", "id" => "path" @@ -869,22 +869,22 @@ fn trailing_slash_overlap() -> Result<(), Box> { assert_router_matches!(router, { "/foo/x/baz/" => { - path: "/foo/{x}/baz/", - value: 1, + route: "/foo/{x}/baz/", + data: 1, params: { "x" => "x" } } "/foo/x/baz" => { - path: "/foo/{x}/baz", - value: 2, + route: "/foo/{x}/baz", + data: 2, params: { "x" => "x" } } "/foo/bar/bar" => { - path: "/foo/bar/bar", - value: 3 + route: "/foo/bar/bar", + data: 3 } }); @@ -1087,15 +1087,15 @@ fn catchall_overlap() -> Result<(), Box> { assert_router_matches!(router, { "/yyy/y" => { - path: "/yyy/{*x}", - value: 1, + route: "/yyy/{*x}", + data: 1, params: { "x" => "y" } } "/yyy/" => { - path: "/yyy{*x}", - value: 2, + route: "/yyy{*x}", + data: 2, params: { "x" => "/" } @@ -1147,104 +1147,104 @@ fn escaped() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 1 + route: "/", + data: 1 } "/{" => { - path: "/{{", - value: 2 + route: "/{{", + data: 2 } "/}" => { - path: "/}}", - value: 3 + route: "/}}", + data: 3 } "/{x" => { - path: "/{{x", - value: 4 + route: "/{{x", + data: 4 } "/}y{" => { - path: "/}}y{{", - value: 5 + route: "/}}y{{", + data: 5 } "/xy{" => { - path: "/xy{{", - value: 6 + route: "/xy{{", + data: 6 } "/{/xyz" => { - path: "/{{/xyz", - value: 7 + route: "/{{/xyz", + data: 7 } // "/foo" => { - // path: "/{ba{{r}", - // value: 8, + // route: "/{ba{{r}", + // data: 8, // params: { // "ba{r" => "foo" // } // } // "/{{" => { - // path: "/{ba{{r}", - // value: 8, + // route: "/{ba{{r}", + // data: 8, // params: { // "ba{r" => "{{" // } // } // "/{{}}/" => { - // path: "/{ba{{r}/", - // value: 9, + // route: "/{ba{{r}/", + // data: 9, // params: { // "ba{r" => "{{}}" // } // } // "/{{}}{{/x" => { - // path: "/{ba{{r}/x", - // value: 10, + // route: "/{ba{{r}/x", + // data: 10, // params: { // "ba{r" => "{{}}{{" // } // } "/baz/x" => { - path: "/baz/{xxx}", - value: 11, + route: "/baz/{xxx}", + data: 11, params: { "xxx" => "x" } } "/baz/x/xy{" => { - path: "/baz/{xxx}/xy{{", - value: 12, + route: "/baz/{xxx}/xy{{", + data: 12, params: { "xxx" => "x" } } "/baz/x/xy{{" => None "/baz/x/}xy{{" => { - path: "/baz/{xxx}/}}xy{{{{", - value: 13, + route: "/baz/{xxx}/}}xy{{{{", + data: 13, params: { "xxx" => "x" } } "/{/{{" => { - path: "/{{/{x}", - value: 14, + route: "/{{/{x}", + data: 14, params: { "x" => "{{" } } // "/xxx" => { - // path: "/{ba{{r}", - // value: 8, + // route: "/{ba{{r}", + // data: 8, // params: { // "ba{r" => "xxx" // } // } "/xxx/" => { - path: "/xxx/", - value: 15 + route: "/xxx/", + data: 15 } // "/xxx/foo" => { - // path: "/xxx/{x}{{}}}}{{}}{{{{}}y}", - // value: 16, + // route: "/xxx/{x}{{}}}}{{}}{{{{}}y}", + // data: 16, // params: { // "x}{}}{}{{}y" => "foo" // } @@ -1309,76 +1309,76 @@ fn basic() -> Result<(), Box> { assert_router_matches!(router, { "/a" => { - path: "/a", - value: 5 + route: "/a", + data: 5 } "/" => None "/hi" => { - path: "/hi", - value: 1 + route: "/hi", + data: 1 } "/contact" => { - path: "/contact", - value: 2 + route: "/contact", + data: 2 } "/co" => { - path: "/co", - value: 3 + route: "/co", + data: 3 } "/con" => None "/cona" => None "/no" => None "/ab" => { - path: "/ab", - value: 6 + route: "/ab", + data: 6 } "ʯ" => { - path: "ʯ", - value: 10 + route: "ʯ", + data: 10 } "β" => { - path: "β", - value: 11 + route: "β", + data: 11 } "/sd!here" => { - path: "/sd!here", - value: 12 + route: "/sd!here", + data: 12 } "/sd$here" => { - path: "/sd$here", - value: 13 + route: "/sd$here", + data: 13 } "/sd&here" => { - path: "/sd&here", - value: 14 + route: "/sd&here", + data: 14 } "/sd'here" => { - path: "/sd'here", - value: 15 + route: "/sd'here", + data: 15 } "/sd(here" => { - path: "/sd(here", - value: 16 + route: "/sd(here", + data: 16 } "/sd)here" => { - path: "/sd)here", - value: 17 + route: "/sd)here", + data: 17 } "/sd+here" => { - path: "/sd+here", - value: 18 + route: "/sd+here", + data: 18 } "/sd,here" => { - path: "/sd,here", - value: 19 + route: "/sd,here", + data: 19 } "/sd;here" => { - path: "/sd;here", - value: 20 + route: "/sd;here", + data: 20 } "/sd=here" => { - path: "/sd=here", - value: 21 + route: "/sd=here", + data: 21 } }); @@ -1554,20 +1554,20 @@ fn wildcard() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 1 + route: "/", + data: 1 } "/cmd/test" => None "/cmd/test/" => { - path: "/cmd/{tool}/", - value: 2, + route: "/cmd/{tool}/", + data: 2, params: { "tool" => "test" } } "/cmd/test/3" => { - path: "/cmd/{tool2}/{sub}", - value: 3, + route: "/cmd/{tool2}/{sub}", + data: 3, params: { "tool2" => "test", "sub" => "3" @@ -1575,26 +1575,26 @@ fn wildcard() -> Result<(), Box> { } "/cmd/who" => None "/cmd/who/" => { - path: "/cmd/{tool}/", - value: 2, + route: "/cmd/{tool}/", + data: 2, params: { "tool" => "who" } } "/cmd/whoami" => { - path: "/cmd/whoami", - value: 4 + route: "/cmd/whoami", + data: 4 } "/cmd/whoami/" => { - path: "/cmd/{tool}/", - value: 2, + route: "/cmd/{tool}/", + data: 2, params: { "tool" => "whoami" } } "/cmd/whoami/r" => { - path: "/cmd/{tool2}/{sub}", - value: 3, + route: "/cmd/{tool2}/{sub}", + data: 3, params: { "tool2" => "whoami", "sub" => "r" @@ -1602,382 +1602,382 @@ fn wildcard() -> Result<(), Box> { } "/cmd/whoami/r/" => None "/cmd/whoami/root" => { - path: "/cmd/whoami/root", - value: 5 + route: "/cmd/whoami/root", + data: 5 } "/cmd/whoami/root/" => { - path: "/cmd/whoami/root/", - value: 6 + route: "/cmd/whoami/root/", + data: 6 } "/src" => { - path: "/src", - value: 7 + route: "/src", + data: 7 } "/src/" => { - path: "/src/", - value: 8 + route: "/src/", + data: 8 } "/src/some/file.png" => { - path: "/src/{*filepath}", - value: 9, + route: "/src/{*filepath}", + data: 9, params: { "filepath" => "some/file.png" } } "/search/" => { - path: "/search/", - value: 10 + route: "/search/", + data: 10 } "/search/actix" => { - path: "/search/{query}", - value: 11, + route: "/search/{query}", + data: 11, params: { "query" => "actix" } } "/search/actix-we" => { - path: "/search/actix-we", - value: 12 + route: "/search/actix-we", + data: 12 } "/search/someth!ng+in+ünìcodé" => { - path: "/search/{query}", - value: 11, + route: "/search/{query}", + data: 11, params: { "query" => "someth!ng+in+ünìcodé" } } "/search/someth!ng+in+ünìcodé/" => None "/user_rustacean" => { - path: "/user_{name}", - value: 14, + route: "/user_{name}", + data: 14, params: { "name" => "rustacean" } } "/user_rustacean/about" => { - path: "/user_{name}/about", - value: 15, + route: "/user_{name}/about", + data: 15, params: { "name" => "rustacean" } } "/files/js/inc/framework.js" => { - path: "/files/{dir}/{*filepath}", - value: 16, + route: "/files/{dir}/{*filepath}", + data: 16, params: { "dir" => "js", "filepath" => "inc/framework.js" } } "/info/gordon/public" => { - path: "/info/{user}/public", - value: 20, + route: "/info/{user}/public", + data: 20, params: { "user" => "gordon" } } "/info/gordon/project/rust" => { - path: "/info/{user}/project/{project}", - value: 21, + route: "/info/{user}/project/{project}", + data: 21, params: { "user" => "gordon", "project" => "rust" } } "/info/gordon/project/rustlang" => { - path: "/info/{user}/project/rustlang", - value: 22, + route: "/info/{user}/project/rustlang", + data: 22, params: { "user" => "gordon" } } "/aa/" => None "/aa/aa" => { - path: "/aa/{*xx}", - value: 23, + route: "/aa/{*xx}", + data: 23, params: { "xx" => "aa" } } "/ab/ab" => { - path: "/ab/{*xx}", - value: 24, + route: "/ab/{*xx}", + data: 24, params: { "xx" => "ab" } } "/ab/hello-world" => { - path: "/ab/hello{*xx}", - value: 25, + route: "/ab/hello{*xx}", + data: 25, params: { "xx" => "-world" } } "/a" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "a" } } "/all" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "all" } } "/d" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "d" } } "/ad" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "ad" } } "/dd" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "dd" } } "/dddaa" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "dddaa" } } "/aa" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "aa" } } "/aaa" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "aaa" } } "/aaa/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "aaa" } } "/a" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "a" } } "/ab" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "ab" } } "/abb/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "abb" } } "/allxxxx" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "allxxxx" } } "/alldd" => { - path: "/{cc}", - value: 26, + route: "/{cc}", + data: 26, params: { "cc" => "alldd" } } "/all/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "all" } } "/a/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "a" } } "/c1/d/e" => { - path: "/c1/{dd}/e", - value: 27, + route: "/c1/{dd}/e", + data: 27, params: { "dd" => "d" } } "/c1/d/e1" => { - path: "/c1/{dd}/e1", - value: 28, + route: "/c1/{dd}/e1", + data: 28, params: { "dd" => "d" } } "/c1/d/ee" => { - path: "/{cc}/{dd}/ee", - value: 30, + route: "/{cc}/{dd}/ee", + data: 30, params: { "cc" => "c1", "dd" => "d" } } "/cc/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "cc" } } "/ccc/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "ccc" } } "/deedwjfs/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "deedwjfs" } } "/acllcc/cc" => { - path: "/{cc}/cc", - value: 29, + route: "/{cc}/cc", + data: 29, params: { "cc" => "acllcc" } } "/get/test/abc/" => { - path: "/get/test/abc/", - value: 34 + route: "/get/test/abc/", + data: 34 } "/get/te/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "te" } } "/get/testaa/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "testaa" } } "/get/xx/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "xx" } } "/get/tt/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "tt" } } "/get/a/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "a" } } "/get/t/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "t" } } "/get/aa/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "aa" } } "/get/abas/abc/" => { - path: "/get/{param}/abc/", - value: 35, + route: "/get/{param}/abc/", + data: 35, params: { "param" => "abas" } } "/something/secondthing/test" => { - path: "/something/secondthing/test", - value: 37 + route: "/something/secondthing/test", + data: 37 } "/something/abcdad/thirdthing" => { - path: "/something/{paramname}/thirdthing", - value: 36, + route: "/something/{paramname}/thirdthing", + data: 36, params: { "paramname" => "abcdad" } } "/something/secondthingaaaa/thirdthing" => { - path: "/something/{paramname}/thirdthing", - value: 36, + route: "/something/{paramname}/thirdthing", + data: 36, params: { "paramname" => "secondthingaaaa" } } "/something/se/thirdthing" => { - path: "/something/{paramname}/thirdthing", - value: 36, + route: "/something/{paramname}/thirdthing", + data: 36, params: { "paramname" => "se" } } "/something/s/thirdthing" => { - path: "/something/{paramname}/thirdthing", - value: 36, + route: "/something/{paramname}/thirdthing", + data: 36, params: { "paramname" => "s" } } "/c/d/ee" => { - path: "/{cc}/{dd}/ee", - value: 30, + route: "/{cc}/{dd}/ee", + data: 30, params: { "cc" => "c", "dd" => "d" } } "/c/d/e/ff" => { - path: "/{cc}/{dd}/{ee}/ff", - value: 31, + route: "/{cc}/{dd}/{ee}/ff", + data: 31, params: { "cc" => "c", "dd" => "d", @@ -1985,8 +1985,8 @@ fn wildcard() -> Result<(), Box> { } } "/c/d/e/f/gg" => { - path: "/{cc}/{dd}/{ee}/{ff}/gg", - value: 32, + route: "/{cc}/{dd}/{ee}/{ff}/gg", + data: 32, params: { "cc" => "c", "dd" => "d", @@ -1995,8 +1995,8 @@ fn wildcard() -> Result<(), Box> { } } "/c/d/e/f/g/hh" => { - path: "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", - value: 33, + route: "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", + data: 33, params: { "cc" => "c", "dd" => "d", @@ -2006,8 +2006,8 @@ fn wildcard() -> Result<(), Box> { } } "/cc/dd/ee/ff/gg/hh" => { - path: "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", - value: 33, + route: "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", + data: 33, params: { "cc" => "cc", "dd" => "dd", @@ -2017,284 +2017,284 @@ fn wildcard() -> Result<(), Box> { } } "/get/abc" => { - path: "/get/abc", - value: 38 + route: "/get/abc", + data: 38 } "/get/a" => { - path: "/get/{param}", - value: 39, + route: "/get/{param}", + data: 39, params: { "param" => "a" } } "/get/abz" => { - path: "/get/{param}", - value: 39, + route: "/get/{param}", + data: 39, params: { "param" => "abz" } } "/get/12a" => { - path: "/get/{param}", - value: 39, + route: "/get/{param}", + data: 39, params: { "param" => "12a" } } "/get/abcd" => { - path: "/get/{param}", - value: 39, + route: "/get/{param}", + data: 39, params: { "param" => "abcd" } } "/get/abc/123abc" => { - path: "/get/abc/123abc", - value: 40 + route: "/get/abc/123abc", + data: 40 } "/get/abc/12" => { - path: "/get/abc/{param}", - value: 41, + route: "/get/abc/{param}", + data: 41, params: { "param" => "12" } } "/get/abc/123a" => { - path: "/get/abc/{param}", - value: 41, + route: "/get/abc/{param}", + data: 41, params: { "param" => "123a" } } "/get/abc/xyz" => { - path: "/get/abc/{param}", - value: 41, + route: "/get/abc/{param}", + data: 41, params: { "param" => "xyz" } } "/get/abc/123abcddxx" => { - path: "/get/abc/{param}", - value: 41, + route: "/get/abc/{param}", + data: 41, params: { "param" => "123abcddxx" } } "/get/abc/123abc/xxx8" => { - path: "/get/abc/123abc/xxx8", - value: 42 + route: "/get/abc/123abc/xxx8", + data: 42 } "/get/abc/123abc/x" => { - path: "/get/abc/123abc/{param}", - value: 43, + route: "/get/abc/123abc/{param}", + data: 43, params: { "param" => "x" } } "/get/abc/123abc/xxx" => { - path: "/get/abc/123abc/{param}", - value: 43, + route: "/get/abc/123abc/{param}", + data: 43, params: { "param" => "xxx" } } "/get/abc/123abc/abc" => { - path: "/get/abc/123abc/{param}", - value: 43, + route: "/get/abc/123abc/{param}", + data: 43, params: { "param" => "abc" } } "/get/abc/123abc/xxx8xxas" => { - path: "/get/abc/123abc/{param}", - value: 43, + route: "/get/abc/123abc/{param}", + data: 43, params: { "param" => "xxx8xxas" } } "/get/abc/123abc/xxx8/1234" => { - path: "/get/abc/123abc/xxx8/1234", - value: 44 + route: "/get/abc/123abc/xxx8/1234", + data: 44 } "/get/abc/123abc/xxx8/1" => { - path: "/get/abc/123abc/xxx8/{param}", - value: 45, + route: "/get/abc/123abc/xxx8/{param}", + data: 45, params: { "param" => "1" } } "/get/abc/123abc/xxx8/123" => { - path: "/get/abc/123abc/xxx8/{param}", - value: 45, + route: "/get/abc/123abc/xxx8/{param}", + data: 45, params: { "param" => "123" } } "/get/abc/123abc/xxx8/78k" => { - path: "/get/abc/123abc/xxx8/{param}", - value: 45, + route: "/get/abc/123abc/xxx8/{param}", + data: 45, params: { "param" => "78k" } } "/get/abc/123abc/xxx8/1234xxxd" => { - path: "/get/abc/123abc/xxx8/{param}", - value: 45, + route: "/get/abc/123abc/xxx8/{param}", + data: 45, params: { "param" => "1234xxxd" } } "/get/abc/123abc/xxx8/1234/ffas" => { - path: "/get/abc/123abc/xxx8/1234/ffas", - value: 46 + route: "/get/abc/123abc/xxx8/1234/ffas", + data: 46 } "/get/abc/123abc/xxx8/1234/f" => { - path: "/get/abc/123abc/xxx8/1234/{param}", - value: 47, + route: "/get/abc/123abc/xxx8/1234/{param}", + data: 47, params: { "param" => "f" } } "/get/abc/123abc/xxx8/1234/ffa" => { - path: "/get/abc/123abc/xxx8/1234/{param}", - value: 47, + route: "/get/abc/123abc/xxx8/1234/{param}", + data: 47, params: { "param" => "ffa" } } "/get/abc/123abc/xxx8/1234/kka" => { - path: "/get/abc/123abc/xxx8/1234/{param}", - value: 47, + route: "/get/abc/123abc/xxx8/1234/{param}", + data: 47, params: { "param" => "kka" } } "/get/abc/123abc/xxx8/1234/ffas321" => { - path: "/get/abc/123abc/xxx8/1234/{param}", - value: 47, + route: "/get/abc/123abc/xxx8/1234/{param}", + data: 47, params: { "param" => "ffas321" } } "/get/abc/123abc/xxx8/1234/kkdd/12c" => { - path: "/get/abc/123abc/xxx8/1234/kkdd/12c", - value: 48 + route: "/get/abc/123abc/xxx8/1234/kkdd/12c", + data: 48 } "/get/abc/123abc/xxx8/1234/kkdd/1" => { - path: "/get/abc/123abc/xxx8/1234/kkdd/{param}", - value: 49, + route: "/get/abc/123abc/xxx8/1234/kkdd/{param}", + data: 49, params: { "param" => "1" } } "/get/abc/123abc/xxx8/1234/kkdd/12" => { - path: "/get/abc/123abc/xxx8/1234/kkdd/{param}", - value: 49, + route: "/get/abc/123abc/xxx8/1234/kkdd/{param}", + data: 49, params: { "param" => "12" } } "/get/abc/123abc/xxx8/1234/kkdd/34" => { - path: "/get/abc/123abc/xxx8/1234/kkdd/{param}", - value: 49, + route: "/get/abc/123abc/xxx8/1234/kkdd/{param}", + data: 49, params: { "param" => "34" } } "/get/abc/123abc/xxx8/1234/kkdd/12c2e3" => { - path: "/get/abc/123abc/xxx8/1234/kkdd/{param}", - value: 49, + route: "/get/abc/123abc/xxx8/1234/kkdd/{param}", + data: 49, params: { "param" => "12c2e3" } } "/get/abc/12/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "12" } } "/get/abc/123abdd/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "123abdd" } } "/get/abc/123abdddf/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "123abdddf" } } "/get/abc/123ab/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "123ab" } } "/get/abc/123abgg/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "123abgg" } } "/get/abc/123abff/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "123abff" } } "/get/abc/123abffff/test" => { - path: "/get/abc/{param}/test", - value: 50, + route: "/get/abc/{param}/test", + data: 50, params: { "param" => "123abffff" } } "/get/abc/123abd/test" => { - path: "/get/abc/123abd/{param}", - value: 51, + route: "/get/abc/123abd/{param}", + data: 51, params: { "param" => "test" } } "/get/abc/123abddd/test" => { - path: "/get/abc/123abddd/{param}", - value: 52, + route: "/get/abc/123abddd/{param}", + data: 52, params: { "param" => "test" } } "/get/abc/123/test22" => { - path: "/get/abc/123/{param}", - value: 53, + route: "/get/abc/123/{param}", + data: 53, params: { "param" => "test22" } } "/get/abc/123abg/test" => { - path: "/get/abc/123abg/{param}", - value: 54, + route: "/get/abc/123abg/{param}", + data: 54, params: { "param" => "test" } } "/get/abc/123abf/testss" => { - path: "/get/abc/123abf/{param}", - value: 55, + route: "/get/abc/123abf/{param}", + data: 55, params: { "param" => "testss" } } "/get/abc/123abfff/te" => { - path: "/get/abc/123abfff/{param}", - value: 56, + route: "/get/abc/123abfff/{param}", + data: 56, params: { "param" => "te" } diff --git a/tests/path_tree.rs b/tests/path_tree.rs index df6e0430..d06a3204 100644 --- a/tests/path_tree.rs +++ b/tests/path_tree.rs @@ -45,52 +45,52 @@ fn statics() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 0 + route: "/", + data: 0 } "/hi" => { - path: "/hi", - value: 1 + route: "/hi", + data: 1 } "/contact" => { - path: "/contact", - value: 2 + route: "/contact", + data: 2 } "/co" => { - path: "/co", - value: 3 + route: "/co", + data: 3 } "/c" => { - path: "/c", - value: 4 + route: "/c", + data: 4 } "/a" => { - path: "/a", - value: 5 + route: "/a", + data: 5 } "/ab" => { - path: "/ab", - value: 6 + route: "/ab", + data: 6 } "/doc/" => { - path: "/doc/", - value: 7 + route: "/doc/", + data: 7 } "/doc/go_faq.html" => { - path: "/doc/go_faq.html", - value: 8 + route: "/doc/go_faq.html", + data: 8 } "/doc/go1.html" => { - path: "/doc/go1.html", - value: 9 + route: "/doc/go1.html", + data: 9 } "/α" => { - path: "/α", - value: 10 + route: "/α", + data: 10 } "/β" => { - path: "/β", - value: 11 + route: "/β", + data: 11 } }); @@ -161,19 +161,19 @@ fn wildcards() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 0 + route: "/", + data: 0 } "/cmd/test/" => { - path: "/cmd/{tool}/", - value: 2, + route: "/cmd/{tool}/", + data: 2, params: { "tool" => "test" } } "/cmd/test/3" => { - path: "/cmd/{tool}/{sub}", - value: 1, + route: "/cmd/{tool}/{sub}", + data: 1, params: { "tool" => "test", "sub" => "3" @@ -182,51 +182,51 @@ fn wildcards() -> Result<(), Box> { // NOTE: Different behaviour: path-tree would match "/src/{*filepath}" "/src/" => None "/src/some/file.png" => { - path: "/src/{*filepath}", - value: 4, + route: "/src/{*filepath}", + data: 4, params: { "filepath" => "some/file.png" } } "/search/someth!ng+in+ünìcodé" => { - path: "/search/{query}", - value: 9, + route: "/search/{query}", + data: 9, params: { "query" => "someth!ng+in+ünìcodé" } } "/user_rust" => { - path: "/user_{name}", - value: 11, + route: "/user_{name}", + data: 11, params: { "name" => "rust" } } "/user_rust/about" => { - path: "/user_{name}/about", - value: 12, + route: "/user_{name}/about", + data: 12, params: { "name" => "rust" } } "/files/js/inc/framework.js" => { - path: "/files/{dir}/{*filepath}", - value: 14, + route: "/files/{dir}/{*filepath}", + data: 14, params: { "dir" => "js", "filepath" => "inc/framework.js" } } "/info/gordon/public" => { - path: "/info/{user}/public", - value: 18, + route: "/info/{user}/public", + data: 18, params: { "user" => "gordon" } } "/info/gordon/project/rust" => { - path: "/info/{user}/project/{project}", - value: 19, + route: "/info/{user}/project/{project}", + data: 19, params: { "user" => "gordon", "project" => "rust" @@ -251,15 +251,15 @@ fn single_named_parameter() -> Result<(), Box> { assert_router_matches!(router, { "/" => None "/users/gordon" => { - path: "/users/{id}", - value: 0, + route: "/users/{id}", + data: 0, params: { "id" => "gordon" } } "/users/you" => { - path: "/users/{id}", - value: 0, + route: "/users/{id}", + data: 0, params: { "id" => "you" } @@ -285,8 +285,8 @@ fn repeated_single_named_param() -> Result<(), Box> { // Possibly we'd be better off erroring here, since it's ambiguous. assert_router_matches!(router, { "/users/gordon" => { - path: "/users/{user_id}", - value: 1, + route: "/users/{user_id}", + data: 1, params: { "user_id" => "gordon" } @@ -319,20 +319,20 @@ fn static_and_named_parameter() -> Result<(), Box> { assert_router_matches!(router, { "/" => None "/a/b/c" => { - path: "/a/b/c", - value: "/a/b/c" + route: "/a/b/c", + data: "/a/b/c" } "/a/c/d" => { - path: "/a/c/d", - value: "/a/c/d" + route: "/a/c/d", + data: "/a/c/d" } "/a/c/a" => { - path: "/a/c/a", - value: "/a/c/a" + route: "/a/c/a", + data: "/a/c/a" } "/a/c/e" => { - path: "/{id}/c/e", - value: "/{id}/c/e", + route: "/{id}/c/e", + data: "/{id}/c/e", params: { "id" => "a" } @@ -363,16 +363,16 @@ fn multi_named_parameters() -> Result<(), Box> { "/rust/let/" => None "/rust/let/const" => None "/rust/let" => { - path: "/{lang}/{keyword}", - value: true, + route: "/{lang}/{keyword}", + data: true, params: { "lang" => "rust", "keyword" => "let" } } "/rust" => { - path: "/{id}", - value: true, + route: "/{id}", + data: true, params: { "id" => "rust" } @@ -398,15 +398,15 @@ fn catch_all_parameter() -> Result<(), Box> { // NOTE: Different behaviour: path-tree would match "/src/{*filepath}" "/src/" => None "/src/somefile.rs" => { - path: "/src/{*filepath}", - value: "* files", + route: "/src/{*filepath}", + data: "* files", params: { "filepath" => "somefile.rs" } } "/src/subdir/somefile.rs" => { - path: "/src/{*filepath}", - value: "* files", + route: "/src/{*filepath}", + data: "* files", params: { "filepath" => "subdir/somefile.rs" } @@ -425,8 +425,8 @@ fn catch_all_parameter() -> Result<(), Box> { assert_router_matches!(router, { "/src/" => { - path: "/src/", - value: "dir" + route: "/src/", + data: "dir" } }); @@ -446,19 +446,19 @@ fn catch_all_parameter_with_prefix() -> Result<(), Box> { assert_router_matches!(router, { "/src/" => { - path: "/src/", - value: "dir" + route: "/src/", + data: "dir" } "/commit/123" => { - path: "/commit/{sha}", - value: "hex", + route: "/commit/{sha}", + data: "hex", params: { "sha" => "123" } } "/commit/123/compare/321" => { - path: "/commit/{sha0}/compare/{sha1}", - value: "compare", + route: "/commit/{sha0}/compare/{sha1}", + data: "compare", params: { "sha0" => "123", "sha1" => "321" @@ -466,44 +466,44 @@ fn catch_all_parameter_with_prefix() -> Result<(), Box> { } "/commit" => None "/commit_" => { - path: "/commit_{*sha}", - value: "* sha", + route: "/commit_{*sha}", + data: "* sha", params: { "sha" => "" } } "/commit_/" => { - path: "/commit_{*sha}", - value: "* sha", + route: "/commit_{*sha}", + data: "* sha", params: { "sha" => "/" } } "/commit_/foo" => { - path: "/commit_{*sha}", - value: "* sha", + route: "/commit_{*sha}", + data: "* sha", params: { "sha" => "/foo" } } "/commit123" => None "/commit_123" => { - path: "/commit_{*sha}", - value: "* sha", + route: "/commit_{*sha}", + data: "* sha", params: { "sha" => "123" } } "/commit_123/" => { - path: "/commit_{*sha}", - value: "* sha", + route: "/commit_{*sha}", + data: "* sha", params: { "sha" => "123/" } } "/commit_123/foo" => { - path: "/commit_{*sha}", - value: "* sha", + route: "/commit_{*sha}", + data: "* sha", params: { "sha" => "123/foo" } @@ -534,20 +534,20 @@ fn static_and_catch_all_parameter() -> Result<(), Box> { assert_router_matches!(router, { "/" => None "/a/b/c" => { - path: "/a/b/c", - value: "/a/b/c" + route: "/a/b/c", + data: "/a/b/c" } "/a/c/d" => { - path: "/a/c/d", - value: "/a/c/d" + route: "/a/c/d", + data: "/a/c/d" } "/a/c/a" => { - path: "/a/c/a", - value: "/a/c/a" + route: "/a/c/a", + data: "/a/c/a" } "/a/c/e" => { - path: "/a/{*c}", - value: "/a/*c", + route: "/a/{*c}", + data: "/a/*c", params: { "c" => "c/e" } @@ -574,19 +574,19 @@ fn root_catch_all_parameter() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 1 + route: "/", + data: 1 } "/download" => { - path: "/{*wildcard}", - value: 2, + route: "/{*wildcard}", + data: 2, params: { "wildcard" => "download" } } "/users/jordan" => { - path: "/users/{*wildcard}", - value: 3, + route: "/users/{*wildcard}", + data: 3, params: { "wildcard" => "jordan" } @@ -611,15 +611,15 @@ fn root_catch_all_parameter_1() -> Result<(), Box> { // NOTE: Different behaviour: path-tree would match "/{*wildcard}" "/" => None "/download" => { - path: "/{*wildcard}", - value: 1, + route: "/{*wildcard}", + data: 1, params: { "wildcard" => "download" } } "/users/jordan" => { - path: "/{*wildcard}", - value: 1, + route: "/{*wildcard}", + data: 1, params: { "wildcard" => "users/jordan" } @@ -636,8 +636,8 @@ fn root_catch_all_parameter_1() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 0 + route: "/", + data: 0 } }); @@ -662,29 +662,29 @@ fn test_named_routes_with_non_ascii_paths() -> Result<(), Box> { assert_router_matches!(router, { "/matchme/abc-s-def/" => { - path: "/matchme/{slug}/", - value: 2, + route: "/matchme/{slug}/", + data: 2, params: { "slug" => "abc-s-def" } } "/matchme/abc-ß-def/" => { - path: "/matchme/{slug}/", - value: 2, + route: "/matchme/{slug}/", + data: 2, params: { "slug" => "abc-ß-def" } } "/matchme/abc-⭐-def/" => { - path: "/matchme/{slug}/", - value: 2, + route: "/matchme/{slug}/", + data: 2, params: { "slug" => "abc-⭐-def" } } "/matchme/abc-def-ß/" => { - path: "/matchme/{slug}/", - value: 2, + route: "/matchme/{slug}/", + data: 2, params: { "slug" => "abc-def-ß" } @@ -711,16 +711,16 @@ fn test_named_wildcard_collide() -> Result<(), Box> { assert_router_matches!(router, { "/git/rust-lang/rust" => { - path: "/git/{org}/{repo}", - value: 1, + route: "/git/{org}/{repo}", + data: 1, params: { "org" => "rust-lang", "repo" => "rust" } } "/git/rust-lang" => { - path: "/git/{*wildcard}", - value: 2, + route: "/git/{*wildcard}", + data: 2, params: { "wildcard" => "rust-lang" } @@ -748,8 +748,8 @@ fn match_params() -> Result<(), Box> { // NOTE: Different behaviour: path-tree would match "/api/v1/{param}/{*wildcard}" "/api/v1/entity/" => None "/api/v1/entity/1" => { - path: "/api/v1/{param}/{*wildcard}", - value: 1, + route: "/api/v1/{param}/{*wildcard}", + data: 1, params: { "param" => "entity", "wildcard" => "1" @@ -759,8 +759,8 @@ fn match_params() -> Result<(), Box> { "/api/v2" => None "/api/v1/" => None "/api/v1/entity/1/foo/bar" => { - path: "/api/v1/{param}/{*wildcard}", - value: 1, + route: "/api/v1/{param}/{*wildcard}", + data: 1, params: { "param" => "entity", "wildcard" => "1/foo/bar" @@ -775,8 +775,8 @@ fn match_params() -> Result<(), Box> { "/api/v1/entity" => None "/api/v1/entity/" => None "/api/v1/entity/1" => { - path: "/api/v1/{param}/{*plus}", - value: 1, + route: "/api/v1/{param}/{*plus}", + data: 1, params: { "param" => "entity", "plus" => "1" @@ -786,8 +786,8 @@ fn match_params() -> Result<(), Box> { "/api/v2" => None "/api/v1/" => None "/api/v1/entity/1/foo/bar" => { - path: "/api/v1/{param}/{*plus}", - value: 1, + route: "/api/v1/{param}/{*plus}", + data: 1, params: { "param" => "entity", "plus" => "1/foo/bar" @@ -805,8 +805,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/v1/some/resource/name:customVerb" => { - path: "/v1/some/resource/name:customVerb", - value: 1 + route: "/v1/some/resource/name:customVerb", + data: 1 } "/v1/some/resource/name:test" => None }); @@ -823,8 +823,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/v1/some/resource/test:customVerb" => { - path: "/v1/some/resource/{name}:customVerb", - value: 1, + route: "/v1/some/resource/{name}:customVerb", + data: 1, params: { "name" => "test" } @@ -846,22 +846,22 @@ fn match_params() -> Result<(), Box> { // NOTE: Different behaviour: path-tree would match "/api/v1/{*wildcard}" "/api/v1/" => None "/api/v1/entity" => { - path: "/api/v1/{*wildcard}", - value: 1, + route: "/api/v1/{*wildcard}", + data: 1, params: { "wildcard" => "entity" } } "/api/v1/entity/1/2" => { - path: "/api/v1/{*wildcard}", - value: 1, + route: "/api/v1/{*wildcard}", + data: 1, params: { "wildcard" => "entity/1/2" } } "/api/v1/Entity/1/2" => { - path: "/api/v1/{*wildcard}", - value: 1, + route: "/api/v1/{*wildcard}", + data: 1, params: { "wildcard" => "Entity/1/2" } @@ -881,8 +881,8 @@ fn match_params() -> Result<(), Box> { "/api/v1" => None "/api/v1/" => None "/api/v1/entity" => { - path: "/api/v1/{param}", - value: 1, + route: "/api/v1/{param}", + data: 1, params: { "param" => "entity" } @@ -919,48 +919,48 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/api/v1/entity-entity2" => { - path: "/api/v1/{param}-{param2}", - value: 1, + route: "/api/v1/{param}-{param2}", + data: 1, params: { "param" => "entity", "param2" => "entity2" } } "/api/v1/entity~entity2" => { - path: "/api/v1/{param}~{param2}", - value: 2, + route: "/api/v1/{param}~{param2}", + data: 2, params: { "param" => "entity", "param2" => "entity2" } } "/api/v1/entity.entity2" => { - path: "/api/v1/{param}.{param2}", - value: 4, + route: "/api/v1/{param}.{param2}", + data: 4, params: { "param" => "entity", "param2" => "entity2" } } "/api/v1/entity_entity2" => { - path: "/api/v1/{param}_{param2}", - value: 5, + route: "/api/v1/{param}_{param2}", + data: 5, params: { "param" => "entity", "param2" => "entity2" } } "/api/v1/entity:entity2" => { - path: "/api/v1/{param}:{param2}", - value: 6, + route: "/api/v1/{param}:{param2}", + data: 6, params: { "param" => "entity", "param2" => "entity2" } } "/api/v1/entity/entity2" => { - path: "/api/v1/{param}/{param2}", - value: 3, + route: "/api/v1/{param}/{param2}", + data: 3, params: { "param" => "entity", "param2" => "entity2" @@ -969,8 +969,8 @@ fn match_params() -> Result<(), Box> { "/api/v1" => None "/api/v1/" => None "/api/v1/test.pdf" => { - path: "/api/v1/{param}.{param2}", - value: 4, + route: "/api/v1/{param}.{param2}", + data: 4, params: { "param" => "test", "param2" => "pdf" @@ -988,8 +988,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/api/v1/const" => { - path: "/api/v1/const", - value: 1 + route: "/api/v1/const", + data: 1 } "/api/v1/cons" => None "/api/v1/conststatic" => None @@ -1010,8 +1010,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/api/abc/fixedEnd" => { - path: "/api/{param}/fixedEnd", - value: 1, + route: "/api/{param}/fixedEnd", + data: 1, params: { "param" => "abc" } @@ -1034,8 +1034,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/shop/product/:test/color:blue/size:xs" => { - path: "/shop/product/:{filter}/color:{color}/size:{size}", - value: 1, + route: "/shop/product/:{filter}/color:{color}/size:{size}", + data: 1, params: { "filter" => "test", "color" => "blue", @@ -1089,50 +1089,50 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/name:john" => { - path: "/name{name}", - value: 1, + route: "/name{name}", + data: 1, params: { "name" => ":john" } } "/@john" => { - path: "/@{name}", - value: 2, + route: "/@{name}", + data: 2, params: { "name" => "john" } } "/-john" => { - path: "/-{name}", - value: 3, + route: "/-{name}", + data: 3, params: { "name" => "john" } } "/.john" => { - path: "/.{name}", - value: 4, + route: "/.{name}", + data: 4, params: { "name" => "john" } } "/~john" => { - path: "/~{name}", - value: 5, + route: "/~{name}", + data: 5, params: { "name" => "john" } } "/_john" => { - path: "/_{name}", - value: 6, + route: "/_{name}", + data: 6, params: { "name" => "john" } } "/john" => { - path: "/{name}", - value: 7, + route: "/{name}", + data: 7, params: { "name" => "john" } @@ -1152,8 +1152,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/api/v1/well/abc/wildcard" => { - path: "/api/v1/{param}/abc/{*wildcard}", - value: 1, + route: "/api/v1/{param}/abc/{*wildcard}", + data: 1, params: { "param" => "well", "wildcard" => "wildcard" @@ -1170,16 +1170,16 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/api/test/abc" => { - path: "/api/{*wildcard}/{param}", - value: 1, + route: "/api/{*wildcard}/{param}", + data: 1, params: { "wildcard" => "test", "param" => "abc" } } "/api/joker/batman/robin/1" => { - path: "/api/{*wildcard}/{param}", - value: 1, + route: "/api/{*wildcard}/{param}", + data: 1, params: { "wildcard" => "joker/batman/robin", "param" => "1" @@ -1187,8 +1187,8 @@ fn match_params() -> Result<(), Box> { } // FIXME: This feels wrong. Maybe we should add a check for empty parts? "/api//joker" => { - path: "/api/{*wildcard}/{param}", - value: 1, + route: "/api/{*wildcard}/{param}", + data: 1, params: { "wildcard" => "", "param" => "joker" @@ -1203,8 +1203,8 @@ fn match_params() -> Result<(), Box> { assert_router_matches!(router, { "/api/test/abc/1" => { - path: "/api/{*wildcard}/{param}/{param2}", - value: 1, + route: "/api/{*wildcard}/{param}/{param2}", + data: 1, params: { "wildcard" => "test", "param" => "abc", @@ -1213,8 +1213,8 @@ fn match_params() -> Result<(), Box> { } "/api/joker/batman" => None "/api/joker/batman-robin/1" => { - path: "/api/{*wildcard}/{param}/{param2}", - value: 1, + route: "/api/{*wildcard}/{param}/{param2}", + data: 1, params: { "wildcard" => "joker", "param" => "batman-robin", @@ -1224,8 +1224,8 @@ fn match_params() -> Result<(), Box> { "/api/joker-batman-robin-1" => None "/api/test/abc" => None "/api/joker/batman/robin" => { - path: "/api/{*wildcard}/{param}/{param2}", - value: 1, + route: "/api/{*wildcard}/{param}/{param2}", + data: 1, params: { "wildcard" => "joker", "param" => "batman", @@ -1233,8 +1233,8 @@ fn match_params() -> Result<(), Box> { } } "/api/joker/batman/robin/1" => { - path: "/api/{*wildcard}/{param}/{param2}", - value: 1, + route: "/api/{*wildcard}/{param}/{param2}", + data: 1, params: { "wildcard" => "joker/batman", "param" => "robin", @@ -1242,8 +1242,8 @@ fn match_params() -> Result<(), Box> { } } "/api/joker/batman/robin/1/2" => { - path: "/api/{*wildcard}/{param}/{param2}", - value: 1, + route: "/api/{*wildcard}/{param}/{param2}", + data: 1, params: { "wildcard" => "joker/batman/robin", "param" => "1", @@ -1317,38 +1317,38 @@ fn basic() -> Result<(), Box> { assert_router_matches!(router, { "/" => { - path: "/", - value: 0 + route: "/", + data: 0 } "/login" => { - path: "/login", - value: 1 + route: "/login", + data: 1 } "/settings/admin" => { - path: "/settings/{page}", - value: 4, + route: "/settings/{page}", + data: 4, params: { "page" => "admin" } } "/viz-rs" => { - path: "/{user}", - value: 5, + route: "/{user}", + data: 5, params: { "user" => "viz-rs" } } "/viz-rs/path-tree" => { - path: "/{user}/{repo}", - value: 6, + route: "/{user}/{repo}", + data: 6, params: { "user" => "viz-rs", "repo" => "path-tree" } } "/rust-lang/rust-analyzer/releases/download/2022-09-12/rust-analyzer-aarch64-apple-darwin.gz" => { - path: "/{org}/{repo}/releases/download/{tag}/{filename}.{ext}", - value: 8, + route: "/{org}/{repo}/releases/download/{tag}/{filename}.{ext}", + data: 8, params: { "org" => "rust-lang", "repo" => "rust-analyzer", @@ -1358,8 +1358,8 @@ fn basic() -> Result<(), Box> { } } "/rust-lang/rust-analyzer/tags/2022-09-12" => { - path: "/{org}/{repo}/tags/{day}-{month}-{year}", - value: 9, + route: "/{org}/{repo}/tags/{day}-{month}-{year}", + data: 9, params: { "org" => "rust-lang", "repo" => "rust-analyzer", @@ -1369,8 +1369,8 @@ fn basic() -> Result<(), Box> { } } "/rust-lang/rust-analyzer/actions/ci:bench" => { - path: "/{org}/{repo}/actions/{name}:{verb}", - value: 10, + route: "/{org}/{repo}/actions/{name}:{verb}", + data: 10, params: { "org" => "rust-lang", "repo" => "rust-analyzer", @@ -1379,8 +1379,8 @@ fn basic() -> Result<(), Box> { } } "/rust-lang/rust-analyzer/stargazers" => { - path: "/{org}/{repo}/{page}", - value: 11, + route: "/{org}/{repo}/{page}", + data: 11, params: { "org" => "rust-lang", "repo" => "rust-analyzer", @@ -1388,8 +1388,8 @@ fn basic() -> Result<(), Box> { } } "/rust-lang/rust-analyzer/stargazers/404" => { - path: "/{org}/{repo}/{*path}", - value: 12, + route: "/{org}/{repo}/{*path}", + data: 12, params: { "org" => "rust-lang", "repo" => "rust-analyzer", @@ -1397,15 +1397,15 @@ fn basic() -> Result<(), Box> { } } "/public/js/main.js" => { - path: "/public/{*any}", - value: 7, + route: "/public/{*any}", + data: 7, params: { "any" => "js/main.js" } } "/api/v1" => { - path: "/api/{*plus}", - value: 13, + route: "/api/{*plus}", + data: 13, params: { "plus" => "v1" } @@ -1730,20 +1730,20 @@ fn github_tree() -> Result<(), Box> { assert_router_matches!(router, { "/rust-lang/rust" => { - path: "/{org}/{repo}", - value: 2400, + route: "/{org}/{repo}", + data: 2400, params: { "org" => "rust-lang", "repo" => "rust" } } "/settings" => { - path: "/settings", - value: 20 + route: "/settings", + data: 20 } "/rust-lang/rust/actions/runs/1" => { - path: "/{org}/{repo}/actions/runs/{id}", - value: 2442, + route: "/{org}/{repo}/actions/runs/{id}", + data: 2442, params: { "org" => "rust-lang", "repo" => "rust", @@ -1753,8 +1753,8 @@ fn github_tree() -> Result<(), Box> { // NOTE: Different behaviour: path-tree would match "/{org}/{repo}/{*path}" "/rust-lang/rust/" => None "/rust-lang/rust/any" => { - path: "/{org}/{repo}/{*path}", - value: 3000, + route: "/{org}/{repo}/{*path}", + data: 3000, params: { "org" => "rust-lang", "repo" => "rust", @@ -1763,8 +1763,8 @@ fn github_tree() -> Result<(), Box> { } // NOTE: Different behaviour: path-tree would match "/{org}/{repo}/{*path}" "/rust-lang/rust/releases/" => { - path: "/{org}/{repo}/{*path}", - value: 3000, + route: "/{org}/{repo}/{*path}", + data: 3000, params: { "org" => "rust-lang", "repo" => "rust", @@ -1772,8 +1772,8 @@ fn github_tree() -> Result<(), Box> { } } "/rust-lang/rust-analyzer/releases/download/2022-09-12/rust-analyzer-aarch64-apple-darwin.gz" => { - path: "/{org}/{repo}/releases/download/{tag}/{filename}.{ext}", - value: 3002, + route: "/{org}/{repo}/releases/download/{tag}/{filename}.{ext}", + data: 3002, params: { "org" => "rust-lang", "repo" => "rust-analyzer", @@ -1809,8 +1809,8 @@ fn test_dots_no_ext() -> Result<(), Box> { assert_router_matches!(router, { "/abc.xyz.123" => { - path: "/{name}", - value: 1, + route: "/{name}", + data: 1, params: { "name" => "abc.xyz.123" } @@ -1831,15 +1831,15 @@ fn test_dots_ext() -> Result<(), Box> { assert_router_matches!(router, { "/abc.xyz.123" => { - path: "/{+name}.123", - value: 2, + route: "/{+name}.123", + data: 2, params: { "name" => "abc.xyz" } } "/abc.xyz.123.456" => { - path: "/{*name}.123.456", - value: 1, + route: "/{*name}.123.456", + data: 1, params: { "name" => "abc.xyz" } @@ -1865,36 +1865,36 @@ fn test_dots_ext_no_qualifier() -> Result<(), Box> { assert_router_matches!(router, { "/node.js" => { - path: "/{name}.js", - value: 2, + route: "/{name}.js", + data: 2, params: { "name" => "node" } } "/path.lib.js" => { - path: "/{name}.js", - value: 2, + route: "/{name}.js", + data: 2, params: { "name" => "path.lib" } } "/node.js.js" => { - path: "/{name}.js", - value: 2, + route: "/{name}.js", + data: 2, params: { "name" => "node.js" } } "/node.js.gz" => { - path: "/{name}.js.gz", - value: 1, + route: "/{name}.js.gz", + data: 1, params: { "name" => "node" } } "/node.js.gz.js.gz" => { - path: "/{name}.js.gz", - value: 1, + route: "/{name}.js.gz", + data: 1, params: { "name" => "node.js.gz" } diff --git a/tests/poem.rs b/tests/poem.rs index a56c5758..be389120 100644 --- a/tests/poem.rs +++ b/tests/poem.rs @@ -253,53 +253,53 @@ fn test_matches() -> Result<(), Box> { assert_router_matches!(router, { "/ab/def" => { - path: "/ab/def", - value: 1 + route: "/ab/def", + data: 1 } "/abc/def" => { - path: "/abc/def", - value: 2 + route: "/abc/def", + data: 2 } "/abc/cde" => { - path: "/abc/{p1}", - value: 3, + route: "/abc/{p1}", + data: 3, params: { "p1" => "cde" } } "/abc/cde/def" => { - path: "/abc/{p1}/def", - value: 4, + route: "/abc/{p1}/def", + data: 4, params: { "p1" => "cde" } } "/abc/cde/hjk" => { - path: "/abc/{p1}/{p2}", - value: 5, + route: "/abc/{p1}/{p2}", + data: 5, params: { "p1" => "cde", "p2" => "hjk" } } "/abc/def/iop/123" => { - path: "/abc/def/{*p1}", - value: 6, + route: "/abc/def/{*p1}", + data: 6, params: { "p1" => "iop/123" } } "/a/b/k/c" => { - path: "/a/{p1}/{p2}/c", - value: 8, + route: "/a/{p1}/{p2}/c", + data: 8, params: { "p1" => "b", "p2" => "k" } } "/kcd/uio" => { - path: "/{*p1}", - value: 9, + route: "/{*p1}", + data: 9, params: { "p1" => "kcd/uio" } @@ -307,22 +307,22 @@ fn test_matches() -> Result<(), Box> { // NOTE: Different behaviour: poem would match "/{*p1}" "/" => None "/abc/123/def" => { - path: "/abc/{param:digit_string}/def", - value: 10, + route: "/abc/{param:digit_string}/def", + data: 10, params: { "param" => "123" } } "/kcd/567" => { - path: "/kcd/{p1:digit_string}", - value: 11, + route: "/kcd/{p1:digit_string}", + data: 11, params: { "p1" => "567" } } "/is-number/-/is-number-7.0.0.tgz" => { - path: "/{package}/-/{package_tgz:ends_with_tgz}", - value: 12, + route: "/{package}/-/{package_tgz:ends_with_tgz}", + data: 12, params: { "package" => "is-number", "package_tgz" => "is-number-7.0.0.tgz" @@ -348,8 +348,8 @@ fn test_match_priority() -> Result<(), Box> { assert_router_matches!(router, { "/a/123" => { - path: "/a/{*path}", - value: 2, + route: "/a/{*path}", + data: 2, params: { "path" => "123" } @@ -368,8 +368,8 @@ fn test_match_priority() -> Result<(), Box> { assert_router_matches!(router, { "/a/123" => { - path: "/a/{id}", - value: 3, + route: "/a/{id}", + data: 3, params: { "id" => "123" } @@ -390,8 +390,8 @@ fn test_match_priority() -> Result<(), Box> { assert_router_matches!(router, { "/a/123" => { - path: "/a/{id:digit_string}", - value: 4, + route: "/a/{id:digit_string}", + data: 4, params: { "id" => "123" } @@ -412,8 +412,8 @@ fn test_match_priority() -> Result<(), Box> { assert_router_matches!(router, { "/a/123" => { - path: "/a/123", - value: 5 + route: "/a/123", + data: 5 } }); @@ -433,8 +433,8 @@ fn test_catch_all_priority_in_sub_path() -> Result<(), Box> { assert_router_matches!(router, { "/a/b/c/123" => { - path: "/a/{*path}", - value: 1, + route: "/a/{*path}", + data: 1, params: { "path" => "b/c/123" } @@ -453,8 +453,8 @@ fn test_catch_all_priority_in_sub_path() -> Result<(), Box> { assert_router_matches!(router, { "/a/b/c/123" => { - path: "/a/b/{*path}", - value: 2, + route: "/a/b/{*path}", + data: 2, params: { "path" => "c/123" } @@ -475,8 +475,8 @@ fn test_catch_all_priority_in_sub_path() -> Result<(), Box> { assert_router_matches!(router, { "/a/b/c/123" => { - path: "/a/b/c/{*path}", - value: 3, + route: "/a/b/c/{*path}", + data: 3, params: { "path" => "123" } @@ -503,15 +503,15 @@ fn test_issue_275() -> Result<(), Box> { assert_router_matches!(router, { "/abc/a" => { - path: "/{id1}/a", - value: 1, + route: "/{id1}/a", + data: 1, params: { "id1" => "abc" } } "/def/b" => { - path: "/{id2}/b", - value: 2, + route: "/{id2}/b", + data: 2, params: { "id2" => "def" } @@ -534,15 +534,15 @@ fn test_percent_decoded() -> Result<(), Box> { assert_router_matches!(router, { "/a/abc" => { - path: "/a/{id}", - value: 1, + route: "/a/{id}", + data: 1, params: { "id" => "abc" } } "/a/%E4%BD%A0%E5%A5%BD" => { - path: "/a/{id}", - value: 1, + route: "/a/{id}", + data: 1, params: { "id" => "你好" } diff --git a/tests/uncommon.rs b/tests/uncommon.rs index 28898faa..bddf2a83 100644 --- a/tests/uncommon.rs +++ b/tests/uncommon.rs @@ -50,141 +50,141 @@ fn uncommon() -> Result<(), Box> { assert_router_matches!(router, { // Japanese (Konnichiwa) "/こんにちは" => { - path: "/こんにちは", - value: 0 + route: "/こんにちは", + data: 0 } "/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF" => { - path: "/こんにちは", - value: 0 + route: "/こんにちは", + data: 0 } "/こんにちわ" => None // Russian (Privet) "/привет" => { - path: "/привет", - value: 1 + route: "/привет", + data: 1 } "/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82" => { - path: "/привет", - value: 1 + route: "/привет", + data: 1 } "/привет!" => None // Chinese (Nǐ Hǎo) "/你好" => { - path: "/你好", - value: 2 + route: "/你好", + data: 2 } "/%E4%BD%A0%E5%A5%BD" => { - path: "/你好", - value: 2 + route: "/你好", + data: 2 } "/你们好" => None // Arabic Numerals (full-width) "/123" => { - path: "/123", - value: 3 + route: "/123", + data: 3 } "/%EF%BC%91%EF%BC%92%EF%BC%93" => { - path: "/123", - value: 3 + route: "/123", + data: 3 } "/123" => None // Null Byte "/null\0byte" => { - path: "/null\0byte", - value: 4 + route: "/null\0byte", + data: 4 } "/null%00byte" => { - path: "/null\0byte", - value: 4 + route: "/null\0byte", + data: 4 } "/nullbyte" => None // Emoji "/⚽️🏀🏈" => { - path: "/⚽️🏀🏈", - value: 5 + route: "/⚽️🏀🏈", + data: 5 } "/%E2%9A%BD%EF%B8%8F%F0%9F%8F%80%F0%9F%8F%88" => { - path: "/⚽️🏀🏈", - value: 5 + route: "/⚽️🏀🏈", + data: 5 } "/⚽️🏀" => None // Unicode "/♔♕♖♗♘♙" => { - path: "/♔♕♖♗♘♙", - value: 6 + route: "/♔♕♖♗♘♙", + data: 6 } "/%E2%99%94%E2%99%95%E2%99%96%E2%99%97%E2%99%98%E2%99%99" => { - path: "/♔♕♖♗♘♙", - value: 6 + route: "/♔♕♖♗♘♙", + data: 6 } "/♔♕♖♗♘♟" => None // Unicode Normalization "/cafe\u{0301}" => { - path: "/cafe\u{0301}", - value: 7 + route: "/cafe\u{0301}", + data: 7 } "/café" => { - path: "/café", - value: 8 + route: "/café", + data: 8 } "/cafe%CC%81" => { - path: "/cafe\u{0301}", - value: 7 + route: "/cafe\u{0301}", + data: 7 } "/caf%C3%A9" => { - path: "/café", - value: 8 + route: "/café", + data: 8 } "/cafe" => None // Unicode Zero Width "/abc\u{200B}123" => { - path: "/abc\u{200B}123", - value: 9 + route: "/abc\u{200B}123", + data: 9 } "/abc%E2%80%8B123" => { - path: "/abc\u{200B}123", - value: 9 + route: "/abc\u{200B}123", + data: 9 } "/abc123" => None // Unicode Right to Left "/hello\u{202E}dlrow" => { - path: "/hello\u{202E}dlrow", - value: 10 + route: "/hello\u{202E}dlrow", + data: 10 } "/hello%E2%80%AEdlrow" => { - path: "/hello\u{202E}dlrow", - value: 10 + route: "/hello\u{202E}dlrow", + data: 10 } "/helloworld" => None // Unicode Whitespace "/\u{2000}\u{2001}\u{2002}" => { - path: "/\u{2000}\u{2001}\u{2002}", - value: 11 + route: "/\u{2000}\u{2001}\u{2002}", + data: 11 } "/%E2%80%80%E2%80%81%E2%80%82" => { - path: "/\u{2000}\u{2001}\u{2002}", - value: 11 + route: "/\u{2000}\u{2001}\u{2002}", + data: 11 } "/ " => None // Unicode Control "/\u{0001}\u{0002}\u{0003}" => { - path: "/\u{0001}\u{0002}\u{0003}", - value: 12 + route: "/\u{0001}\u{0002}\u{0003}", + data: 12 } "/%01%02%03" => { - path: "/\u{0001}\u{0002}\u{0003}", - value: 12 + route: "/\u{0001}\u{0002}\u{0003}", + data: 12 } "/123" => None });