use super::Pattern;
use crate::Endpoint;
use std::pin::Pin;
use std::sync::Arc;
pub(crate) struct Route {
pub(crate) path: String,
pub(crate) pattern: Pattern,
method: Option<http::Method>,
endpoint: Pin<Box<dyn Endpoint>>,
}
impl Route {
pub(crate) fn method(&self) -> Option<&http::Method> {
self.method.as_ref()
}
pub(crate) fn endpoint(&self) -> &Pin<Box<dyn Endpoint>> {
&self.endpoint
}
pub(crate) fn matches(&self, method: &http::Method) -> bool {
self.method.is_none() || self.method.as_ref() == Some(method)
}
}
impl std::fmt::Debug for Route {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Route")
.field("path", &self.path)
.field("method", &self.method)
.field("endpoint", &self.endpoint)
.finish_non_exhaustive()
}
}
#[derive(Debug)]
pub struct Path<'a> {
pub(super) prefix: String,
pub(super) builder: &'a mut Vec<Arc<Route>>,
pub(super) pattern: Option<Pattern>,
}
macro_rules! method {
($($(#[$m:meta])* $v:vis fn $n:ident = $meth:expr;)+) => {
$(
$(#[$m])* $v fn $n<E: Endpoint>(&mut self, endpoint: E) -> &mut Self {
self.method($meth, endpoint)
}
)+
};
}
impl<'a> Path<'a> {
pub(super) fn new(prefix: impl Into<String>, builder: &'a mut Vec<Arc<Route>>) -> Self {
Path {
prefix: prefix.into(),
builder,
pattern: None,
}
}
pub fn at<P: AsRef<str>>(&mut self, path: P) -> Path<'_> {
Path::new(super::join_paths(&self.prefix, path.as_ref()), self.builder)
}
pub fn under<P: AsRef<str>, F: FnOnce(&mut Path<'_>)>(&mut self, path: P, f: F) -> &mut Self {
let mut base = self.at(path);
f(&mut base);
self
}
pub fn all<E: Endpoint>(&mut self, endpoint: E) -> &mut Self {
let pattern = self.create_pattern();
self.builder.push(Arc::new(Route {
path: self.prefix.clone(),
pattern,
method: None,
endpoint: Box::pin(endpoint),
}));
self
}
pub fn method<E: Endpoint>(&mut self, method: http::Method, endpoint: E) -> &mut Self {
let pattern = self.create_pattern();
self.builder.push(Arc::new(Route {
path: self.prefix.clone(),
pattern,
method: Some(method),
endpoint: Box::pin(endpoint),
}));
self
}
method![
pub fn get = http::Method::GET;
pub fn post = http::Method::POST;
pub fn options = http::Method::OPTIONS;
pub fn put = http::Method::PUT;
pub fn delete = http::Method::DELETE;
pub fn head = http::Method::HEAD;
pub fn trace = http::Method::TRACE;
pub fn connect = http::Method::CONNECT;
pub fn patch = http::Method::PATCH;
];
fn create_pattern(&mut self) -> Pattern {
if let Some(pattern) = self.pattern.clone() {
pattern
} else {
let pattern = Pattern::new(&self.prefix);
self.pattern = Some(pattern.clone());
pattern
}
}
}