use std::future::Future; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; use std::rc::Rc; use std::cell::RefCell; use crate::{Service, ServiceFactory}; /// Convert `Fn(Config, &mut Service1) -> Future` fn to a service factory pub fn apply_cfg( srv: T, f: F, ) -> impl ServiceFactory< Config = C, Request = S::Request, Response = S::Response, Error = S::Error, Service = S, InitError = E, Future = R, > + Clone where F: FnMut(C, &mut T) -> R, T: Service, R: Future>, S: Service, { ApplyConfigService { srv: Rc::new(RefCell::new((srv, f))), _t: PhantomData, } } /// Convert `Fn(Config, &mut Service1) -> Future` fn to a service factory /// /// Service1 get constructed from `T` factory. pub fn apply_cfg_factory( factory: T, f: F, ) -> impl ServiceFactory< Config = C, Request = S::Request, Response = S::Response, Error = S::Error, Service = S, InitError = T::InitError, > + Clone where F: FnMut(C, &mut T::Service) -> R, T: ServiceFactory, T::InitError: From, R: Future>, S: Service, { ApplyConfigServiceFactory { srv: Rc::new(RefCell::new((factory, f))), _t: PhantomData, } } /// Convert `Fn(Config, &mut Server) -> Future` fn to NewService\ struct ApplyConfigService where F: FnMut(C, &mut T) -> R, T: Service, R: Future>, S: Service, { srv: Rc>, _t: PhantomData<(C, R, S)>, } impl Clone for ApplyConfigService where F: FnMut(C, &mut T) -> R, T: Service, R: Future>, S: Service, { fn clone(&self) -> Self { ApplyConfigService { srv: self.srv.clone(), _t: PhantomData, } } } impl ServiceFactory for ApplyConfigService where F: FnMut(C, &mut T) -> R, T: Service, R: Future>, S: Service, { type Config = C; type Request = S::Request; type Response = S::Response; type Error = S::Error; type Service = S; type InitError = E; type Future = R; fn new_service(&self, cfg: C) -> Self::Future { let (t, f) = &mut *self.srv.borrow_mut(); f(cfg, t) } } /// Convert `Fn(&Config) -> Future` fn to NewService struct ApplyConfigServiceFactory where F: FnMut(C, &mut T::Service) -> R, T: ServiceFactory, R: Future>, S: Service, { srv: Rc>, _t: PhantomData<(C, R, S)>, } impl Clone for ApplyConfigServiceFactory where F: FnMut(C, &mut T::Service) -> R, T: ServiceFactory, R: Future>, S: Service, { fn clone(&self) -> Self { Self { srv: self.srv.clone(), _t: PhantomData, } } } impl ServiceFactory for ApplyConfigServiceFactory where F: FnMut(C, &mut T::Service) -> R, T: ServiceFactory, T::InitError: From, R: Future>, S: Service, { type Config = C; type Request = S::Request; type Response = S::Response; type Error = S::Error; type Service = S; type InitError = T::InitError; type Future = ApplyConfigServiceFactoryResponse; fn new_service(&self, cfg: C) -> Self::Future { ApplyConfigServiceFactoryResponse { cfg: Some(cfg), store: self.srv.clone(), state: State::A(self.srv.borrow().0.new_service(())), } } } #[pin_project::pin_project] struct ApplyConfigServiceFactoryResponse where F: FnMut(C, &mut T::Service) -> R, T: ServiceFactory, T::InitError: From, R: Future>, S: Service, { cfg: Option, store: Rc>, #[pin] state: State, } #[pin_project::pin_project(project = StateProj)] enum State where T: ServiceFactory, T::InitError: From, R: Future>, S: Service, { A(#[pin] T::Future), B(T::Service), C(#[pin] R), } impl Future for ApplyConfigServiceFactoryResponse where F: FnMut(C, &mut T::Service) -> R, T: ServiceFactory, T::InitError: From, R: Future>, S: Service, { type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.as_mut().project(); match this.state.as_mut().project() { StateProj::A(fut) => match fut.poll(cx)? { Poll::Pending => Poll::Pending, Poll::Ready(srv) => { this.state.set(State::B(srv)); self.poll(cx) } }, StateProj::B(srv) => match srv.poll_ready(cx)? { Poll::Ready(_) => { { let (_, f) = &mut *this.store.borrow_mut(); let fut = f(this.cfg.take().unwrap(), srv); this.state.set(State::C(fut)); } self.poll(cx) } Poll::Pending => Poll::Pending, }, StateProj::C(fut) => fut.poll(cx), } } }