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