reep 0.2.0

[deprecated] REsource EndPoint (REEP): Generic Iron Endpoint for RESTlike Resource Access
Documentation
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> {
    //hm, maybe inline this allways. But, compiler should know better...
    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"
    }
}

//TODO use url content part end/decoding

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(())
    }
}