diff options
Diffstat (limited to 'third_party/rust/http-body/src/lib.rs')
-rw-r--r-- | third_party/rust/http-body/src/lib.rs | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/third_party/rust/http-body/src/lib.rs b/third_party/rust/http-body/src/lib.rs new file mode 100644 index 0000000000..84efd9169f --- /dev/null +++ b/third_party/rust/http-body/src/lib.rs @@ -0,0 +1,324 @@ +#![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<Option<Result<Self::Data, Self::Error>>>; + + /// 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<Result<Option<HeaderMap>, 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<F, B>(self, f: F) -> MapData<Self, F> + 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<F, E>(self, f: F) -> MapErr<Self, F> + where + Self: Sized, + F: FnMut(Self::Error) -> E, + { + MapErr::new(self, f) + } + + /// Turn this body into a boxed trait object. + fn boxed(self) -> BoxBody<Self::Data, Self::Error> + 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<Self::Data, Self::Error> + where + Self: Sized + Send + 'static, + { + UnsyncBoxBody::new(self) + } +} + +impl<T: Body + Unpin + ?Sized> Body for &mut T { + type Data = T::Data; + type Error = T::Error; + + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + Pin::new(&mut **self).poll_data(cx) + } + + fn poll_trailers( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<HeaderMap>, 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<P> Body for Pin<P> +where + P: Unpin + ops::DerefMut, + P::Target: Body, +{ + type Data = <<P as ops::Deref>::Target as Body>::Data; + type Error = <<P as ops::Deref>::Target as Body>::Error; + + fn poll_data( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + Pin::get_mut(self).as_mut().poll_data(cx) + } + + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<HeaderMap>, 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<T: Body + Unpin + ?Sized> Body for Box<T> { + type Data = T::Data; + type Error = T::Error; + + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + Pin::new(&mut **self).poll_data(cx) + } + + fn poll_trailers( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<HeaderMap>, 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<B: Body> Body for http::Request<B> { + type Data = B::Data; + type Error = B::Error; + + fn poll_data( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + unsafe { + self.map_unchecked_mut(http::Request::body_mut) + .poll_data(cx) + } + } + + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<HeaderMap>, 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<B: Body> Body for http::Response<B> { + type Data = B::Data; + type Error = B::Error; + + fn poll_data( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + unsafe { + self.map_unchecked_mut(http::Response::body_mut) + .poll_data(cx) + } + } + + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<HeaderMap>, 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<Option<Result<Self::Data, Self::Error>>> { + 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<Result<Option<HeaderMap>, 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<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {} +} |