1
1
use std:: error:: Error as StdError ;
2
2
use std:: future:: Future ;
3
+ use std:: marker:: PhantomData ;
3
4
use std:: pin:: Pin ;
4
5
use std:: task:: { self , Poll } ;
5
6
use std:: fmt;
@@ -11,13 +12,15 @@ use std::time::Duration;
11
12
use futures_util:: future:: Either ;
12
13
use http:: uri:: { Scheme , Uri } ;
13
14
use net2:: TcpBuilder ;
15
+ use pin_project:: pin_project;
14
16
use tokio:: net:: TcpStream ;
15
17
use tokio:: time:: Delay ;
16
18
17
19
use super :: dns:: { self , resolve, GaiResolver , Resolve } ;
18
20
use super :: { Connected , Destination } ;
19
21
//#[cfg(feature = "runtime")] use super::dns::TokioThreadpoolGaiResolver;
20
22
23
+
21
24
/// A connector for the `http` scheme.
22
25
///
23
26
/// Performs DNS resolution in a thread pool, and then connects over TCP.
@@ -233,8 +236,7 @@ where
233
236
{
234
237
type Response = ( TcpStream , Connected ) ;
235
238
type Error = ConnectError ;
236
- type Future =
237
- Pin < Box < dyn Future < Output = Result < Self :: Response , Self :: Error > > + Send + ' static > > ;
239
+ type Future = HttpConnecting < R > ;
238
240
239
241
fn poll_ready ( & mut self , cx : & mut task:: Context < ' _ > ) -> Poll < Result < ( ) , Self :: Error > > {
240
242
ready ! ( self . resolver. poll_ready( cx) ) . map_err ( ConnectError :: dns) ?;
@@ -243,7 +245,10 @@ where
243
245
244
246
fn call ( & mut self , dst : Destination ) -> Self :: Future {
245
247
let mut self_ = self . clone ( ) ;
246
- Box :: pin ( async move { self_. call_async ( dst) . await } )
248
+ HttpConnecting {
249
+ fut : Box :: pin ( async move { self_. call_async ( dst) . await } ) ,
250
+ _marker : PhantomData ,
251
+ }
247
252
}
248
253
}
249
254
@@ -373,6 +378,32 @@ impl HttpInfo {
373
378
}
374
379
}
375
380
381
+ // Not publicly exported (so missing_docs doesn't trigger).
382
+ //
383
+ // We return this `Future` instead of the `Pin<Box<dyn Future>>` directly
384
+ // so that users don't rely on it fitting in a `Pin<Box<dyn Future>>` slot
385
+ // (and thus we can change the type in the future).
386
+ #[ must_use = "futures do nothing unless polled" ]
387
+ #[ pin_project]
388
+ #[ allow( missing_debug_implementations) ]
389
+ pub struct HttpConnecting < R > {
390
+ #[ pin]
391
+ fut : BoxConnecting ,
392
+ _marker : PhantomData < R > ,
393
+ }
394
+
395
+ type ConnectResult = Result < ( TcpStream , Connected ) , ConnectError > ;
396
+ type BoxConnecting = Pin < Box < dyn Future < Output = ConnectResult > + Send > > ;
397
+
398
+ impl < R : Resolve > Future for HttpConnecting < R > {
399
+ type Output = ConnectResult ;
400
+
401
+ fn poll ( self : Pin < & mut Self > , cx : & mut task:: Context < ' _ > ) -> Poll < Self :: Output > {
402
+ self . project ( ) . fut . poll ( cx)
403
+ }
404
+ }
405
+
406
+
376
407
// Not publicly exported (so missing_docs doesn't trigger).
377
408
pub struct ConnectError {
378
409
msg : Box < str > ,
0 commit comments