xitca_router/lib.rs
1//! A fork of [matchit](https://github.com/ibraheemdev/matchit) using small string type for params lifetime elision.
2//!
3//! ```rust
4//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
5//! let mut router = xitca_router::Router::new();
6//! router.insert("/home", "Welcome!")?;
7//! router.insert("/users/:id", "A User")?;
8//!
9//! let matched = router.at("/users/978")?;
10//! assert_eq!(*matched.value, "A User");
11//!
12//! // params is owned value that can be sent between threads.
13//! let params = matched.params;
14//! std::thread::spawn(move || {
15//! assert_eq!(params.get("id"), Some("978"));
16//! })
17//! .join()
18//! .unwrap();
19//! # Ok(())
20//! # }
21//! ```
22//!
23//! ## Parameters
24//!
25//! Along with static routes, the router also supports dynamic route segments. These can either be named or catch-all parameters:
26//!
27//! ### Named Parameters
28//!
29//! Named parameters like `/:id` match anything until the next `/` or the end of the path:
30//!
31//! ```rust
32//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
33//! let mut m = xitca_router::Router::new();
34//! m.insert("/users/:id", true)?;
35//!
36//! assert_eq!(m.at("/users/1")?.params.get("id"), Some("1"));
37//! assert_eq!(m.at("/users/23")?.params.get("id"), Some("23"));
38//! assert!(m.at("/users").is_err());
39//!
40//! # Ok(())
41//! # }
42//! ```
43//!
44//! ### Catch-all Parameters
45//!
46//! Catch-all parameters start with `*` and match everything after the `/`.
47//! They must always be at the **end** of the route:
48//!
49//! ```rust
50//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
51//! let mut m = xitca_router::Router::new();
52//! m.insert("/*p", true)?;
53//!
54//! assert_eq!(m.at("/foo.js")?.params.get("p"), Some("foo.js"));
55//! assert_eq!(m.at("/c/bar.css")?.params.get("p"), Some("c/bar.css"));
56//!
57//! # Ok(())
58//! # }
59//! ```
60//!
61//! ### Relaxed Catch-all Parameters
62//!
63//! Relaxed Catch-all parameters with a single `*` and match everything after the `/`(Including `/` itself).
64//! Since there is no identifier for Params key associated they are left empty.
65//! They must always be at the **end** of the route:
66//!
67//! ```rust
68//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
69//! let mut m = xitca_router::Router::new();
70//! m.insert("/*", true)?;
71//!
72//! assert!(m.at("/")?.value);
73//! assert!(m.at("/foo")?.value);
74//!
75//! # Ok(())
76//! # }
77//! ```
78//!
79//! ## Routing Priority
80//!
81//! Static and dynamic route segments are allowed to overlap. If they do, static segments will be given higher priority:
82//!
83//! ```rust
84//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
85//! let mut m = xitca_router::Router::new();
86//! m.insert("/", "Welcome!").unwrap() ; // priority: 1
87//! m.insert("/about", "About Me").unwrap(); // priority: 1
88//! m.insert("/*filepath", "...").unwrap(); // priority: 2
89//!
90//! # Ok(())
91//! # }
92//! ```
93
94#![forbid(unsafe_code)]
95
96mod error;
97mod router;
98mod tree;
99
100pub mod params;
101
102pub use error::{InsertError, MatchError};
103pub use router::{Match, Router};