//! 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_lite::pin_project; use super::error::Overloaded; pin_project! { /// Future for the [`LoadShed`] service. /// /// [`LoadShed`]: crate::load_shed::LoadShed pub struct ResponseFuture { #[pin] state: ResponseState, } } pin_project! { #[project = ResponseStateProj] enum ResponseState { Called { #[pin] fut: 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") } }