use std::rc::Rc; use std::cell::UnsafeCell; use std::marker::PhantomData; use serde::de::DeserializeOwned; use futures::{Async, Future, Poll}; use error::Error; use handler::{Handler, Reply, ReplyItem, Responder}; use httprequest::HttpRequest; use httpresponse::HttpResponse; use extractor::HttpRequestExtractor; /// Trait defines object that could be registered as route handler #[allow(unused_variables)] pub trait WithHandler: 'static where D: HttpRequestExtractor, T: DeserializeOwned, S: 'static { /// The type of value that handler will return. type Result: Responder; /// Handle request fn handle(&mut self, data: D) -> Self::Result; } /// WithHandler for Fn() impl WithHandler for F where F: Fn(D) -> R + 'static, R: Responder + 'static, D: HttpRequestExtractor, T: DeserializeOwned, S: 'static, { type Result = R; fn handle(&mut self, item: D) -> R { (self)(item) } } pub(crate) fn with(h: H) -> With where H: WithHandler, D: HttpRequestExtractor, T: DeserializeOwned, { With{hnd: Rc::new(UnsafeCell::new(h)), _t: PhantomData, _d: PhantomData, _s: PhantomData} } pub struct With where H: WithHandler, D: HttpRequestExtractor, T: DeserializeOwned, S: 'static, { hnd: Rc>, _t: PhantomData, _d: PhantomData, _s: PhantomData, } impl Handler for With where H: WithHandler, D: HttpRequestExtractor, T: DeserializeOwned, T: 'static, D: 'static, S: 'static, H: 'static { type Result = Reply; fn handle(&mut self, req: HttpRequest) -> Self::Result { let fut = Box::new(D::extract(&req)); Reply::async( WithHandlerFut{ req, hnd: Rc::clone(&self.hnd), fut1: Some(fut), fut2: None, _t: PhantomData, _d: PhantomData, }) } } struct WithHandlerFut where H: WithHandler, D: HttpRequestExtractor, T: DeserializeOwned, T: 'static, D: 'static, S: 'static { hnd: Rc>, req: HttpRequest, fut1: Option>>, fut2: Option>>, _t: PhantomData, _d: PhantomData, } impl Future for WithHandlerFut where H: WithHandler, D: HttpRequestExtractor, T: DeserializeOwned, T: 'static, D: 'static, S: 'static { type Item = HttpResponse; type Error = Error; fn poll(&mut self) -> Poll { if let Some(ref mut fut) = self.fut2 { return fut.poll() } let item = match self.fut1.as_mut().unwrap().poll()? { Async::Ready(item) => item, Async::NotReady => return Ok(Async::NotReady), }; let hnd: &mut H = unsafe{&mut *self.hnd.get()}; let item = match hnd.handle(item) .respond_to(self.req.without_state()) { Ok(item) => item.into(), Err(err) => return Err(err.into()), }; match item.into() { ReplyItem::Message(resp) => return Ok(Async::Ready(resp)), ReplyItem::Future(fut) => self.fut2 = Some(fut), } self.poll() } }