use std::future::Future; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; use futures::future::{ok, Ready}; use pin_project::pin_project; use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory}; /// Create `ServiceFactory` for function that can act as a `Service` pub fn service_fn( f: F, ) -> impl ServiceFactory + Clone where F: FnMut(Req) -> Fut + Clone, Fut: Future>, { NewServiceFn::new(f) } pub fn service_fn2( f: F, ) -> impl Service where F: FnMut(Req) -> Fut, Fut: Future>, { ServiceFn::new(f) } /// Create `ServiceFactory` for function that can produce services pub fn factory_fn( f: F, ) -> impl ServiceFactory< Config = Cfg, Service = S, Request = S::Request, Response = S::Response, Error = S::Error, InitError = Err, Future = Fut, > where S: Service, F: Fn() -> Fut, Fut: Future>, { FnNewServiceNoConfig::new(f) } /// Create `ServiceFactory` for function that can produce services with configuration pub fn factory_fn_cfg( f: F, ) -> impl ServiceFactory< Config = Cfg, Service = Srv, Request = Srv::Request, Response = Srv::Response, Error = Srv::Error, InitError = Err, > where F: Fn(&Cfg) -> Fut, Fut: Future>, Srv: Service, { FnNewServiceConfig::new(f) } pub struct ServiceFn where F: FnMut(Req) -> Fut, Fut: Future>, { f: F, _t: PhantomData, } impl ServiceFn where F: FnMut(Req) -> Fut, Fut: Future>, { pub(crate) fn new(f: F) -> Self { ServiceFn { f, _t: PhantomData } } } impl Clone for ServiceFn where F: FnMut(Req) -> Fut + Clone, Fut: Future>, { fn clone(&self) -> Self { ServiceFn::new(self.f.clone()) } } impl Service for ServiceFn where F: FnMut(Req) -> Fut, Fut: Future>, { type Request = Req; type Response = Res; type Error = Err; type Future = Fut; fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: Req) -> Self::Future { (self.f)(req) } } impl IntoService> for F where F: FnMut(Req) -> Fut, Fut: Future>, { fn into_service(self) -> ServiceFn { ServiceFn::new(self) } } struct NewServiceFn where F: FnMut(Req) -> Fut, Fut: Future>, { f: F, _t: PhantomData<(Req, Cfg)>, } impl NewServiceFn where F: FnMut(Req) -> Fut + Clone, Fut: Future>, { fn new(f: F) -> Self { NewServiceFn { f, _t: PhantomData } } } impl Clone for NewServiceFn where F: FnMut(Req) -> Fut + Clone, Fut: Future>, { fn clone(&self) -> Self { NewServiceFn::new(self.f.clone()) } } impl ServiceFactory for NewServiceFn where F: FnMut(Req) -> Fut + Clone, Fut: Future>, { type Request = Req; type Response = Res; type Error = Err; type Config = Cfg; type Service = ServiceFn; type InitError = (); type Future = Ready>; fn new_service(&self, _: &Cfg) -> Self::Future { ok(ServiceFn::new(self.f.clone())) } } /// Convert `Fn(&Config) -> Future` fn to NewService struct FnNewServiceConfig where F: Fn(&Cfg) -> Fut, Fut: Future>, Srv: Service, { f: F, _t: PhantomData<(Fut, Cfg, Srv, Err)>, } impl FnNewServiceConfig where F: Fn(&Cfg) -> Fut, Fut: Future>, Srv: Service, { pub fn new(f: F) -> Self { FnNewServiceConfig { f, _t: PhantomData } } } impl ServiceFactory for FnNewServiceConfig where F: Fn(&Cfg) -> Fut, Fut: Future>, Srv: Service, { type Request = Srv::Request; type Response = Srv::Response; type Error = Srv::Error; type Config = Cfg; type Service = Srv; type InitError = Err; type Future = FnNewServiceConfigFut; fn new_service(&self, cfg: &Cfg) -> Self::Future { FnNewServiceConfigFut { fut: (self.f)(cfg), _t: PhantomData, } } } #[pin_project] struct FnNewServiceConfigFut where R: Future>, S: Service, { #[pin] fut: R, _t: PhantomData<(S,)>, } impl Future for FnNewServiceConfigFut where R: Future>, S: Service, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Poll::Ready(Ok(futures::ready!(self.project().fut.poll(cx))?)) } } /// Converter for `Fn() -> Future` fn pub struct FnNewServiceNoConfig where F: Fn() -> R, R: Future>, S: Service, { f: F, _t: PhantomData, } impl FnNewServiceNoConfig where F: Fn() -> R, R: Future>, S: Service, { fn new(f: F) -> Self { FnNewServiceNoConfig { f, _t: PhantomData } } } impl ServiceFactory for FnNewServiceNoConfig where F: Fn() -> R, R: Future>, S: Service, { type Request = S::Request; type Response = S::Response; type Error = S::Error; type Service = S; type Config = C; type InitError = E; type Future = R; fn new_service(&self, _: &C) -> Self::Future { (self.f)() } } impl Clone for FnNewServiceNoConfig where F: Fn() -> R + Clone, R: Future>, S: Service, { fn clone(&self) -> Self { Self::new(self.f.clone()) } } impl IntoServiceFactory> for F where F: Fn() -> R, R: Future>, S: Service, { fn into_factory(self) -> FnNewServiceNoConfig { FnNewServiceNoConfig::new(self) } }