diff --git a/Cargo.toml b/Cargo.toml index c9fbdcdb10..06f51f9ea7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,6 @@ tokio-fs = "=0.2.0-alpha.4" tokio-test = "=0.2.0-alpha.4" url = "1.0" - [features] default = [ "__internal_flaky_tests", @@ -78,6 +77,12 @@ nightly = [] __internal_flaky_tests = [] __internal_happy_eyeballs_tests = [] +[package.metadata.docs.rs] +features = [ + "runtime", + "stream", +] + [profile.release] codegen-units = 1 incremental = false @@ -94,12 +99,12 @@ required-features = ["runtime"] [[example]] name = "client_json" path = "examples/client_json.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[example]] name = "echo" path = "examples/echo.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[example]] name = "hello" @@ -114,7 +119,7 @@ required-features = ["runtime"] [[example]] name = "params" path = "examples/params.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[example]] name = "proxy" @@ -155,7 +160,7 @@ required-features = ["runtime"] [[example]] name = "web_api" path = "examples/web_api.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[bench]] @@ -171,20 +176,20 @@ required-features = ["runtime"] [[bench]] name = "server" path = "benches/server.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[test]] name = "client" path = "tests/client.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[test]] name = "integration" path = "tests/integration.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] [[test]] name = "server" path = "tests/server.rs" -required-features = ["runtime"] +required-features = ["runtime", "stream"] diff --git a/src/body/body.rs b/src/body/body.rs index b726e2fa1c..3562bf8c9b 100644 --- a/src/body/body.rs +++ b/src/body/body.rs @@ -1,10 +1,14 @@ use std::borrow::Cow; +#[cfg(feature = "stream")] use std::error::Error as StdError; use std::fmt; use bytes::Bytes; -use futures_core::{Stream, TryStream}; +use futures_core::Stream; // for mpsc::Receiver +#[cfg(feature = "stream")] +use futures_core::TryStream; use futures_channel::{mpsc, oneshot}; +#[cfg(feature = "stream")] use futures_util::TryStreamExt; use http_body::{SizeHint, Body as HttpBody}; use http::HeaderMap; @@ -18,8 +22,6 @@ type BodySender = mpsc::Sender>; /// A stream of `Chunk`s, used when receiving bodies. /// /// A good default `Payload` to use in many applications. -/// -/// Also implements `futures::Stream`, so stream combinators may be used. #[must_use = "streams do nothing unless polled"] pub struct Body { kind: Kind, @@ -43,6 +45,7 @@ enum Kind { // while a borrow of a `Request` exists. // // See https://github.com/rust-lang/rust/issues/57017 + #[cfg(feature = "stream")] Wrapped(Pin>> + Send + Sync>>), } @@ -140,6 +143,12 @@ impl Body { /// let body = Body::wrap_stream(stream); /// # } /// ``` + /// + /// # Unstable + /// + /// This function requires enabling the unstable `stream` feature in your + /// `Cargo.toml`. + #[cfg(feature = "stream")] pub fn wrap_stream(stream: S) -> Body where S: TryStream + Send + Sync + 'static, @@ -277,6 +286,8 @@ impl Body { Some(Err(e)) => Poll::Ready(Some(Err(crate::Error::new_body(e)))), None => Poll::Ready(None), }, + + #[cfg(feature = "stream")] Kind::Wrapped(ref mut s) => { match ready!(s.as_mut().poll_next(cx)) { Some(res) => Poll::Ready(Some(res.map_err(crate::Error::new_body))), @@ -326,6 +337,7 @@ impl HttpBody for Body { Kind::Once(ref val) => val.is_none(), Kind::Chan { content_length, .. } => content_length == Some(0), Kind::H2 { recv: ref h2, .. } => h2.is_end_stream(), + #[cfg(feature = "stream")] Kind::Wrapped(..) => false, } } @@ -340,6 +352,7 @@ impl HttpBody for Body { Kind::Once(None) => { SizeHint::default() }, + #[cfg(feature = "stream")] Kind::Wrapped(..) => SizeHint::default(), Kind::Chan { content_length, .. } | Kind::H2 { content_length, .. } => { let mut hint = SizeHint::default(); @@ -361,12 +374,12 @@ impl fmt::Debug for Body { #[derive(Debug)] struct Empty; #[derive(Debug)] - struct Once<'a>(&'a Chunk); + struct Full<'a>(&'a Chunk); let mut builder = f.debug_tuple("Body"); match self.kind { Kind::Once(None) => builder.field(&Empty), - Kind::Once(Some(ref chunk)) => builder.field(&Once(chunk)), + Kind::Once(Some(ref chunk)) => builder.field(&Full(chunk)), _ => builder.field(&Streaming), }; @@ -374,6 +387,7 @@ impl fmt::Debug for Body { } } +#[cfg(feature = "stream")] impl Stream for Body { type Item = crate::Result; @@ -383,6 +397,7 @@ impl Stream for Body { } +#[cfg(feature = "stream")] impl From>> + Send + Sync>> for Body diff --git a/src/lib.rs b/src/lib.rs index 35fc3b1b31..0f5cf59486 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,15 @@ //! //! If looking for just a convenient HTTP client, consider the //! [reqwest](https://crates.io/crates/reqwest) crate. +//! +//! # Optional Features +//! +//! The following optional features are available: +//! +//! - `runtime` (*enabled by default*): Enables convenient integration with +//! `tokio`, providing connectors and acceptors for TCP, and a default +//! executor. +//! - `stream` (*unstable*): Provides `futures::Stream` capabilities. #[doc(hidden)] pub use http; #[macro_use] extern crate log; diff --git a/src/server/tcp.rs b/src/server/tcp.rs index 17e9a14a3e..3092ff6507 100644 --- a/src/server/tcp.rs +++ b/src/server/tcp.rs @@ -156,17 +156,6 @@ impl AddrIncoming { } } -/* -impl Stream for AddrIncoming { - type Item = io::Result; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { - let result = ready!(self.poll_next_(cx)); - Poll::Ready(Some(result)) - } -} -*/ - impl Accept for AddrIncoming { type Conn = AddrStream; type Error = io::Error;