#![doc(html_root_url = "https://docs.rs/http-body/0.4.5")] #![deny( missing_debug_implementations, missing_docs, unreachable_pub, broken_intra_doc_links )] #![cfg_attr(test, deny(warnings))] //! Asynchronous HTTP request or response body. //! //! See [`Body`] for more details. //! //! [`Body`]: trait.Body.html mod empty; mod full; mod limited; mod next; mod size_hint; pub mod combinators; pub use self::empty::Empty; pub use self::full::Full; pub use self::limited::{LengthLimitError, Limited}; pub use self::next::{Data, Trailers}; pub use self::size_hint::SizeHint; use self::combinators::{BoxBody, MapData, MapErr, UnsyncBoxBody}; use bytes::{Buf, Bytes}; use http::HeaderMap; use std::convert::Infallible; use std::ops; use std::pin::Pin; use std::task::{Context, Poll}; /// Trait representing a streaming body of a Request or Response. /// /// Data is streamed via the `poll_data` function, which asynchronously yields `T: Buf` values. The /// `size_hint` function provides insight into the total number of bytes that will be streamed. /// /// The `poll_trailers` function returns an optional set of trailers used to finalize the request / /// response exchange. This is mostly used when using the HTTP/2.0 protocol. /// pub trait Body { /// Values yielded by the `Body`. type Data: Buf; /// The error type this `Body` might generate. type Error; /// Attempt to pull out the next data buffer of this stream. fn poll_data( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>>; /// Poll for an optional **single** `HeaderMap` of trailers. /// /// This function should only be called once `poll_data` returns `None`. fn poll_trailers( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll, Self::Error>>; /// Returns `true` when the end of stream has been reached. /// /// An end of stream means that both `poll_data` and `poll_trailers` will /// return `None`. /// /// A return value of `false` **does not** guarantee that a value will be /// returned from `poll_stream` or `poll_trailers`. fn is_end_stream(&self) -> bool { false } /// Returns the bounds on the remaining length of the stream. /// /// When the **exact** remaining length of the stream is known, the upper bound will be set and /// will equal the lower bound. fn size_hint(&self) -> SizeHint { SizeHint::default() } /// Returns future that resolves to next data chunk, if any. fn data(&mut self) -> Data<'_, Self> where Self: Unpin + Sized, { Data(self) } /// Returns future that resolves to trailers, if any. fn trailers(&mut self) -> Trailers<'_, Self> where Self: Unpin + Sized, { Trailers(self) } /// Maps this body's data value to a different value. fn map_data(self, f: F) -> MapData where Self: Sized, F: FnMut(Self::Data) -> B, B: Buf, { MapData::new(self, f) } /// Maps this body's error value to a different value. fn map_err(self, f: F) -> MapErr where Self: Sized, F: FnMut(Self::Error) -> E, { MapErr::new(self, f) } /// Turn this body into a boxed trait object. fn boxed(self) -> BoxBody where Self: Sized + Send + Sync + 'static, { BoxBody::new(self) } /// Turn this body into a boxed trait object that is !Sync. fn boxed_unsync(self) -> UnsyncBoxBody where Self: Sized + Send + 'static, { UnsyncBoxBody::new(self) } } impl Body for &mut T { type Data = T::Data; type Error = T::Error; fn poll_data( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { Pin::new(&mut **self).poll_data(cx) } fn poll_trailers( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll, Self::Error>> { Pin::new(&mut **self).poll_trailers(cx) } fn is_end_stream(&self) -> bool { Pin::new(&**self).is_end_stream() } fn size_hint(&self) -> SizeHint { Pin::new(&**self).size_hint() } } impl

Body for Pin

where P: Unpin + ops::DerefMut, P::Target: Body, { type Data = <

::Target as Body>::Data; type Error = <

::Target as Body>::Error; fn poll_data( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { Pin::get_mut(self).as_mut().poll_data(cx) } fn poll_trailers( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll, Self::Error>> { Pin::get_mut(self).as_mut().poll_trailers(cx) } fn is_end_stream(&self) -> bool { self.as_ref().is_end_stream() } fn size_hint(&self) -> SizeHint { self.as_ref().size_hint() } } impl Body for Box { type Data = T::Data; type Error = T::Error; fn poll_data( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { Pin::new(&mut **self).poll_data(cx) } fn poll_trailers( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll, Self::Error>> { Pin::new(&mut **self).poll_trailers(cx) } fn is_end_stream(&self) -> bool { self.as_ref().is_end_stream() } fn size_hint(&self) -> SizeHint { self.as_ref().size_hint() } } impl Body for http::Request { type Data = B::Data; type Error = B::Error; fn poll_data( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { unsafe { self.map_unchecked_mut(http::Request::body_mut) .poll_data(cx) } } fn poll_trailers( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll, Self::Error>> { unsafe { self.map_unchecked_mut(http::Request::body_mut) .poll_trailers(cx) } } fn is_end_stream(&self) -> bool { self.body().is_end_stream() } fn size_hint(&self) -> SizeHint { self.body().size_hint() } } impl Body for http::Response { type Data = B::Data; type Error = B::Error; fn poll_data( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { unsafe { self.map_unchecked_mut(http::Response::body_mut) .poll_data(cx) } } fn poll_trailers( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll, Self::Error>> { unsafe { self.map_unchecked_mut(http::Response::body_mut) .poll_trailers(cx) } } fn is_end_stream(&self) -> bool { self.body().is_end_stream() } fn size_hint(&self) -> SizeHint { self.body().size_hint() } } impl Body for String { type Data = Bytes; type Error = Infallible; fn poll_data( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll>> { if !self.is_empty() { let s = std::mem::take(&mut *self); Poll::Ready(Some(Ok(s.into_bytes().into()))) } else { Poll::Ready(None) } } fn poll_trailers( self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll, Self::Error>> { Poll::Ready(Ok(None)) } fn is_end_stream(&self) -> bool { self.is_empty() } fn size_hint(&self) -> SizeHint { SizeHint::with_exact(self.len() as u64) } } #[cfg(test)] fn _assert_bounds() { fn can_be_trait_object(_: &dyn Body>, Error = std::io::Error>) {} }