#
http_body/
lib.rs

    1#![deny(
    2    missing_debug_implementations,
    3    missing_docs,
    4    unreachable_pub,
    5    clippy::missing_safety_doc,
    6    clippy::undocumented_unsafe_blocks
    7)]
    8#![cfg_attr(test, deny(warnings))]
    9
    10//! Asynchronous HTTP request or response body.
    11//!
    12//! See [`Body`] for more details.
    13//!
    14//! [`Body`]: trait.Body.html
    15
    16mod frame;
    17mod size_hint;
    18
    19pub use self::frame::Frame;
    20pub use self::size_hint::SizeHint;
    21
    22use bytes::{Buf, Bytes};
    23use std::convert::Infallible;
    24use std::ops;
    25use std::pin::Pin;
    26use std::task::{Context, Poll};
    27
    28/// Trait representing a streaming body of a Request or Response.
    29///
    30/// Individual frames are streamed via the `poll_frame` function, which asynchronously yields
    31/// instances of [`Frame<Data>`].
    32///
    33/// Frames can contain a data buffer of type `Self::Data`. Frames can also contain an optional
    34/// set of trailers used to finalize the request/response exchange. This is mostly used when using
    35/// the HTTP/2.0 protocol.
    36///
    37/// The `size_hint` function provides insight into the total number of bytes that will be streamed.
    38pub trait Body {
    39    /// Values yielded by the `Body`.
    40    type Data: Buf;
    41
    42    /// The error type this `Body` might generate.
    43    type Error;
    44
    45    #[allow(clippy::type_complexity)]
    46    /// Attempt to pull out the next data buffer of this stream.
    47    fn poll_frame(
    48        self: Pin<&mut Self>,
    49        cx: &mut Context<'_>,
    50    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>>;
    51
    52    /// Returns `true` when the end of stream has been reached.
    53    ///
    54    /// An end of stream means that `poll_frame` will return `None`.
    55    ///
    56    /// A return value of `false` **does not** guarantee that a value will be
    57    /// returned from `poll_frame`.
    58    fn is_end_stream(&self) -> bool {
    59        false
    60    }
    61
    62    /// Returns the bounds on the remaining length of the stream.
    63    ///
    64    /// When the **exact** remaining length of the stream is known, the upper bound will be set and
    65    /// will equal the lower bound.
    66    fn size_hint(&self) -> SizeHint {
    67        SizeHint::default()
    68    }
    69}
    70
    71impl<T: Body + Unpin + ?Sized> Body for &mut T {
    72    type Data = T::Data;
    73    type Error = T::Error;
    74
    75    fn poll_frame(
    76        mut self: Pin<&mut Self>,
    77        cx: &mut Context<'_>,
    78    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
    79        Pin::new(&mut **self).poll_frame(cx)
    80    }
    81
    82    fn is_end_stream(&self) -> bool {
    83        Pin::new(&**self).is_end_stream()
    84    }
    85
    86    fn size_hint(&self) -> SizeHint {
    87        Pin::new(&**self).size_hint()
    88    }
    89}
    90
    91impl<P> Body for Pin<P>
    92where
    93    P: Unpin + ops::DerefMut,
    94    P::Target: Body,
    95{
    96    type Data = <<P as ops::Deref>::Target as Body>::Data;
    97    type Error = <<P as ops::Deref>::Target as Body>::Error;
    98
    99    fn poll_frame(
    100        self: Pin<&mut Self>,
    101        cx: &mut Context<'_>,
    102    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
    103        Pin::get_mut(self).as_mut().poll_frame(cx)
    104    }
    105
    106    fn is_end_stream(&self) -> bool {
    107        self.as_ref().is_end_stream()
    108    }
    109
    110    fn size_hint(&self) -> SizeHint {
    111        self.as_ref().size_hint()
    112    }
    113}
    114
    115impl<T: Body + Unpin + ?Sized> Body for Box<T> {
    116    type Data = T::Data;
    117    type Error = T::Error;
    118
    119    fn poll_frame(
    120        mut self: Pin<&mut Self>,
    121        cx: &mut Context<'_>,
    122    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
    123        Pin::new(&mut **self).poll_frame(cx)
    124    }
    125
    126    fn is_end_stream(&self) -> bool {
    127        self.as_ref().is_end_stream()
    128    }
    129
    130    fn size_hint(&self) -> SizeHint {
    131        self.as_ref().size_hint()
    132    }
    133}
    134
    135impl<B: Body> Body for http::Request<B> {
    136    type Data = B::Data;
    137    type Error = B::Error;
    138
    139    fn poll_frame(
    140        self: Pin<&mut Self>,
    141        cx: &mut Context<'_>,
    142    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
    143        // SAFETY:
    144        // A pin projection.
    145        unsafe {
    146            self.map_unchecked_mut(http::Request::body_mut)
    147                .poll_frame(cx)
    148        }
    149    }
    150
    151    fn is_end_stream(&self) -> bool {
    152        self.body().is_end_stream()
    153    }
    154
    155    fn size_hint(&self) -> SizeHint {
    156        self.body().size_hint()
    157    }
    158}
    159
    160impl<B: Body> Body for http::Response<B> {
    161    type Data = B::Data;
    162    type Error = B::Error;
    163
    164    fn poll_frame(
    165        self: Pin<&mut Self>,
    166        cx: &mut Context<'_>,
    167    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
    168        // SAFETY:
    169        // A pin projection.
    170        unsafe {
    171            self.map_unchecked_mut(http::Response::body_mut)
    172                .poll_frame(cx)
    173        }
    174    }
    175
    176    fn is_end_stream(&self) -> bool {
    177        self.body().is_end_stream()
    178    }
    179
    180    fn size_hint(&self) -> SizeHint {
    181        self.body().size_hint()
    182    }
    183}
    184
    185impl Body for String {
    186    type Data = Bytes;
    187    type Error = Infallible;
    188
    189    fn poll_frame(
    190        mut self: Pin<&mut Self>,
    191        _cx: &mut Context<'_>,
    192    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
    193        if !self.is_empty() {
    194            let s = std::mem::take(&mut *self);
    195            Poll::Ready(Some(Ok(Frame::data(s.into_bytes().into()))))
    196        } else {
    197            Poll::Ready(None)
    198        }
    199    }
    200
    201    fn is_end_stream(&self) -> bool {
    202        self.is_empty()
    203    }
    204
    205    fn size_hint(&self) -> SizeHint {
    206        SizeHint::with_exact(self.len() as u64)
    207    }
    208}
    209
    210#[cfg(test)]
    211fn _assert_bounds() {
    212    fn can_be_trait_object(_: &dyn Body<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {}
    213}