Skip to content

Commit fc9f307

Browse files
authoredJan 31, 2023
feat(rt): make private executor traits public (but sealed) in rt::bounds (#3127)
Define public trait aliases that are sealed, but can be named externally, and have documentation showing how to provide a Executor to match the bounds, and how to express the bounds in your own API. Closes #2051 Closes #3097
1 parent 8068aa0 commit fc9f307

File tree

6 files changed

+104
-44
lines changed

6 files changed

+104
-44
lines changed
 

‎src/common/exec.rs

-34
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,8 @@ use std::future::Future;
33
use std::pin::Pin;
44
use std::sync::Arc;
55

6-
#[cfg(feature = "server")]
7-
use crate::body::Body;
8-
#[cfg(all(feature = "http2", feature = "server"))]
9-
use crate::proto::h2::server::H2Stream;
106
use crate::rt::Executor;
117

12-
#[cfg(feature = "server")]
13-
pub trait ConnStreamExec<F, B: Body>: Clone {
14-
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
15-
}
16-
178
pub(crate) type BoxSendFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
189

1910
// Executor must be provided by the user
@@ -44,31 +35,6 @@ impl fmt::Debug for Exec {
4435
}
4536
}
4637

47-
#[cfg(feature = "server")]
48-
impl<F, B> ConnStreamExec<F, B> for Exec
49-
where
50-
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
51-
B: Body,
52-
{
53-
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) {
54-
self.execute(fut)
55-
}
56-
}
57-
58-
// ==== impl Executor =====
59-
60-
#[cfg(feature = "server")]
61-
impl<E, F, B> ConnStreamExec<F, B> for E
62-
where
63-
E: Executor<H2Stream<F, B>> + Clone,
64-
H2Stream<F, B>: Future<Output = ()>,
65-
B: Body,
66-
{
67-
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) {
68-
self.execute(fut)
69-
}
70-
}
71-
7238
// If http2 is not enable, we just have a stub here, so that the trait bounds
7339
// that *would* have been needed are still checked. Why?
7440
//

‎src/proto/h2/server.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tracing::{debug, trace, warn};
1313

