summaryrefslogtreecommitdiffstats
path: root/third_party/rust/hyper/src/common/exec.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/hyper/src/common/exec.rs')
-rw-r--r--third_party/rust/hyper/src/common/exec.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/third_party/rust/hyper/src/common/exec.rs b/third_party/rust/hyper/src/common/exec.rs
new file mode 100644
index 0000000000..76f616184b
--- /dev/null
+++ b/third_party/rust/hyper/src/common/exec.rs
@@ -0,0 +1,145 @@
+use std::fmt;
+use std::future::Future;
+use std::pin::Pin;
+use std::sync::Arc;
+
+#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
+use crate::body::Body;
+#[cfg(feature = "server")]
+use crate::body::HttpBody;
+#[cfg(all(feature = "http2", feature = "server"))]
+use crate::proto::h2::server::H2Stream;
+use crate::rt::Executor;
+#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
+use crate::server::server::{new_svc::NewSvcTask, Watcher};
+#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
+use crate::service::HttpService;
+
+#[cfg(feature = "server")]
+pub trait ConnStreamExec<F, B: HttpBody>: Clone {
+ fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
+}
+
+#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
+pub trait NewSvcExec<I, N, S: HttpService<Body>, E, W: Watcher<I, S, E>>: Clone {
+ fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>);
+}
+
+pub(crate) type BoxSendFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
+
+// Either the user provides an executor for background tasks, or we use
+// `tokio::spawn`.
+#[derive(Clone)]
+pub enum Exec {
+ Default,
+ Executor(Arc<dyn Executor<BoxSendFuture> + Send + Sync>),
+}
+
+// ===== impl Exec =====
+
+impl Exec {
+ pub(crate) fn execute<F>(&self, fut: F)
+ where
+ F: Future<Output = ()> + Send + 'static,
+ {
+ match *self {
+ Exec::Default => {
+ #[cfg(feature = "tcp")]
+ {
+ tokio::task::spawn(fut);
+ }
+ #[cfg(not(feature = "tcp"))]
+ {
+ // If no runtime, we need an executor!
+ panic!("executor must be set")
+ }
+ }
+ Exec::Executor(ref e) => {
+ e.execute(Box::pin(fut));
+ }
+ }
+ }
+}
+
+impl fmt::Debug for Exec {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Exec").finish()
+ }
+}
+
+#[cfg(feature = "server")]
+impl<F, B> ConnStreamExec<F, B> for Exec
+where
+ H2Stream<F, B>: Future<Output = ()> + Send + 'static,
+ B: HttpBody,
+{
+ fn execute_h2stream(&mut self, fut: H2Stream<F, B>) {
+ self.execute(fut)
+ }
+}
+
+#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
+impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec
+where
+ NewSvcTask<I, N, S, E, W>: Future<Output = ()> + Send + 'static,
+ S: HttpService<Body>,
+ W: Watcher<I, S, E>,
+{
+ fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) {
+ self.execute(fut)
+ }
+}
+
+// ==== impl Executor =====
+
+#[cfg(feature = "server")]
+impl<E, F, B> ConnStreamExec<F, B> for E
+where
+ E: Executor<H2Stream<F, B>> + Clone,
+ H2Stream<F, B>: Future<Output = ()>,
+ B: HttpBody,
+{
+ fn execute_h2stream(&mut self, fut: H2Stream<F, B>) {
+ self.execute(fut)
+ }
+}
+
+#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
+impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E
+where
+ E: Executor<NewSvcTask<I, N, S, E, W>> + Clone,
+ NewSvcTask<I, N, S, E, W>: Future<Output = ()>,
+ S: HttpService<Body>,
+ W: Watcher<I, S, E>,
+{
+ fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) {
+ self.execute(fut)
+ }
+}
+
+// If http2 is not enable, we just have a stub here, so that the trait bounds
+// that *would* have been needed are still checked. Why?
+//
+// Because enabling `http2` shouldn't suddenly add new trait bounds that cause
+// a compilation error.
+#[cfg(not(feature = "http2"))]
+#[allow(missing_debug_implementations)]
+pub struct H2Stream<F, B>(std::marker::PhantomData<(F, B)>);
+
+#[cfg(not(feature = "http2"))]
+impl<F, B, E> Future for H2Stream<F, B>
+where
+ F: Future<Output = Result<http::Response<B>, E>>,
+ B: crate::body::HttpBody,
+ B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
+ E: Into<Box<dyn std::error::Error + Send + Sync>>,
+{
+ type Output = ();
+
+ fn poll(
+ self: Pin<&mut Self>,
+ _cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Self::Output> {
+ unreachable!()
+ }
+}