feat(body): put Stream impl for Body behind stream feature
				
					
				
			BREAKING CHANGE: Using a `Body` as a `Stream`, and constructing one via `Body::wrap_stream`, require enabling the unstable `stream` feature.
This commit is contained in:
		| @@ -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<Result<Chunk, crate::Error>>; | ||||
| /// 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<Body>` exists. | ||||
|     // | ||||
|     // See https://github.com/rust-lang/rust/issues/57017 | ||||
|     #[cfg(feature = "stream")] | ||||
|     Wrapped(Pin<Box<dyn Stream<Item = Result<Chunk, Box<dyn StdError + Send + Sync>>> + 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<S>(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<Chunk>; | ||||
|  | ||||
| @@ -383,6 +397,7 @@ impl Stream for Body { | ||||
| } | ||||
|  | ||||
|  | ||||
| #[cfg(feature = "stream")] | ||||
| impl | ||||
|     From<Box<dyn Stream<Item = Result<Chunk, Box<dyn StdError + Send + Sync>>> + Send + Sync>> | ||||
|     for Body | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -156,17 +156,6 @@ impl AddrIncoming { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| impl Stream for AddrIncoming { | ||||
|     type Item = io::Result<AddrStream>; | ||||
|  | ||||
|     fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> { | ||||
|         let result = ready!(self.poll_next_(cx)); | ||||
|         Poll::Ready(Some(result)) | ||||
|     } | ||||
| } | ||||
| */ | ||||
|  | ||||
| impl Accept for AddrIncoming { | ||||
|     type Conn = AddrStream; | ||||
|     type Error = io::Error; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user