1414
use super::{ping, PipeToSendStream, SendBuf};
1515
use crate::body::{Body, Incoming as IncomingBody};
16-
use crate::common::exec::ConnStreamExec;
16+
use crate::rt::bounds::Http2ConnExec;
1717
use crate::common::time::Time;
1818
use crate::common::{date, task, Future, Pin, Poll};
1919
use crate::ext::Protocol;
@@ -110,7 +110,7 @@ where
110110
S: HttpService<IncomingBody, ResBody = B>,
111111
S::Error: Into<Box<dyn StdError + Send + Sync>>,
112112
B: Body + 'static,
113-
E: ConnStreamExec<S::Future, B>,
113+
E: Http2ConnExec<S::Future, B>,
114114
{
115115
pub(crate) fn new(
116116
io: T,
@@ -186,7 +186,7 @@ where
186186
S: HttpService<IncomingBody, ResBody = B>,
187187
S::Error: Into<Box<dyn StdError + Send + Sync>>,
188188
B: Body + 'static,
189-
E: ConnStreamExec<S::Future, B>,
189+
E: Http2ConnExec<S::Future, B>,
190190
{
191191
type Output = crate::Result<Dispatched>;
192192

@@ -240,7 +240,7 @@ where
240240
where
241241
S: HttpService<IncomingBody, ResBody = B>,
242242
S::Error: Into<Box<dyn StdError + Send + Sync>>,
243-
E: ConnStreamExec<S::Future, B>,
243+
E: Http2ConnExec<S::Future, B>,
244244
{
245245
if self.closing.is_none() {
246246
loop {

‎src/rt/bounds.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//! Trait aliases
2+
//!
3+
//! Traits in this module ease setting bounds and usually automatically
4+
//! implemented by implementing another trait.
5+
6+
#[cfg(all(feature = "server", feature = "http2"))]
7+
pub use self::h2::Http2ConnExec;
8+
9+
#[cfg(all(feature = "server", feature = "http2"))]
10+
#[cfg_attr(docsrs, doc(cfg(all(feature = "server", feature = "http2"))))]
11+
mod h2 {
12+
use crate::{common::exec::Exec, proto::h2::server::H2Stream, rt::Executor};
13+
use http_body::Body;
14+
use std::future::Future;
15+
16+
/// An executor to spawn http2 connections.
17+
///
18+
/// This trait is implemented for any type that implements [`Executor`]
19+
/// trait for any future.
20+
///
21+
/// This trait is sealed and cannot be implemented for types outside this crate.
22+
///
23+
/// [`Executor`]: crate::rt::Executor
24+
pub trait Http2ConnExec<F, B: Body>: sealed::Sealed<(F, B)> + Clone {
25+
#[doc(hidden)]
26+
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
27+
}
28+
29+
impl<F, B> Http2ConnExec<F, B> for Exec
30+
where
31+
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
32+
B: Body,
33+
{
34+
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) {
35+
self.execute(fut)
36+
}
37+
}
38+
39+
impl<F, B> sealed::Sealed<(F, B)> for Exec
40+
where
41+
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
42+
B: Body,
43+
{
44+
}
45+
46+
#[doc(hidden)]
47+
impl<E, F, B> Http2ConnExec<F, B> for E
48+
where
49+
E: Executor<H2Stream<F, B>> + Clone,
50+
H2Stream<F, B>: Future<Output = ()>,
51+
B: Body,
52+
{
53+
fn execute_h2stream(&mut self, fut: H2Stream<F, B>) {
54+
self.execute(fut)
55+
}
56+
}
57+
58+
impl<E, F, B> sealed::Sealed<(F, B)> for E
59+
where
60+
E: Executor<H2Stream<F, B>> + Clone,
61+
H2Stream<F, B>: Future<Output = ()>,
62+
B: Body,
63+
{
64+
}
65+
66+
mod sealed {
67+
pub trait Sealed<T> {}
68+
}
69+
}

‎src/rt.rs ‎src/rt/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,35 @@
55
//! If the `runtime` feature is disabled, the types in this module can be used
66
//! to plug in other runtimes.
77
8+
pub mod bounds;
9+
810
use std::{
911
future::Future,
1012
pin::Pin,
1113
time::{Duration, Instant},
1214
};
1315

1416
/// An executor of futures.
17+
///
18+
/// This trait should be implemented for any future.
19+
///
20+
/// # Example
21+
///
22+
/// ```
23+
/// # use hyper::rt::Executor;
24+
/// # use std::future::Future;
25+
/// struct TokioExecutor;
26+
///
27+
/// impl<F> Executor<F> for TokioExecutor
28+
/// where
29+
/// F: Future + Send + 'static,
30+
/// F::Output: Send + 'static,
31+
/// {
32+
/// fn execute(&self, future: F) {
33+
/// tokio::spawn(future);
34+
/// }
35+
/// }
36+
/// ```
1537
pub trait Executor<Fut> {
1638
/// Place the future into the executor to be run.
1739
fn execute(&self, fut: Fut);

‎src/server/conn/http2.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use pin_project_lite::pin_project;
99
use tokio::io::{AsyncRead, AsyncWrite};
1010

1111
use crate::body::{Body, Incoming as IncomingBody};
12-
use crate::common::exec::ConnStreamExec;
1312
use crate::common::{task, Future, Pin, Poll, Unpin};
1413
use crate::proto;
14+
use crate::rt::bounds::Http2ConnExec;
1515
use crate::service::HttpService;
1616
use crate::{common::time::Time, rt::Timer};
1717

@@ -54,7 +54,7 @@ where
5454
I: AsyncRead + AsyncWrite + Unpin,
5555
B: Body + 'static,
5656
B::Error: Into<Box<dyn StdError + Send + Sync>>,
57-
E: ConnStreamExec<S::Future, B>,
57+
E: Http2ConnExec<S::Future, B>,
5858
{
5959
/// Start a graceful shutdown process for this connection.
6060
///
@@ -78,7 +78,7 @@ where
7878
I: AsyncRead + AsyncWrite + Unpin + 'static,
7979
B: Body + 'static,
8080
B::Error: Into<Box<dyn StdError + Send + Sync>>,
81-
E: ConnStreamExec<S::Future, B>,
81+
E: Http2ConnExec<S::Future, B>,
8282
{
8383
type Output = crate::Result<()>;
8484

@@ -99,7 +99,10 @@ where
9999
impl<E> Builder<E> {
100100
/// Create a new connection builder.
101101
///
102-
/// This starts with the default options, and an executor.
102+
/// This starts with the default options, and an executor which is a type
103+
/// that implements [`Http2ConnExec`] trait.
104+
///
105+
/// [`Http2ConnExec`]: crate::rt::bounds::Http2ConnExec
103106
pub fn new(exec: E) -> Self {
104107
Self {
105108
exec: exec,
@@ -259,7 +262,7 @@ impl<E> Builder<E> {
259262
Bd: Body + 'static,
260263
Bd::Error: Into<Box<dyn StdError + Send + Sync>>,
261264
I: AsyncRead + AsyncWrite + Unpin,
262-
E: ConnStreamExec<S::Future, Bd>,
265+
E: Http2ConnExec<S::Future, Bd>,
263266
{
264267
let proto = proto::h2::Server::new(
265268
io,

‎src/service/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ mod service;
2626
mod util;
2727

2828
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "server"))]
29-
pub(super) use self::http::HttpService;
29+
pub use self::http::HttpService;
3030
#[cfg(all(
3131
any(feature = "http1", feature = "http2"),
3232
any(feature = "server", feature = "client")

0 commit comments

Comments
 (0)
Please sign in to comment.