use std::error::Error as StdError;
use std::any::Any;
use std::marker::PhantomData;
use std::borrow::Borrow;
use std::fmt;
use iron::{IronResult, Request};
use iron::status;
use iron::middleware::BeforeMiddleware;
use types::{Id, ParserMiddleware};
use router::Router;
use iron::error::IronError;
use url::percent_encoding::percent_decode;
pub struct ActualParserMiddleware<T: ParserMiddleware>(T);
impl<T: ParserMiddleware> ActualParserMiddleware<T> {
pub fn new(val: T) -> ActualParserMiddleware<T> {
ActualParserMiddleware(val)
}
}
impl<T: ParserMiddleware> BeforeMiddleware for ActualParserMiddleware<T> {
fn before(&self, req: &mut Request) -> IronResult<()> {
let value = try!(self.0.parse(req));
req.extensions.insert::<T>(value);
Ok(())
}
}
pub struct IdParser<I> {
_phantom: PhantomData<I>
}
impl<I> IdParser<I> {
pub fn new() -> IdParser<I> {
IdParser {
_phantom: PhantomData
}
}
}
#[derive(Debug)]
pub struct MissingIdError;
impl fmt::Display for MissingIdError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "MissingIdError")
}
}
impl StdError for MissingIdError {
fn description(&self) -> &'static str {
"id is missing"
}
}
impl<I: Send+Sync+Any> BeforeMiddleware for IdParser<I>
where I: Id
{
fn before<'a, 'b>(&'a self, req: &'b mut Request) -> IronResult<()> {
let id = if let Some(raw_id) = req.extensions.get::<Router>().unwrap().find("resource_id") {
try!(I::Value::parse(percent_decode(raw_id.as_bytes()).decode_utf8_lossy().borrow()))
} else {
return Err(IronError::new(MissingIdError, (status::BadRequest, "id is missing")));
};
req.extensions.insert::<I>(id);
Ok(())
}
}