1 //! Future types 2 3 use std::fmt; 4 use std::future::Future; 5 use std::pin::Pin; 6 use std::task::{Context, Poll}; 7 8 use futures_core::ready; 9 use pin_project_lite::pin_project; 10 11 use super::error::Overloaded; 12 13 pin_project! { 14 /// Future for the [`LoadShed`] service. 15 /// 16 /// [`LoadShed`]: crate::load_shed::LoadShed 17 pub struct ResponseFuture<F> { 18 #[pin] 19 state: ResponseState<F>, 20 } 21 } 22 23 pin_project! { 24 #[project = ResponseStateProj] 25 enum ResponseState<F> { 26 Called { 27 #[pin] 28 fut: F 29 }, 30 Overloaded, 31 } 32 } 33 34 impl<F> ResponseFuture<F> { called(fut: F) -> Self35 pub(crate) fn called(fut: F) -> Self { 36 ResponseFuture { 37 state: ResponseState::Called { fut }, 38 } 39 } 40 overloaded() -> Self41 pub(crate) fn overloaded() -> Self { 42 ResponseFuture { 43 state: ResponseState::Overloaded, 44 } 45 } 46 } 47 48 impl<F, T, E> Future for ResponseFuture<F> 49 where 50 F: Future<Output = Result<T, E>>, 51 E: Into<crate::BoxError>, 52 { 53 type Output = Result<T, crate::BoxError>; 54 poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>55 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 56 match self.project().state.project() { 57 ResponseStateProj::Called { fut } => { 58 Poll::Ready(ready!(fut.poll(cx)).map_err(Into::into)) 59 } 60 ResponseStateProj::Overloaded => Poll::Ready(Err(Overloaded::new().into())), 61 } 62 } 63 } 64 65 impl<F> fmt::Debug for ResponseFuture<F> 66 where 67 // bounds for future-proofing... 68 F: fmt::Debug, 69 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 71 f.write_str("ResponseFuture") 72 } 73 } 74