From 9645a125e6be71bd09b53b1d8fd276f83e3c37a9 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Wed, 4 Dec 2019 13:59:38 -0800 Subject: [PATCH] refactor(client): return HttpConnecting newtype --- src/client/connect/http.rs | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/client/connect/http.rs b/src/client/connect/http.rs index f9a08d5a..1ae73ff6 100644 --- a/src/client/connect/http.rs +++ b/src/client/connect/http.rs @@ -1,5 +1,6 @@ use std::error::Error as StdError; use std::future::Future; +use std::marker::PhantomData; use std::pin::Pin; use std::task::{self, Poll}; use std::fmt; @@ -11,6 +12,7 @@ use std::time::Duration; use futures_util::future::Either; use http::uri::{Scheme, Uri}; use net2::TcpBuilder; +use pin_project::pin_project; use tokio::net::TcpStream; use tokio::time::Delay; @@ -18,6 +20,7 @@ use super::dns::{self, resolve, GaiResolver, Resolve}; use super::{Connected, Destination}; //#[cfg(feature = "runtime")] use super::dns::TokioThreadpoolGaiResolver; + /// A connector for the `http` scheme. /// /// Performs DNS resolution in a thread pool, and then connects over TCP. @@ -233,8 +236,7 @@ where { type Response = (TcpStream, Connected); type Error = ConnectError; - type Future = - Pin> + Send + 'static>>; + type Future = HttpConnecting; fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll> { ready!(self.resolver.poll_ready(cx)).map_err(ConnectError::dns)?; @@ -243,7 +245,10 @@ where fn call(&mut self, dst: Destination) -> Self::Future { let mut self_ = self.clone(); - Box::pin(async move { self_.call_async(dst).await }) + HttpConnecting { + fut: Box::pin(async move { self_.call_async(dst).await }), + _marker: PhantomData, + } } } @@ -373,6 +378,32 @@ impl HttpInfo { } } +// Not publicly exported (so missing_docs doesn't trigger). +// +// We return this `Future` instead of the `Pin>` directly +// so that users don't rely on it fitting in a `Pin>` slot +// (and thus we can change the type in the future). +#[must_use = "futures do nothing unless polled"] +#[pin_project] +#[allow(missing_debug_implementations)] +pub struct HttpConnecting { + #[pin] + fut: BoxConnecting, + _marker: PhantomData, +} + +type ConnectResult = Result<(TcpStream, Connected), ConnectError>; +type BoxConnecting = Pin + Send>>; + +impl Future for HttpConnecting { + type Output = ConnectResult; + + fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll { + self.project().fut.poll(cx) + } +} + + // Not publicly exported (so missing_docs doesn't trigger). pub struct ConnectError { msg: Box,