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