use crate::trie::Route;
use crate::trie::{Converter, ParamInfo};
use fastapi_types::Method;
#[derive(Debug)]
pub struct RouteMatch<'a> {
pub route: &'a Route,
pub params: Vec<(&'a str, &'a str)>,
}
impl<'a> RouteMatch<'a> {
#[must_use]
pub fn get_param(&self, name: &str) -> Option<&str> {
self.params
.iter()
.find(|(n, _)| *n == name)
.map(|(_, v)| *v)
}
#[must_use]
pub fn param_count(&self) -> usize {
self.params.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.params.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> + '_ {
self.params.iter().map(|(k, v)| (*k, *v))
}
#[must_use]
pub fn is_param_uuid(&self, name: &str) -> Option<bool> {
self.route
.path_params
.iter()
.find(|p: &&ParamInfo| p.name == name)
.map(|p| p.converter == Converter::Uuid)
}
pub fn get_param_int(&self, name: &str) -> Option<Result<i64, std::num::ParseIntError>> {
self.get_param(name).map(str::parse::<i64>)
}
pub fn get_param_i32(&self, name: &str) -> Option<Result<i32, std::num::ParseIntError>> {
self.get_param(name).map(str::parse::<i32>)
}
pub fn get_param_u64(&self, name: &str) -> Option<Result<u64, std::num::ParseIntError>> {
self.get_param(name).map(str::parse::<u64>)
}
pub fn get_param_u32(&self, name: &str) -> Option<Result<u32, std::num::ParseIntError>> {
self.get_param(name).map(str::parse::<u32>)
}
pub fn get_param_float(&self, name: &str) -> Option<Result<f64, std::num::ParseFloatError>> {
self.get_param(name).map(str::parse::<f64>)
}
pub fn get_param_f32(&self, name: &str) -> Option<Result<f32, std::num::ParseFloatError>> {
self.get_param(name).map(str::parse::<f32>)
}
}
#[derive(Debug)]
pub enum RouteLookup<'a> {
Match(RouteMatch<'a>),
MethodNotAllowed { allowed: AllowedMethods },
NotFound,
}
#[derive(Debug, Clone)]
pub struct AllowedMethods {
methods: Vec<Method>,
}
impl AllowedMethods {
#[must_use]
pub fn new(mut methods: Vec<Method>) -> Self {
if methods.contains(&Method::Get) && !methods.contains(&Method::Head) {
methods.push(Method::Head);
}
methods.sort_by_key(method_order);
methods.dedup();
Self { methods }
}
#[must_use]
pub fn methods(&self) -> &[Method] {
&self.methods
}
#[must_use]
pub fn contains(&self, method: Method) -> bool {
self.methods.contains(&method)
}
#[must_use]
pub fn header_value(&self) -> String {
let mut out = String::new();
for (idx, method) in self.methods.iter().enumerate() {
if idx > 0 {
out.push_str(", ");
}
out.push_str(method.as_str());
}
out
}
}
fn method_order(method: &Method) -> u8 {
match *method {
Method::Get => 0,
Method::Head => 1,
Method::Post => 2,
Method::Put => 3,
Method::Delete => 4,
Method::Patch => 5,
Method::Options => 6,
Method::Trace => 7,
}
}