diff options
Diffstat (limited to 'third_party/rust/http-body/src/combinators')
4 files changed, 336 insertions, 0 deletions
diff --git a/third_party/rust/http-body/src/combinators/box_body.rs b/third_party/rust/http-body/src/combinators/box_body.rs new file mode 100644 index 0000000000..97c8313fd7 --- /dev/null +++ b/third_party/rust/http-body/src/combinators/box_body.rs @@ -0,0 +1,134 @@ +use crate::Body; +use bytes::Buf; +use std::{ + fmt, + pin::Pin, + task::{Context, Poll}, +}; + +/// A boxed [`Body`] trait object. +pub struct BoxBody<D, E> { + inner: Pin<Box<dyn Body<Data = D, Error = E> + Send + Sync + 'static>>, +} + +/// A boxed [`Body`] trait object that is !Sync. +pub struct UnsyncBoxBody<D, E> { + inner: Pin<Box<dyn Body<Data = D, Error = E> + Send + 'static>>, +} + +impl<D, E> BoxBody<D, E> { + /// Create a new `BoxBody`. + pub fn new<B>(body: B) -> Self + where + B: Body<Data = D, Error = E> + Send + Sync + 'static, + D: Buf, + { + Self { + inner: Box::pin(body), + } + } +} + +impl<D, E> fmt::Debug for BoxBody<D, E> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BoxBody").finish() + } +} + +impl<D, E> Body for BoxBody<D, E> +where + D: Buf, +{ + type Data = D; + type Error = E; + + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + self.inner.as_mut().poll_data(cx) + } + + fn poll_trailers( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { + self.inner.as_mut().poll_trailers(cx) + } + + fn is_end_stream(&self) -> bool { + self.inner.is_end_stream() + } + + fn size_hint(&self) -> crate::SizeHint { + self.inner.size_hint() + } +} + +impl<D, E> Default for BoxBody<D, E> +where + D: Buf + 'static, +{ + fn default() -> Self { + BoxBody::new(crate::Empty::new().map_err(|err| match err {})) + } +} + +// === UnsyncBoxBody === +impl<D, E> UnsyncBoxBody<D, E> { + /// Create a new `BoxBody`. + pub fn new<B>(body: B) -> Self + where + B: Body<Data = D, Error = E> + Send + 'static, + D: Buf, + { + Self { + inner: Box::pin(body), + } + } +} + +impl<D, E> fmt::Debug for UnsyncBoxBody<D, E> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnsyncBoxBody").finish() + } +} + +impl<D, E> Body for UnsyncBoxBody<D, E> +where + D: Buf, +{ + type Data = D; + type Error = E; + + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + self.inner.as_mut().poll_data(cx) + } + + fn poll_trailers( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { + self.inner.as_mut().poll_trailers(cx) + } + + fn is_end_stream(&self) -> bool { + self.inner.is_end_stream() + } + + fn size_hint(&self) -> crate::SizeHint { + self.inner.size_hint() + } +} + +impl<D, E> Default for UnsyncBoxBody<D, E> +where + D: Buf + 'static, +{ + fn default() -> Self { + UnsyncBoxBody::new(crate::Empty::new().map_err(|err| match err {})) + } +} diff --git a/third_party/rust/http-body/src/combinators/map_data.rs b/third_party/rust/http-body/src/combinators/map_data.rs new file mode 100644 index 0000000000..6d9c5a8964 --- /dev/null +++ b/third_party/rust/http-body/src/combinators/map_data.rs @@ -0,0 +1,94 @@ +use crate::Body; +use bytes::Buf; +use pin_project_lite::pin_project; +use std::{ + any::type_name, + fmt, + pin::Pin, + task::{Context, Poll}, +}; + +pin_project! { + /// Body returned by the [`map_data`] combinator. + /// + /// [`map_data`]: crate::util::BodyExt::map_data + #[derive(Clone, Copy)] + pub struct MapData<B, F> { + #[pin] + inner: B, + f: F + } +} + +impl<B, F> MapData<B, F> { + #[inline] + pub(crate) fn new(body: B, f: F) -> Self { + Self { inner: body, f } + } + + /// Get a reference to the inner body + pub fn get_ref(&self) -> &B { + &self.inner + } + + /// Get a mutable reference to the inner body + pub fn get_mut(&mut self) -> &mut B { + &mut self.inner + } + + /// Get a pinned mutable reference to the inner body + pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut B> { + self.project().inner + } + + /// Consume `self`, returning the inner body + pub fn into_inner(self) -> B { + self.inner + } +} + +impl<B, F, B2> Body for MapData<B, F> +where + B: Body, + F: FnMut(B::Data) -> B2, + B2: Buf, +{ + type Data = B2; + type Error = B::Error; + + fn poll_data( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + let this = self.project(); + match this.inner.poll_data(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(None) => Poll::Ready(None), + Poll::Ready(Some(Ok(data))) => Poll::Ready(Some(Ok((this.f)(data)))), + Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(err))), + } + } + + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { + self.project().inner.poll_trailers(cx) + } + + fn is_end_stream(&self) -> bool { + self.inner.is_end_stream() + } +} + +impl<B, F> fmt::Debug for MapData<B, F> +where + B: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("MapData") + .field("inner", &self.inner) + .field("f", &type_name::<F>()) + .finish() + } +} diff --git a/third_party/rust/http-body/src/combinators/map_err.rs b/third_party/rust/http-body/src/combinators/map_err.rs new file mode 100644 index 0000000000..c77168deb5 --- /dev/null +++ b/third_party/rust/http-body/src/combinators/map_err.rs @@ -0,0 +1,97 @@ +use crate::Body; +use pin_project_lite::pin_project; +use std::{ + any::type_name, + fmt, + pin::Pin, + task::{Context, Poll}, +}; + +pin_project! { + /// Body returned by the [`map_err`] combinator. + /// + /// [`map_err`]: crate::util::BodyExt::map_err + #[derive(Clone, Copy)] + pub struct MapErr<B, F> { + #[pin] + inner: B, + f: F + } +} + +impl<B, F> MapErr<B, F> { + #[inline] + pub(crate) fn new(body: B, f: F) -> Self { + Self { inner: body, f } + } + + /// Get a reference to the inner body + pub fn get_ref(&self) -> &B { + &self.inner + } + + /// Get a mutable reference to the inner body + pub fn get_mut(&mut self) -> &mut B { + &mut self.inner + } + + /// Get a pinned mutable reference to the inner body + pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut B> { + self.project().inner + } + + /// Consume `self`, returning the inner body + pub fn into_inner(self) -> B { + self.inner + } +} + +impl<B, F, E> Body for MapErr<B, F> +where + B: Body, + F: FnMut(B::Error) -> E, +{ + type Data = B::Data; + type Error = E; + + fn poll_data( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Option<Result<Self::Data, Self::Error>>> { + let this = self.project(); + match this.inner.poll_data(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(None) => Poll::Ready(None), + Poll::Ready(Some(Ok(data))) => Poll::Ready(Some(Ok(data))), + Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err((this.f)(err)))), + } + } + + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> { + let this = self.project(); + this.inner.poll_trailers(cx).map_err(this.f) + } + + fn is_end_stream(&self) -> bool { + self.inner.is_end_stream() + } + + fn size_hint(&self) -> crate::SizeHint { + self.inner.size_hint() + } +} + +impl<B, F> fmt::Debug for MapErr<B, F> +where + B: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("MapErr") + .field("inner", &self.inner) + .field("f", &type_name::<F>()) + .finish() + } +} diff --git a/third_party/rust/http-body/src/combinators/mod.rs b/third_party/rust/http-body/src/combinators/mod.rs new file mode 100644 index 0000000000..c52f367554 --- /dev/null +++ b/third_party/rust/http-body/src/combinators/mod.rs @@ -0,0 +1,11 @@ +//! Combinators for the `Body` trait. + +mod box_body; +mod map_data; +mod map_err; + +pub use self::{ + box_body::{BoxBody, UnsyncBoxBody}, + map_data::MapData, + map_err::MapErr, +}; |