use std::fmt; use std::{ future::Future, pin::Pin, task::{Context, Poll}, }; use tower_service::Service; /// Returns a new [`FutureService`] for the given future. /// /// A [`FutureService`] allows you to treat a future that resolves to a service as a service. This /// can be useful for services that are created asynchronously. /// /// # Example /// ``` /// use tower::{service_fn, Service, ServiceExt}; /// use tower::util::future_service; /// use std::convert::Infallible; /// /// # fn main() { /// # async { /// // A future which outputs a type implementing `Service`. /// let future_of_a_service = async { /// let svc = service_fn(|_req: ()| async { Ok::<_, Infallible>("ok") }); /// Ok::<_, Infallible>(svc) /// }; /// /// // Wrap the future with a `FutureService`, allowing it to be used /// // as a service without awaiting the future's completion: /// let mut svc = future_service(Box::pin(future_of_a_service)); /// /// // Now, when we wait for the service to become ready, it will /// // drive the future to completion internally. /// let svc = svc.ready().await.unwrap(); /// let res = svc.call(()).await.unwrap(); /// # }; /// # } /// ``` /// /// # Regarding the [`Unpin`] bound /// /// The [`Unpin`] bound on `F` is necessary because the future will be polled in /// [`Service::poll_ready`] which doesn't have a pinned receiver (it takes `&mut self` and not `self: /// Pin<&mut Self>`). So we cannot put the future into a `Pin` without requiring `Unpin`. /// /// This will most likely come up if you're calling `future_service` with an async block. In that /// case you can use `Box::pin(async { ... })` as shown in the example. pub fn future_service(future: F) -> FutureService where F: Future> + Unpin, S: Service, { FutureService::new(future) } /// A type that implements [`Service`] for a [`Future`] that produces a [`Service`]. /// /// See [`future_service`] for more details. #[derive(Clone)] pub struct FutureService { state: State, } impl FutureService { /// Returns a new [`FutureService`] for the given future. /// /// A [`FutureService`] allows you to treat a future that resolves to a service as a service. This /// can be useful for services that are created asynchronously. /// /// # Example /// ``` /// use tower::{service_fn, Service, ServiceExt}; /// use tower::util::FutureService; /// use std::convert::Infallible; /// /// # fn main() { /// # async { /// // A future which outputs a type implementing `Service`. /// let future_of_a_service = async { /// let svc = service_fn(|_req: ()| async { Ok::<_, Infallible>("ok") }); /// Ok::<_, Infallible>(svc) /// }; /// /// // Wrap the future with a `FutureService`, allowing it to be used /// // as a service without awaiting the future's completion: /// let mut svc = FutureService::new(Box::pin(future_of_a_service)); /// /// // Now, when we wait for the service to become ready, it will /// // drive the future to completion internally. /// let svc = svc.ready().await.unwrap(); /// let res = svc.call(()).await.unwrap(); /// # }; /// # } /// ``` /// /// # Regarding the [`Unpin`] bound /// /// The [`Unpin`] bound on `F` is necessary because the future will be polled in /// [`Service::poll_ready`] which doesn't have a pinned receiver (it takes `&mut self` and not `self: /// Pin<&mut Self>`). So we cannot put the future into a `Pin` without requiring `Unpin`. /// /// This will most likely come up if you're calling `future_service` with an async block. In that /// case you can use `Box::pin(async { ... })` as shown in the example. pub fn new(future: F) -> Self { Self { state: State::Future(future), } } } impl fmt::Debug for FutureService where S: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FutureService") .field("state", &format_args!("{:?}", self.state)) .finish() } } #[derive(Clone)] enum State { Future(F), Service(S), } impl fmt::Debug for State where S: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { State::Future(_) => f .debug_tuple("State::Future") .field(&format_args!("<{}>", std::any::type_name::())) .finish(), State::Service(svc) => f.debug_tuple("State::Service").field(svc).finish(), } } } impl Service for FutureService where F: Future> + Unpin, S: Service, { type Response = S::Response; type Error = E; type Future = S::Future; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { loop { self.state = match &mut self.state { State::Future(fut) => { let fut = Pin::new(fut); let svc = futures_core::ready!(fut.poll(cx)?); State::Service(svc) } State::Service(svc) => return svc.poll_ready(cx), }; } } fn call(&mut self, req: R) -> Self::Future { if let State::Service(svc) = &mut self.state { svc.call(req) } else { panic!("FutureService::call was called before FutureService::poll_ready") } } } #[cfg(test)] mod tests { use super::*; use crate::util::{future_service, ServiceExt}; use crate::Service; use futures::future::{ready, Ready}; use std::convert::Infallible; #[tokio::test] async fn pending_service_debug_impl() { let mut pending_svc = future_service(ready(Ok(DebugService))); assert_eq!( format!("{:?}", pending_svc), "FutureService { state: State::Future(>>) }" ); pending_svc.ready().await.unwrap(); assert_eq!( format!("{:?}", pending_svc), "FutureService { state: State::Service(DebugService) }" ); } #[derive(Debug)] struct DebugService; impl Service<()> for DebugService { type Response = (); type Error = Infallible; type Future = Ready>; fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { Ok(()).into() } fn call(&mut self, _req: ()) -> Self::Future { ready(Ok(())) } } }