use std::cell::RefCell; use std::marker::PhantomData; use std::rc::Rc; use actix_http::{Error, Extensions, Response}; use actix_service::{NewService, Service, Void}; use futures::future::{ok, FutureResult}; use futures::{try_ready, Async, Future, IntoFuture, Poll}; use crate::extract::FromRequest; use crate::request::HttpRequest; use crate::responder::Responder; use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; /// Handler converter factory pub trait Factory: Clone where R: Responder, { fn call(&self, param: T) -> R; } impl Factory<(), R> for F where F: Fn() -> R + Clone + 'static, R: Responder + 'static, { fn call(&self, _: ()) -> R { (self)() } } #[doc(hidden)] pub struct Handler where F: Factory, R: Responder, { hnd: F, _t: PhantomData<(T, R)>, } impl Handler where F: Factory, R: Responder, { pub fn new(hnd: F) -> Self { Handler { hnd, _t: PhantomData, } } } impl NewService for Handler where F: Factory, R: Responder + 'static, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; type InitError = (); type Service = HandlerService; type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { ok(HandlerService { hnd: self.hnd.clone(), _t: PhantomData, }) } } #[doc(hidden)] pub struct HandlerService where F: Factory, R: Responder + 'static, { hnd: F, _t: PhantomData<(T, R)>, } impl Service for HandlerService where F: Factory, R: Responder + 'static, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; type Future = HandlerServiceResponse<::Future>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future { let fut = self.hnd.call(param).respond_to(&req).into_future(); HandlerServiceResponse { fut, req: Some(req), } } } pub struct HandlerServiceResponse { fut: T, req: Option, } impl Future for HandlerServiceResponse where T: Future, T::Error: Into, { type Item = ServiceResponse; type Error = Void; fn poll(&mut self) -> Poll { match self.fut.poll() { Ok(Async::Ready(res)) => Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res, ))), Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { let res: Response = e.into().into(); Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res, ))) } } } } /// Async handler converter factory pub trait AsyncFactory: Clone + 'static where R: IntoFuture, R::Item: Into, R::Error: Into, { fn call(&self, param: T) -> R; } impl AsyncFactory<(), R> for F where F: Fn() -> R + Clone + 'static, R: IntoFuture, R::Item: Into, R::Error: Into, { fn call(&self, _: ()) -> R { (self)() } } #[doc(hidden)] pub struct AsyncHandler where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { hnd: F, _t: PhantomData<(T, R)>, } impl AsyncHandler where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { pub fn new(hnd: F) -> Self { AsyncHandler { hnd, _t: PhantomData, } } } impl NewService for AsyncHandler where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Error; type InitError = (); type Service = AsyncHandlerService; type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { ok(AsyncHandlerService { hnd: self.hnd.clone(), _t: PhantomData, }) } } #[doc(hidden)] pub struct AsyncHandlerService where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { hnd: F, _t: PhantomData<(T, R)>, } impl Service for AsyncHandlerService where F: AsyncFactory, R: IntoFuture, R::Item: Into, R::Error: Into, { type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Error; type Future = AsyncHandlerServiceResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future { AsyncHandlerServiceResponse { fut: self.hnd.call(param).into_future(), req: Some(req), } } } #[doc(hidden)] pub struct AsyncHandlerServiceResponse { fut: T, req: Option, } impl Future for AsyncHandlerServiceResponse where T: Future, T::Item: Into, T::Error: Into, { type Item = ServiceResponse; type Error = Error; fn poll(&mut self) -> Poll { match self.fut.poll() { Ok(Async::Ready(res)) => Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res.into(), ))), Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { let res: Response = e.into().into(); Ok(Async::Ready(ServiceResponse::new( self.req.take().unwrap(), res, ))) } } } } /// Extract arguments from request pub struct Extract> { config: Rc>>>, _t: PhantomData<(P, T)>, } impl> Extract { pub fn new(config: Rc>>>) -> Self { Extract { config, _t: PhantomData, } } } impl> NewService for Extract { type Request = ServiceRequest

; type Response = (T, HttpRequest); type Error = (Error, ServiceFromRequest

); type InitError = (); type Service = ExtractService; type Future = FutureResult; fn new_service(&self, _: &()) -> Self::Future { ok(ExtractService { _t: PhantomData, config: self.config.borrow().clone(), }) } } pub struct ExtractService> { config: Option>, _t: PhantomData<(P, T)>, } impl> Service for ExtractService { type Request = ServiceRequest

; type Response = (T, HttpRequest); type Error = (Error, ServiceFromRequest

); type Future = ExtractResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, req: ServiceRequest

) -> Self::Future { let mut req = ServiceFromRequest::new(req, self.config.clone()); ExtractResponse { fut: T::from_request(&mut req).into_future(), req: Some(req), } } } pub struct ExtractResponse> { req: Option>, fut: ::Future, } impl> Future for ExtractResponse { type Item = (T, HttpRequest); type Error = (Error, ServiceFromRequest

); fn poll(&mut self) -> Poll { let item = try_ready!(self .fut .poll() .map_err(|e| (e.into(), self.req.take().unwrap()))); let req = self.req.take().unwrap(); let req = req.into_request(); Ok(Async::Ready((item, req))) } } /// FromRequest trait impl for tuples macro_rules! factory_tuple ({ $(($n:tt, $T:ident)),+} => { impl Factory<($($T,)+), Res> for Func where Func: Fn($($T,)+) -> Res + Clone + 'static, Res: Responder + 'static, { fn call(&self, param: ($($T,)+)) -> Res { (self)($(param.$n,)+) } } impl AsyncFactory<($($T,)+), Res> for Func where Func: Fn($($T,)+) -> Res + Clone + 'static, Res: IntoFuture + 'static, Res::Item: Into, Res::Error: Into, { fn call(&self, param: ($($T,)+)) -> Res { (self)($(param.$n,)+) } } }); #[rustfmt::skip] mod m { use super::*; factory_tuple!((0, A)); factory_tuple!((0, A), (1, B)); factory_tuple!((0, A), (1, B), (2, C)); factory_tuple!((0, A), (1, B), (2, C), (3, D)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I)); factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J)); }