use std::rc::Rc; use std::collections::HashMap; use error::UrlGenerationError; use resource::Resource; use recognizer::{Params, RouteRecognizer, PatternElement}; /// Interface for application router. pub struct Router(Rc>>); impl Router { pub(crate) fn new(prefix: &str, map: HashMap>) -> Router { let prefix = prefix.trim().trim_right_matches('/').to_owned(); let mut resources = Vec::new(); for (path, resource) in map { resources.push((path, resource.get_name(), resource)) } Router(Rc::new(RouteRecognizer::new(prefix, resources))) } /// Router prefix #[inline] pub(crate) fn prefix(&self) -> &str { self.0.prefix() } /// Query for matched resource pub fn query(&self, path: &str) -> Option<(Option, &Resource)> { self.0.recognize(path) } /// Check if application contains matching route. pub fn has_route(&self, path: &str) -> bool { self.0.recognize(path).is_some() } /// Build named resource path. /// /// Check [`HttpRequest::url_for()`](../struct.HttpRequest.html#method.url_for) /// for detailed information. pub fn resource_path(&self, name: &str, elements: U) -> Result where U: IntoIterator, I: AsRef, { if let Some(pattern) = self.0.get_pattern(name) { let mut path = String::from(self.prefix()); path.push('/'); let mut iter = elements.into_iter(); for el in pattern.elements() { match *el { PatternElement::Str(ref s) => path.push_str(s), PatternElement::Var(_) => { if let Some(val) = iter.next() { path.push_str(val.as_ref()) } else { return Err(UrlGenerationError::NotEnoughElements) } } } } Ok(path) } else { Err(UrlGenerationError::ResourceNotFound) } } } impl Clone for Router { fn clone(&self) -> Router { Router(Rc::clone(&self.0)) } }