use std::str::FromStr;
use crate::handler::matcher::{Matcher, Route};
use crate::handler::{Error, Result, Scope, TryIntoHandler};
use crate::middleware::{Middleware, TryIntoMiddleware};
use super::factory::Factory;
use super::Stack;
#[derive(Debug)]
pub struct Builder {
middlewares: Vec<Box<dyn Factory>>,
}
impl Builder {
pub(crate) fn new() -> Self {
Self { middlewares: Vec::new() }
}
pub(crate) fn push<M>(&mut self, middleware: M)
where
M: TryIntoMiddleware,
{
self.middlewares.push(Box::new(|scope: &Scope| {
middleware
.try_into_middleware(scope)
.map(|middleware| Box::new(middleware) as Box<dyn Middleware>)
}));
}
#[inline]
pub fn with<M>(mut self, middleware: M) -> Self
where
M: TryIntoMiddleware,
{
self.push(middleware);
self
}
}
impl TryIntoMiddleware for Builder {
type Output = Stack;
fn try_into_middleware(self, scope: &Scope) -> Result<Self::Output> {
let route = scope.route.as_ref();
let matcher = route
.map(|base| -> Result<_> {
let mut matcher = Matcher::new();
let rest = Route::from_str("/{*rest}")
.map_err(|err| Error::Matcher(err.into()))?;
matcher
.add(base.append(rest), ())
.map_err(Into::into)
.map(|()| matcher)
})
.transpose()?;
let iter = self.middlewares.into_iter().map(|f| f(scope));
iter.collect::<Result<_>>()
.map(|middlewares| Stack { middlewares, matcher })
}
}
impl TryIntoHandler for Builder {
type Output = Stack;
fn try_into_handler(self) -> Result<Self::Output> {
let scope = Scope::default();
self.try_into_middleware(&scope)
}
}