1#![doc(html_root_url = "https://docs.rs/http-body/0.4.6")]
2#![deny(
3 missing_debug_implementations,
4 missing_docs,
5 unreachable_pub,
6 broken_intra_doc_links
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 collect;
17mod empty;
18mod full;
19mod limited;
20mod next;
21mod size_hint;
22
23pub mod combinators;
24
25pub use self::collect::Collected;
26pub use self::empty::Empty;
27pub use self::full::Full;
28pub use self::limited::{LengthLimitError, Limited};
29pub use self::next::{Data, Trailers};
30pub use self::size_hint::SizeHint;
31
32use self::combinators::{BoxBody, MapData, MapErr, UnsyncBoxBody};
33use bytes::{Buf, Bytes};
34use http::HeaderMap;
35use std::convert::Infallible;
36use std::ops;
37use std::pin::Pin;
38use std::task::{Context, Poll};
39
40/// Trait representing a streaming body of a Request or Response.
41///
42/// Data is streamed via the `poll_data` function, which asynchronously yields `T: Buf` values. The
43/// `size_hint` function provides insight into the total number of bytes that will be streamed.
44///
45/// The `poll_trailers` function returns an optional set of trailers used to finalize the request /
46/// response exchange. This is mostly used when using the HTTP/2.0 protocol.
47///
48pub trait Body {
49 /// Values yielded by the `Body`.
50 type Data: Buf;
51
52 /// The error type this `Body` might generate.
53 type Error;
54
55 /// Attempt to pull out the next data buffer of this stream.
56 fn poll_data(
57 self: Pin<&mut Self>,
58 cx: &mut Context<'_>,
59 ) -> Poll<Option<Result<Self::Data, Self::Error>>>;
60
61 /// Poll for an optional **single** `HeaderMap` of trailers.
62 ///
63 /// This function should only be called once `poll_data` returns `None`.
64 fn poll_trailers(
65 self: Pin<&mut Self>,
66 cx: &mut Context<'_>,
67 ) -> Poll<Result<Option<HeaderMap>, Self::Error>>;
68
69 /// Returns `true` when the end of stream has been reached.
70 ///
71 /// An end of stream means that both `poll_data` and `poll_trailers` will
72 /// return `None`.
73 ///
74 /// A return value of `false` **does not** guarantee that a value will be
75 /// returned from `poll_stream` or `poll_trailers`.
76 fn is_end_stream(&self) -> bool {
77 false
78 }
79
80 /// Returns the bounds on the remaining length of the stream.
81 ///
82 /// When the **exact** remaining length of the stream is known, the upper bound will be set and
83 /// will equal the lower bound.
84 fn size_hint(&self) -> SizeHint {
85 SizeHint::default()
86 }
87
88 /// Returns future that resolves to next data chunk, if any.
89 fn data(&mut self) -> Data<'_, Self>
90 where
91 Self: Unpin + Sized,
92 {
93 Data(self)
94 }
95
96 /// Returns future that resolves to trailers, if any.
97 fn trailers(&mut self) -> Trailers<'_, Self>
98 where
99 Self: Unpin + Sized,
100 {
101 Trailers(self)
102 }
103
104 /// Maps this body's data value to a different value.
105 fn map_data<F, B>(self, f: F) -> MapData<Self, F>
106 where
107 Self: Sized,
108 F: FnMut(Self::Data) -> B,
109 B: Buf,
110 {
111 MapData::new(self, f)
112 }
113
114 /// Maps this body's error value to a different value.
115 fn map_err<F, E>(self, f: F) -> MapErr<Self, F>
116 where
117 Self: Sized,
118 F: FnMut(Self::Error) -> E,
119 {
120 MapErr::new(self, f)
121 }
122
123 /// Turn this body into [`Collected`] body which will collect all the DATA frames
124 /// and trailers.
125 fn collect(self) -> crate::collect::Collect<Self>
126 where
127 Self: Sized,
128 {
129 collect::Collect::new(self)
130 }
131
132 /// Turn this body into a boxed trait object.
133 fn boxed(self) -> BoxBody<Self::Data, Self::Error>
134 where
135 Self: Sized + Send + Sync + 'static,
136 {
137 BoxBody::new(self)
138 }
139
140 /// Turn this body into a boxed trait object that is !Sync.
141 fn boxed_unsync(self) -> UnsyncBoxBody<Self::Data, Self::Error>
142 where
143 Self: Sized + Send + 'static,
144 {
145 UnsyncBoxBody::new(self)
146 }
147}
148
149impl<T: Body + Unpin + ?Sized> Body for &mut T {
150 type Data = T::Data;
151 type Error = T::Error;
152
153 fn poll_data(
154 mut self: Pin<&mut Self>,
155 cx: &mut Context<'_>,
156 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
157 Pin::new(&mut **self).poll_data(cx)
158 }
159
160 fn poll_trailers(
161 mut self: Pin<&mut Self>,
162 cx: &mut Context<'_>,
163 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
164 Pin::new(&mut **self).poll_trailers(cx)
165 }
166
167 fn is_end_stream(&self) -> bool {
168 Pin::new(&**self).is_end_stream()
169 }
170
171 fn size_hint(&self) -> SizeHint {
172 Pin::new(&**self).size_hint()
173 }
174}
175
176impl<P> Body for Pin<P>
177where
178 P: Unpin + ops::DerefMut,
179 P::Target: Body,
180{
181 type Data = <<P as ops::Deref>::Target as Body>::Data;
182 type Error = <<P as ops::Deref>::Target as Body>::Error;
183
184 fn poll_data(
185 self: Pin<&mut Self>,
186 cx: &mut Context<'_>,
187 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
188 Pin::get_mut(self).as_mut().poll_data(cx)
189 }
190
191 fn poll_trailers(
192 self: Pin<&mut Self>,
193 cx: &mut Context<'_>,
194 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
195 Pin::get_mut(self).as_mut().poll_trailers(cx)
196 }
197
198 fn is_end_stream(&self) -> bool {
199 self.as_ref().is_end_stream()
200 }
201
202 fn size_hint(&self) -> SizeHint {
203 self.as_ref().size_hint()
204 }
205}
206
207impl<T: Body + Unpin + ?Sized> Body for Box<T> {
208 type Data = T::Data;
209 type Error = T::Error;
210
211 fn poll_data(
212 mut self: Pin<&mut Self>,
213 cx: &mut Context<'_>,
214 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
215 Pin::new(&mut **self).poll_data(cx)
216 }
217
218 fn poll_trailers(
219 mut self: Pin<&mut Self>,
220 cx: &mut Context<'_>,
221 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
222 Pin::new(&mut **self).poll_trailers(cx)
223 }
224
225 fn is_end_stream(&self) -> bool {
226 self.as_ref().is_end_stream()
227 }
228
229 fn size_hint(&self) -> SizeHint {
230 self.as_ref().size_hint()
231 }
232}
233
234impl<B: Body> Body for http::Request<B> {
235 type Data = B::Data;
236 type Error = B::Error;
237
238 fn poll_data(
239 self: Pin<&mut Self>,
240 cx: &mut Context<'_>,
241 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
242 unsafe {
243 self.map_unchecked_mut(http::Request::body_mut)
244 .poll_data(cx)
245 }
246 }
247
248 fn poll_trailers(
249 self: Pin<&mut Self>,
250 cx: &mut Context<'_>,
251 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
252 unsafe {
253 self.map_unchecked_mut(http::Request::body_mut)
254 .poll_trailers(cx)
255 }
256 }
257
258 fn is_end_stream(&self) -> bool {
259 self.body().is_end_stream()
260 }
261
262 fn size_hint(&self) -> SizeHint {
263 self.body().size_hint()
264 }
265}
266
267impl<B: Body> Body for http::Response<B> {
268 type Data = B::Data;
269 type Error = B::Error;
270
271 fn poll_data(
272 self: Pin<&mut Self>,
273 cx: &mut Context<'_>,
274 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
275 unsafe {
276 self.map_unchecked_mut(http::Response::body_mut)
277 .poll_data(cx)
278 }
279 }
280
281 fn poll_trailers(
282 self: Pin<&mut Self>,
283 cx: &mut Context<'_>,
284 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
285 unsafe {
286 self.map_unchecked_mut(http::Response::body_mut)
287 .poll_trailers(cx)
288 }
289 }
290
291 fn is_end_stream(&self) -> bool {
292 self.body().is_end_stream()
293 }
294
295 fn size_hint(&self) -> SizeHint {
296 self.body().size_hint()
297 }
298}
299
300impl Body for String {
301 type Data = Bytes;
302 type Error = Infallible;
303
304 fn poll_data(
305 mut self: Pin<&mut Self>,
306 _cx: &mut Context<'_>,
307 ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
308 if !self.is_empty() {
309 let s = std::mem::take(&mut *self);
310 Poll::Ready(Some(Ok(s.into_bytes().into())))
311 } else {
312 Poll::Ready(None)
313 }
314 }
315
316 fn poll_trailers(
317 self: Pin<&mut Self>,
318 _cx: &mut Context<'_>,
319 ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
320 Poll::Ready(Ok(None))
321 }
322
323 fn is_end_stream(&self) -> bool {
324 self.is_empty()
325 }
326
327 fn size_hint(&self) -> SizeHint {
328 SizeHint::with_exact(self.len() as u64)
329 }
330}
331
332#[cfg(test)]
333fn _assert_bounds() {
334 fn can_be_trait_object(_: &dyn Body<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {}
335}
336