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