use std::marker::PhantomData; use crate::IntoFuture; use futures::future::{ok, Future, Ready}; use futures::{ready, Poll}; use crate::{IntoNewService, IntoService, NewService, Service}; use std::pin::Pin; use std::task::Context; use pin_project::pin_project; /// Create `NewService` for function that can act as a Service pub fn service_fn(f: F) -> NewServiceFn where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { NewServiceFn::new(f) } /// Create `NewService` for function that can produce services pub fn new_service_fn(f: F) -> FnNewServiceNoConfig where F: Fn() -> R, R: IntoFuture, R::Item: IntoService, S: Service, { FnNewServiceNoConfig::new(f) } /// Create `NewService` for function that can produce services with configuration pub fn new_service_cfg(f: F) -> FnNewServiceConfig where F: Fn(&C) -> R, R: IntoFuture, R::Item: IntoService, S: Service, { FnNewServiceConfig::new(f) } pub struct ServiceFn where F: FnMut(Req) -> Out, Out: IntoFuture, { f: F, _t: PhantomData, } impl ServiceFn where F: FnMut(Req) -> Out, Out: IntoFuture, { pub(crate) fn new(f: F) -> Self { ServiceFn { f, _t: PhantomData } } } impl Clone for ServiceFn where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { fn clone(&self) -> Self { ServiceFn::new(self.f.clone()) } } impl Service for ServiceFn where F: FnMut(Req) -> Out, Out: IntoFuture, { type Request = Req; type Response = Out::Item; type Error = Out::Error; type Future = Out::Future; fn poll_ready( self: Pin<&mut Self>, _ctx: &mut Context<'_>, ) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: Req) -> Self::Future { (self.f)(req).into_future() } } impl IntoService> for F where F: FnMut(Req) -> Out, Out: IntoFuture, { fn into_service(self) -> ServiceFn { ServiceFn::new(self) } } pub struct NewServiceFn where F: FnMut(Req) -> Out, Out: IntoFuture, { f: F, _t: PhantomData<(Req, Cfg)>, } impl NewServiceFn where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { pub(crate) fn new(f: F) -> Self { NewServiceFn { f, _t: PhantomData } } } impl Clone for NewServiceFn where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { fn clone(&self) -> Self { NewServiceFn::new(self.f.clone()) } } impl NewService for NewServiceFn where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { type Request = Req; type Response = Out::Item; type Error = Out::Error; type Config = Cfg; type Service = ServiceFn; type InitError = (); type Future = Ready>; fn new_service(&self, _: &Cfg) -> Self::Future { ok(ServiceFn::new(self.f.clone())) } } impl IntoService> for NewServiceFn where F: FnMut(Req) -> Out + Clone, Out: IntoFuture, { fn into_service(self) -> ServiceFn { ServiceFn::new(self.f.clone()) } } impl IntoNewService> for F where F: Fn(Req) -> Out + Clone, Out: IntoFuture, { fn into_new_service(self) -> NewServiceFn { NewServiceFn::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)>, } 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 Request = S::Request; type Response = S::Response; type Error = S::Error; type Config = C; 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, } } } #[pin_project] pub struct FnNewServiceConfigFut where R: IntoFuture, R::Item: IntoService, S: Service, { #[pin] fut: R::Future, _t: PhantomData<(S,)>, } impl Future for FnNewServiceConfigFut where R: IntoFuture, R::Item: IntoService, S: Service, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Poll::Ready(Ok(ready!(self.project().fut.poll(cx))?.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()) } } /// 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 Request = S::Request; type Response = S::Response; type Error = S::Error; type Service = S; type Config = C; type InitError = E; type Future = R::Future; fn new_service(&self, _: &C) -> 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> for F where F: Fn() -> R, R: IntoFuture, S: Service, { fn into_new_service(self) -> FnNewServiceNoConfig { FnNewServiceNoConfig::new(self) } }