use std::marker::PhantomData; use futures::future::{ok, Future, FutureResult}; use futures::{try_ready, Async, IntoFuture, Poll}; use crate::{IntoConfigurableNewService, IntoNewService, IntoService, NewService, Service}; /// Create `NewService` for function that can act as Service pub fn fn_service(f: F) -> FnNewService where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { FnNewService::new(f) } /// Create `NewService` for function that can produce services pub fn fn_factory(f: F) -> FnNewServiceNoConfig where F: Fn() -> R, R: IntoFuture, S: Service, { FnNewServiceNoConfig::new(f) } /// Create `NewService` for function that can produce services with configuration pub fn fn_cfg_factory(f: F) -> FnNewServiceConfig where F: Fn(&C) -> R, R: IntoFuture, R::Item: IntoService, S: Service, { FnNewServiceConfig::new(f) } pub struct FnService where F: FnMut(Req) -> Out, Out: IntoFuture, { f: F, _t: PhantomData<(Req,)>, } impl FnService where F: FnMut(Req) -> Out, Out: IntoFuture, { pub fn new(f: F) -> Self { FnService { f, _t: PhantomData } } } impl Clone for FnService where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { fn clone(&self) -> Self { FnService { f: self.f.clone(), _t: PhantomData, } } } impl Service for FnService where F: FnMut(Req) -> Out, Out: IntoFuture, { type Response = Out::Item; type Error = Out::Error; type Future = Out::Future; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, req: Req) -> Self::Future { (self.f)(req).into_future() } } impl IntoService, Req> for F where F: FnMut(Req) -> Out + 'static, Out: IntoFuture, { fn into_service(self) -> FnService { FnService::new(self) } } pub struct FnNewService where F: FnMut(Req) -> Out, Out: IntoFuture, { f: F, _t: PhantomData<(Req, Cfg)>, } impl FnNewService where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { pub fn new(f: F) -> Self { FnNewService { f, _t: PhantomData } } } impl NewService for FnNewService where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { type Response = Out::Item; type Error = Out::Error; type Service = FnService; type InitError = (); type Future = FutureResult; fn new_service(&self, _: &Cfg) -> Self::Future { ok(FnService::new(self.f.clone())) } } impl Clone for FnNewService where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { fn clone(&self) -> Self { Self::new(self.f.clone()) } } impl IntoNewService, Req, Cfg> for F where F: Fn(Req) -> Out + Clone, Out: IntoFuture, { fn into_new_service(self) -> FnNewService { FnNewService::new(self) } } /// Converter for `Fn() -> Future` fn pub struct FnNewServiceNoConfig where F: Fn() -> R, R: IntoFuture, S: Service, { f: F, _t: PhantomData, } impl FnNewServiceNoConfig where F: Fn() -> R, R: IntoFuture, S: Service, { pub fn new(f: F) -> Self { FnNewServiceNoConfig { f, _t: PhantomData } } } impl NewService for FnNewServiceNoConfig where F: Fn() -> R, R: IntoFuture, S: Service, { type Response = S::Response; type Error = S::Error; type Service = S; type InitError = E; type Future = R::Future; fn new_service(&self, _: &()) -> Self::Future { (self.f)().into_future() } } impl Clone for FnNewServiceNoConfig where F: Fn() -> R + Clone, R: IntoFuture, S: Service, { fn clone(&self) -> Self { Self::new(self.f.clone()) } } impl IntoNewService, Req, ()> for F where F: Fn() -> R, R: IntoFuture, S: Service, { fn into_new_service(self) -> FnNewServiceNoConfig { FnNewServiceNoConfig::new(self) } } /// Convert `Fn(&Config) -> Future` fn to NewService pub struct FnNewServiceConfig where F: Fn(&C) -> R, R: IntoFuture, R::Item: IntoService, S: Service, { f: F, _t: PhantomData<(C, R, S, E, Req)>, } impl FnNewServiceConfig where F: Fn(&C) -> R, R: IntoFuture, R::Item: IntoService, S: Service, { pub fn new(f: F) -> Self { FnNewServiceConfig { f, _t: PhantomData } } } impl NewService for FnNewServiceConfig where F: Fn(&C) -> R, R: IntoFuture, R::Item: IntoService, S: Service, { type Response = S::Response; type Error = S::Error; type Service = S; type InitError = E; type Future = FnNewServiceConfigFut; fn new_service(&self, cfg: &C) -> Self::Future { FnNewServiceConfigFut { fut: (self.f)(cfg).into_future(), _t: PhantomData, } } } pub struct FnNewServiceConfigFut where R: IntoFuture, R::Item: IntoService, S: Service, { fut: R::Future, _t: PhantomData<(S, Req)>, } impl Future for FnNewServiceConfigFut where R: IntoFuture, R::Item: IntoService, S: Service, { type Item = S; type Error = R::Error; fn poll(&mut self) -> Poll { Ok(Async::Ready(try_ready!(self.fut.poll()).into_service())) } } impl Clone for FnNewServiceConfig where F: Fn(&C) -> R + Clone, R: IntoFuture, R::Item: IntoService, S: Service, { fn clone(&self) -> Self { Self::new(self.f.clone()) } } impl IntoConfigurableNewService, Req, C> for F where F: Fn(&C) -> R, R: IntoFuture, R::Item: IntoService, S: Service, { fn into_new_service(self) -> FnNewServiceConfig { FnNewServiceConfig::new(self) } } #[cfg(test)] mod tests { use crate::{IntoService, Service, ServiceExt}; #[test] fn test_fn_service() { let mut rt = actix_rt::Runtime::new().unwrap(); let srv = (|_t: &str| -> Result { Ok(1) }).into_service(); let mut srv = srv.and_then(|test: usize| Ok(test)); let s = "HELLO".to_owned(); let res = rt.block_on(srv.call(&s)).unwrap(); assert_eq!(res, 1); } }