Skip to main content

http_body_alt/
body.rs

1use core::{
2    ops::{Deref, DerefMut},
3    pin::Pin,
4    task::{Context, Poll},
5};
6
7use super::{frame::Frame, size_hint::SizeHint};
8
9type Result<T, E> = std::result::Result<Frame<T>, E>;
10
11/// An asynchronous streaming body composed of [`Frame`]s.
12///
13/// Each frame is either a [`Frame::Data`] carrying payload bytes or a [`Frame::Trailers`]
14/// carrying trailing headers. The stream signals completion by returning `Poll::Ready(None)`.
15pub trait Body {
16    /// The payload data type yielded by [`Frame::Data`] variants.
17    type Data;
18    /// The error type that can occur while producing frames.
19    type Error;
20
21    /// Attempt to pull the next frame from the body.
22    ///
23    /// # Return values
24    ///
25    /// - `Poll::Pending` — the next frame is not yet available.
26    /// - `Poll::Ready(Some(Ok(frame)))` — a [`Frame::Data`] or [`Frame::Trailers`] frame.
27    /// - `Poll::Ready(Some(Err(e)))` — a terminal error; no further frames will be produced.
28    /// - `Poll::Ready(None)` — the body is fully consumed.
29    fn poll_frame(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Result<Self::Data, Self::Error>>>;
30
31    /// Indicates whether the body has been fully consumed.
32    ///
33    /// - `true` — the body is exhausted and [`Body::poll_frame`] should not be called again.
34    /// - `false` — the body may still have frames to yield, or its state is unknown.
35    ///
36    /// Implementors SHOULD override this method when possible. Accurate reporting improves
37    /// correctness and performance of consumers that can skip polling when the body is empty.
38    #[inline]
39    fn is_end_stream(&self) -> bool {
40        false
41    }
42
43    /// Returns a hint about the total size of the remaining [`Frame::Data`] payload.
44    ///
45    /// The hint applies only to data frames; trailer frames are not included.
46    ///
47    /// Implementors SHOULD override this method when possible. An accurate size hint allows
48    /// consumers to pre-allocate buffers and set content-length headers.
49    #[inline]
50    fn size_hint(&self) -> SizeHint {
51        SizeHint::default()
52    }
53}
54
55impl<B> Body for Box<B>
56where
57    B: Body + ?Sized + Unpin,
58{
59    type Data = B::Data;
60    type Error = B::Error;
61
62    #[inline]
63    fn poll_frame(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Result<Self::Data, Self::Error>>> {
64        Body::poll_frame(Pin::new(self.get_mut().deref_mut()), cx)
65    }
66
67    #[inline]
68    fn is_end_stream(&self) -> bool {
69        self.deref().is_end_stream()
70    }
71
72    #[inline]
73    fn size_hint(&self) -> SizeHint {
74        self.deref().size_hint()
75    }
76}
77
78impl<B> Body for Pin<B>
79where
80    B: DerefMut,
81    B::Target: Body,
82{
83    type Data = <B::Target as Body>::Data;
84    type Error = <B::Target as Body>::Error;
85
86    #[inline]
87    fn poll_frame(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Result<Self::Data, Self::Error>>> {
88        Body::poll_frame(self.as_deref_mut(), cx)
89    }
90
91    #[inline]
92    fn is_end_stream(&self) -> bool {
93        self.as_ref().is_end_stream()
94    }
95
96    #[inline]
97    fn size_hint(&self) -> SizeHint {
98        self.as_ref().size_hint()
99    }
100}