use std::marker::PhantomData; use futures::future::Future; use futures::{try_ready, Async, IntoFuture, Poll}; use crate::cell::Cell; use crate::{IntoService, NewService, Service}; /// Convert `Fn(&Config, &mut Service) -> Future` fn to a NewService pub fn apply_cfg(srv: T, f: F) -> ApplyConfigService where F: FnMut(&C, &mut T) -> R, T: Service, R: IntoFuture, R::Item: IntoService, S: Service, { ApplyConfigService { f: Cell::new(f), srv: Cell::new(srv.into_service()), _t: PhantomData, } } /// Convert `Fn(&Config) -> Future` fn to NewService pub struct ApplyConfigService where F: FnMut(&C, &mut T) -> R, T: Service, R: IntoFuture, R::Item: IntoService, S: Service, { f: Cell, srv: Cell, _t: PhantomData<(C, R, S)>, } impl Clone for ApplyConfigService where F: FnMut(&C, &mut T) -> R, T: Service, R: IntoFuture, R::Item: IntoService, S: Service, { fn clone(&self) -> Self { ApplyConfigService { f: self.f.clone(), srv: self.srv.clone(), _t: PhantomData, } } } impl NewService for ApplyConfigService where F: FnMut(&C, &mut T) -> R, T: Service, R: IntoFuture, R::Item: IntoService, S: Service, { type Config = C; type Request = S::Request; type Response = S::Response; type Error = S::Error; type Service = S; type InitError = R::Error; type Future = FnNewServiceConfigFut; fn new_service(&self, cfg: &C) -> Self::Future { FnNewServiceConfigFut { fut: unsafe { (self.f.get_mut_unsafe())(cfg, self.srv.get_mut_unsafe()) } .into_future(), _t: PhantomData, } } } pub struct FnNewServiceConfigFut where R: IntoFuture, R::Item: IntoService, S: Service, { fut: R::Future, _t: PhantomData<(S,)>, } 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())) } }