via_router/path/
pattern.rs1use std::fmt::{self, Debug, Display};
2
3#[derive(PartialEq)]
4pub enum Pattern {
5 Root,
6 Static(Param),
7 Dynamic(Param),
8 Wildcard(Param),
9}
10
11#[derive(Debug, PartialEq)]
14pub struct Param {
15 ident: Box<str>,
16}
17
18macro_rules! rest_or {
22 (
23 $segment:expr,
25 $($arg:tt)*
27 ) => {{
28 let segment = $segment;
29 match segment.get(1..) {
30 None | Some("") => panic!($($arg)*),
32 Some(rest) => rest,
34 }
35 }};
36}
37
38pub fn patterns(path: &'static str) -> impl Iterator<Item = Pattern> {
41 super::split(path).into_iter().map(|at| {
42 let end = at.end();
43 let start = at.start();
44 let segment = match path.get(start..end) {
45 Some(slice) => slice,
46 None => panic!("Path segments cannot be empty when defining a route."),
47 };
48
49 match segment.chars().next() {
50 Some(':') => {
54 let rest = rest_or!(segment, "Dynamic parameters must be named. Found ':'.");
55 let param = Param::new(rest);
56
57 Pattern::Dynamic(param)
58 }
59
60 Some('*') => {
64 let rest = rest_or!(segment, "Wildcard parameters must be named. Found '*'.");
65 let param = Param::new(rest);
66
67 Pattern::Wildcard(param)
68 }
69
70 _ => {
73 let param = Param::new(segment);
74 Pattern::Static(param)
75 }
76 }
77 })
78}
79
80impl Param {
81 pub fn as_str(&self) -> &str {
82 &self.ident
83 }
84}
85
86impl Param {
87 pub(crate) fn new(ident: &str) -> Self {
88 Self {
89 ident: ident.into(),
90 }
91 }
92}
93
94impl Clone for Param {
95 fn clone(&self) -> Self {
96 Self {
97 ident: self.ident.clone(),
98 }
99 }
100}
101
102impl Display for Param {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 Display::fmt(&self.ident, f)
105 }
106}