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