use std::collections::HashMap;
use std::iter::{Iterator, FlatMap};
use std::slice::Split;
use std::ops::Deref;
use hyper::method::Method;
use handler::Handler;
use context::MaybeUtf8Owned;
use context::hypermedia::Link;
pub use self::tree_router::TreeRouter;
mod tree_router;
pub struct Endpoint<'a, T: 'a> {
pub handler: Option<&'a T>,
pub variables: HashMap<MaybeUtf8Owned, MaybeUtf8Owned>,
pub hyperlinks: Vec<Link<'a>>
}
impl<'a, T> From<Option<&'a T>> for Endpoint<'a, T> {
fn from(handler: Option<&'a T>) -> Endpoint<'a, T> {
Endpoint {
handler: handler,
variables: HashMap::new(),
hyperlinks: vec![]
}
}
}
pub trait Router: Send + Sync + 'static {
type Handler: Handler;
fn insert<'a, D: ?Sized + Deref<Target=R> + 'a, R: ?Sized + Route<'a> + 'a>(&mut self, method: Method, route: &'a D, handler: Self::Handler);
fn find<'a>(&'a self, method: &Method, route: &[u8]) -> Endpoint<'a, Self::Handler>;
}
impl<H: Handler> Router for H {
type Handler = H;
fn find<'a>(&'a self, _method: &Method, _route: &[u8]) -> Endpoint<'a, H> {
Some(self).into()
}
fn insert<'a, D: ?Sized + Deref<Target=R> + 'a, R: ?Sized + Route<'a> + 'a>(&mut self, _method: Method, _route: &'a D, _handler: H) {}
}
pub trait Route<'a> {
type Segments: Iterator<Item=&'a [u8]>;
fn segments(&'a self) -> <Self as Route<'a>>::Segments;
}
fn is_slash(c: &u8) -> bool {
*c == b'/'
}
impl<'a> Route<'a> for str {
type Segments = RouteIter<Split<'a, u8, fn(&u8) -> bool>>;
fn segments(&'a self) -> <Self as Route<'a>>::Segments {
self.as_bytes().segments()
}
}
impl<'a> Route<'a> for [u8] {
type Segments = RouteIter<Split<'a, u8, fn(&u8) -> bool>>;
fn segments(&'a self) -> <Self as Route<'a>>::Segments {
let s = if self.starts_with(b"/") {
&self[1..]
} else {
self
};
let s = if s.ends_with(b"/") {
&s[..s.len() - 1]
} else {
s
};
if s.len() == 0 {
RouteIter::Root
} else {
RouteIter::Path(s.split(is_slash))
}
}
}
impl<'a, 'b: 'a, I: 'a, T: 'a> Route<'a> for I where
&'a I: IntoIterator<Item=&'a T>,
T: Deref,
<T as Deref>::Target: Route<'a> + 'b
{
type Segments = FlatMap<<&'a I as IntoIterator>::IntoIter, <<T as Deref>::Target as Route<'a>>::Segments, fn(&'a T) -> <<T as Deref>::Target as Route<'a>>::Segments>;
fn segments(&'a self) -> Self::Segments {
fn segments<'a, 'b: 'a, T: Deref<Target=R> + 'b, R: ?Sized + Route<'a, Segments=S> + 'b, S: Iterator<Item=&'a[u8]>>(s: &'a T) -> S {
s.segments()
}
self.into_iter().flat_map(segments)
}
}
pub enum RouteIter<I: Iterator> {
Root,
Path(I)
}
impl<I: Iterator> Iterator for RouteIter<I> {
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
match self {
&mut RouteIter::Path(ref mut i) => i.next(),
&mut RouteIter::Root => None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
&RouteIter::Path(ref i) => i.size_hint(),
&RouteIter::Root => (0, Some(0))
}
}
}