1use crate::trie::Route;
4use crate::trie::{Converter, ParamInfo};
5use fastapi_types::Method;
6
7#[derive(Debug)]
9pub struct RouteMatch<'a> {
10 pub route: &'a Route,
12 pub params: Vec<(&'a str, &'a str)>,
14}
15
16impl<'a> RouteMatch<'a> {
17 #[must_use]
19 pub fn get_param(&self, name: &str) -> Option<&str> {
20 self.params
21 .iter()
22 .find(|(n, _)| *n == name)
23 .map(|(_, v)| *v)
24 }
25
26 #[must_use]
28 pub fn param_count(&self) -> usize {
29 self.params.len()
30 }
31
32 #[must_use]
34 pub fn is_empty(&self) -> bool {
35 self.params.is_empty()
36 }
37
38 pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> + '_ {
40 self.params.iter().map(|(k, v)| (*k, *v))
41 }
42
43 #[must_use]
45 pub fn is_param_uuid(&self, name: &str) -> Option<bool> {
46 self.route
47 .path_params
48 .iter()
49 .find(|p: &&ParamInfo| p.name == name)
50 .map(|p| p.converter == Converter::Uuid)
51 }
52
53 pub fn get_param_int(&self, name: &str) -> Option<Result<i64, std::num::ParseIntError>> {
55 self.get_param(name).map(str::parse::<i64>)
56 }
57
58 pub fn get_param_i32(&self, name: &str) -> Option<Result<i32, std::num::ParseIntError>> {
60 self.get_param(name).map(str::parse::<i32>)
61 }
62
63 pub fn get_param_u64(&self, name: &str) -> Option<Result<u64, std::num::ParseIntError>> {
65 self.get_param(name).map(str::parse::<u64>)
66 }
67
68 pub fn get_param_u32(&self, name: &str) -> Option<Result<u32, std::num::ParseIntError>> {
70 self.get_param(name).map(str::parse::<u32>)
71 }
72
73 pub fn get_param_float(&self, name: &str) -> Option<Result<f64, std::num::ParseFloatError>> {
75 self.get_param(name).map(str::parse::<f64>)
76 }
77
78 pub fn get_param_f32(&self, name: &str) -> Option<Result<f32, std::num::ParseFloatError>> {
80 self.get_param(name).map(str::parse::<f32>)
81 }
82}
83
84#[derive(Debug)]
86pub enum RouteLookup<'a> {
87 Match(RouteMatch<'a>),
89 MethodNotAllowed { allowed: AllowedMethods },
91 NotFound,
93}
94
95#[derive(Debug, Clone)]
97pub struct AllowedMethods {
98 methods: Vec<Method>,
99}
100
101impl AllowedMethods {
102 #[must_use]
107 pub fn new(mut methods: Vec<Method>) -> Self {
108 if methods.contains(&Method::Get) && !methods.contains(&Method::Head) {
109 methods.push(Method::Head);
110 }
111 methods.sort_by_key(method_order);
112 methods.dedup();
113 Self { methods }
114 }
115
116 #[must_use]
118 pub fn methods(&self) -> &[Method] {
119 &self.methods
120 }
121
122 #[must_use]
124 pub fn contains(&self, method: Method) -> bool {
125 self.methods.contains(&method)
126 }
127
128 #[must_use]
130 pub fn header_value(&self) -> String {
131 let mut out = String::new();
132 for (idx, method) in self.methods.iter().enumerate() {
133 if idx > 0 {
134 out.push_str(", ");
135 }
136 out.push_str(method.as_str());
137 }
138 out
139 }
140}
141
142fn method_order(method: &Method) -> u8 {
143 match *method {
144 Method::Get => 0,
145 Method::Head => 1,
146 Method::Post => 2,
147 Method::Put => 3,
148 Method::Delete => 4,
149 Method::Patch => 5,
150 Method::Options => 6,
151 Method::Trace => 7,
152 }
153}