1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! # `matchit`
//!
//! [](https://docs.rs/matchit)
//! [](https://crates.io/crates/matchit)
//! [](https://crates.io/crates/matchit)
//!
//! A blazing fast URL router.
//!
//! ```rust
//! use matchit::Router;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut router = Router::new();
//! router.insert("/home", "Welcome!")?;
//! router.insert("/users/:id", "A User")?;
//!
//! let matched = router.at("/users/978")?;
//! assert_eq!(matched.params.get("id"), Some("978"));
//! assert_eq!(*matched.value, "A User");
//! # Ok(())
//! # }
//! ```
//!
//! ## Parameters
//!
//! Along with static routes, the router also supports dynamic route segments. These can either be named or catch-all parameters:
//!
//! ### Named Parameters
//!
//! Named parameters like `/:id` match anything until the next `/` or the end of the path:
//!
//! ```rust
//! # use matchit::Router;
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut m = Router::new();
//! m.insert("/users/:id", true)?;
//!
//! assert_eq!(m.at("/users/1")?.params.get("id"), Some("1"));
//! assert_eq!(m.at("/users/23")?.params.get("id"), Some("23"));
//! assert!(m.at("/users").is_err());
//!
//! # Ok(())
//! # }
//! ```
//!
//! ### Catch-all Parameters
//!
//! Catch-all parameters start with `*` and match everything after the `/`. They must always be at the **end** of the route:
//!
//! ```rust
//! # use matchit::Router;
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut m = Router::new();
//! m.insert("/*p", true)?;
//!
//! assert_eq!(m.at("/foo.js")?.params.get("p"), Some("foo.js"));
//! assert_eq!(m.at("/c/bar.css")?.params.get("p"), Some("c/bar.css"));
//!
//! // note that this would not match
//! assert!(m.at("/").is_err());
//!
//! # Ok(())
//! # }
//! ```
//!
//! ## Routing Priority
//!
//! Static and dynamic route segments are allowed to overlap. If they do, static segments will be given higher priority:
//!
//! ```rust
//! # use matchit::Router;
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut m = Router::new();
//! m.insert("/", "Welcome!").unwrap() ; // priority: 1
//! m.insert("/about", "About Me").unwrap(); // priority: 1
//! m.insert("/*filepath", "...").unwrap(); // priority: 2
//!
//! # Ok(())
//! # }
//! ```
//!
//! ## How does it work?
//!
//! The router takes advantage of the fact that URL routes generally follow a hierarchical structure. Routes are stored them in a radix trie that makes heavy use of common prefixes:
//!
//! ```text
//! Priority Path Value
//! 9 \ 1
//! 3 ├s None
//! 2 |├earch\ 2
//! 1 |└upport\ 3
//! 2 ├blog\ 4
//! 1 | └:post None
//! 1 | └\ 5
//! 2 ├about-us\ 6
//! 1 | └team\ 7
//! 1 └contact\ 8
//! ```
//!
//! This allows us to reduce the route search to a small number of branches. Child nodes on the same level of the tree are also prioritized
//! by the number of children with registered values, increasing the chance of choosing the correct branch of the first try.
pub use ;
pub use ;
pub use ;