use std::sync::Arc;
use crate::middleware::Middleware;
use crate::request::PathParams;
use crate::Next;
pub enum MatchWhen<State> {
Exact(Arc<dyn Middleware<State>>),
Partial(Arc<dyn Middleware<State>>),
}
pub struct Endpoint<'a, State> {
inner: via_router::Endpoint<'a, Vec<MatchWhen<State>>>,
}
pub struct Router<State> {
inner: via_router::Router<Vec<MatchWhen<State>>>,
}
impl<'a, State> Endpoint<'a, State> {
pub fn at(&mut self, pattern: &'static str) -> Endpoint<State> {
Endpoint {
inner: self.inner.at(pattern),
}
}
pub fn scope<T>(&mut self, scope: T) -> &mut Self
where
T: FnOnce(&mut Self),
{
scope(self);
self
}
pub fn param(&self) -> Option<&str> {
self.inner.param().map(|name| name.as_str())
}
pub fn include<T>(&mut self, middleware: T) -> &mut Self
where
T: Middleware<State> + 'static,
{
let middleware = Arc::new(middleware);
self.route_mut().push(MatchWhen::Partial(middleware));
self
}
pub fn respond<T>(&mut self, responder: T) -> &mut Self
where
T: Middleware<State> + 'static,
{
let responder = Arc::new(responder);
self.route_mut().push(MatchWhen::Exact(responder));
self
}
fn route_mut(&mut self) -> &mut Vec<MatchWhen<State>> {
self.inner.get_or_insert_route_with(Vec::new)
}
}
impl<State> Router<State>
where
State: Send + Sync + 'static,
{
pub fn new() -> Self {
Self {
inner: via_router::Router::new(),
}
}
pub fn at(&mut self, pattern: &'static str) -> Endpoint<State> {
Endpoint {
inner: self.inner.at(pattern),
}
}
pub fn lookup(&self, path: &str, params: &mut PathParams) -> Next<State> {
let mut stack = Vec::new();
for found in self.inner.visit(path).into_iter().rev() {
if let Some(param) = found.param {
params.push((param, found.at));
}
let route = match found.route.and_then(|key| self.inner.get(key)) {
Some(route) => route,
None => continue,
};
for middleware in route.iter().rev().filter_map(|when| match when {
MatchWhen::Exact(exact) if found.is_leaf => Some(exact),
MatchWhen::Partial(partial) => Some(partial),
MatchWhen::Exact(_) => None,
}) {
stack.push(Arc::clone(middleware));
}
}
Next::new(stack)
}
}