tower/reconnect/
future.rs

1use pin_project_lite::pin_project;
2use std::{
3    future::Future,
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8pin_project! {
9    /// Future that resolves to the response or failure to connect.
10    #[derive(Debug)]
11    pub struct ResponseFuture<F, E> {
12        #[pin]
13        inner: Inner<F, E>,
14    }
15}
16
17pin_project! {
18    #[project = InnerProj]
19    #[derive(Debug)]
20    enum Inner<F, E> {
21        Future {
22            #[pin]
23            fut: F,
24        },
25        Error {
26            error: Option<E>,
27        },
28    }
29}
30
31impl<F, E> Inner<F, E> {
32    fn future(fut: F) -> Self {
33        Self::Future { fut }
34    }
35
36    fn error(error: Option<E>) -> Self {
37        Self::Error { error }
38    }
39}
40
41impl<F, E> ResponseFuture<F, E> {
42    pub(crate) fn new(inner: F) -> Self {
43        ResponseFuture {
44            inner: Inner::future(inner),
45        }
46    }
47
48    pub(crate) fn error(error: E) -> Self {
49        ResponseFuture {
50            inner: Inner::error(Some(error)),
51        }
52    }
53}
54
55impl<F, T, E, ME> Future for ResponseFuture<F, ME>
56where
57    F: Future<Output = Result<T, E>>,
58    E: Into<crate::BoxError>,
59    ME: Into<crate::BoxError>,
60{
61    type Output = Result<T, crate::BoxError>;
62
63    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
64        let me = self.project();
65        match me.inner.project() {
66            InnerProj::Future { fut } => fut.poll(cx).map_err(Into::into),
67            InnerProj::Error { error } => {
68                let e = error.take().expect("Polled after ready.").into();
69                Poll::Ready(Err(e))
70            }
71        }
72    }
73}