1 use pin_project_lite::pin_project;
2 use std::{
3     future::Future,
4     pin::Pin,
5     task::{Context, Poll},
6 };
7 
8 pin_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 
17 pin_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 
31 impl<F, E> Inner<F, E> {
future(fut: F) -> Self32     fn future(fut: F) -> Self {
33         Self::Future { fut }
34     }
35 
error(error: Option<E>) -> Self36     fn error(error: Option<E>) -> Self {
37         Self::Error { error }
38     }
39 }
40 
41 impl<F, E> ResponseFuture<F, E> {
new(inner: F) -> Self42     pub(crate) fn new(inner: F) -> Self {
43         ResponseFuture {
44             inner: Inner::future(inner),
45         }
46     }
47 
error(error: E) -> Self48     pub(crate) fn error(error: E) -> Self {
49         ResponseFuture {
50             inner: Inner::error(Some(error)),
51         }
52     }
53 }
54 
55 impl<F, T, E, ME> Future for ResponseFuture<F, ME>
56 where
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 
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>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 }
74