use pin_project::pin_project; use std::{ future::Future, pin::Pin, task::{Context, Poll}, }; /// Future that resolves to the response or failure to connect. #[pin_project] #[derive(Debug)] pub struct ResponseFuture { #[pin] inner: Inner, } #[pin_project(project = InnerProj)] #[derive(Debug)] enum Inner { Future(#[pin] F), Error(Option), } impl ResponseFuture { pub(crate) fn new(inner: F) -> Self { ResponseFuture { inner: Inner::Future(inner), } } pub(crate) fn error(error: E) -> Self { ResponseFuture { inner: Inner::Error(Some(error)), } } } impl Future for ResponseFuture where F: Future>, E: Into, ME: Into, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let me = self.project(); match me.inner.project() { InnerProj::Future(fut) => fut.poll(cx).map_err(Into::into), InnerProj::Error(e) => { let e = e.take().expect("Polled after ready.").into(); Poll::Ready(Err(e)) } } } }