tower/load_shed/
future.rs

1//! Future types
2
3use std::fmt;
4use std::future::Future;
5use std::pin::Pin;
6use std::task::{Context, Poll};
7
8use futures_core::ready;
9use pin_project_lite::pin_project;
10
11use super::error::Overloaded;
12
13pin_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
23pin_project! {
24    #[project = ResponseStateProj]
25    enum ResponseState<F> {
26        Called {
27            #[pin]
28            fut: F
29        },
30        Overloaded,
31    }
32}
33
34impl<F> ResponseFuture<F> {
35    pub(crate) fn called(fut: F) -> Self {
36        ResponseFuture {
37            state: ResponseState::Called { fut },
38        }
39    }
40
41    pub(crate) fn overloaded() -> Self {
42        ResponseFuture {
43            state: ResponseState::Overloaded,
44        }
45    }
46}
47
48impl<F, T, E> Future for ResponseFuture<F>
49where
50    F: Future<Output = Result<T, E>>,
51    E: Into<crate::BoxError>,
52{
53    type Output = Result<T, crate::BoxError>;
54
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
65impl<F> fmt::Debug for ResponseFuture<F>
66where
67    // bounds for future-proofing...
68    F: fmt::Debug,
69{
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        f.write_str("ResponseFuture")
72    }
73}