//! Future types use std::fmt; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; use futures_core::ready; use pin_project::pin_project; use super::error::Overloaded; /// Future for the `LoadShed` service. #[pin_project] pub struct ResponseFuture { #[pin] state: ResponseState, } #[pin_project(project = ResponseStateProj)] enum ResponseState { Called(#[pin] F), Overloaded, } impl ResponseFuture { pub(crate) fn called(fut: F) -> Self { ResponseFuture { state: ResponseState::Called(fut), } } pub(crate) fn overloaded() -> Self { ResponseFuture { state: ResponseState::Overloaded, } } } impl Future for ResponseFuture where F: Future>, E: Into, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.project().state.project() { ResponseStateProj::Called(fut) => Poll::Ready(ready!(fut.poll(cx)).map_err(Into::into)), ResponseStateProj::Overloaded => Poll::Ready(Err(Overloaded::new().into())), } } } impl fmt::Debug for ResponseFuture where // bounds for future-proofing... F: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("ResponseFuture") } }