use std::collections::BTreeMap;
use std::str::FromStr;
use crate::handler::{Error, Matcher, Result, Scope};
use crate::http::Method;
use crate::middleware::TryIntoMiddleware;
use crate::router::{Action, Route};
use super::Routes;
#[allow(clippy::type_complexity)]
#[derive(Debug)]
pub struct Builder {
routes: BTreeMap<Method, Vec<(String, Box<dyn Action>)>>,
}
impl Builder {
#[allow(clippy::new_without_default)]
#[must_use]
pub fn new() -> Self {
Self { routes: BTreeMap::new() }
}
pub fn add<P, A>(&mut self, method: Method, path: P, action: A)
where
P: Into<String>,
A: Action,
{
self.routes
.entry(method)
.or_default()
.push((path.into(), Box::new(action)));
}
}
impl TryIntoMiddleware for Builder {
type Output = Routes;
fn try_into_middleware(self, scope: &Scope) -> Result<Self::Output> {
let base = match scope.route.as_ref() {
Some(route) => route,
None => &Route::default(),
};
let iter = self.routes.into_iter().map(|(method, items)| {
let mut matcher = Matcher::new();
for (path, action) in items {
let path = Route::from_str(&path)
.map_err(|err| Error::Matcher(err.into()))?;
matcher.add(base.append(path), action)?;
}
Ok((method, matcher))
});
iter.collect::<Result<BTreeMap<_, _>>>()
.map(|routes| Routes { matchers: routes })
}
}