use std::collections::HashMap;
use std::sync::Arc;
use request::SapperRequest;
use response::SapperResponse;
use handler::SapperHandler;
use app::Result;
use app::Error;
use app::PathParams;
use app::Key;
use hyper::method::Method;
use recognizer::Router as Recognizer;
use recognizer::{Match, Params};
impl Key for PathParams { type Value = Params; }
pub struct Router {
routers: HashMap<Method, Recognizer<Arc<Box<dyn SapperHandler>>>>,
wildcard: Recognizer<Arc<Box<dyn SapperHandler>>>
}
impl Router {
pub fn new() -> Router {
Router {
routers: HashMap::new(),
wildcard: Recognizer::new()
}
}
pub fn route<S>(&mut self, method: Method,
glob: S, handler: Arc<Box<dyn SapperHandler>>) -> &mut Router
where S: AsRef<str> {
self.routers.entry(method).or_insert(Recognizer::new())
.add(glob.as_ref(), handler);
self
}
fn recognize(&self, method: &Method, path: &str)
-> Option<Match<&Arc<Box<dyn SapperHandler>>>> {
self.routers.get(method).and_then(|router| router.recognize(path).ok())
.or(self.wildcard.recognize(path).ok())
}
pub fn handle_method(&self, req: &mut SapperRequest, path: &str) -> Result<SapperResponse> {
if let Some(matched) = self.recognize(req.method(), path) {
req.ext_mut().insert::<PathParams>(matched.params);
matched.handler.handle(req)
} else {
Err(Error::NotFound)
}
}
}