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 | |
16 | mod frame; |
17 | mod size_hint; |
18 | |
19 | pub use self::frame::Frame; |
20 | pub use self::size_hint::SizeHint; |
21 | |
22 | use bytes::{Buf, Bytes}; |
23 | use std::convert::Infallible; |
24 | use std::ops; |
25 | use std::pin::Pin; |
26 | use 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. |
38 | pub 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 | |
71 | impl<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 | |
91 | impl<P> Body for Pin<P> |
92 | where |
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 | |
115 | impl<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 | |
135 | impl<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(func: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 | |
160 | impl<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(func: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 | |
185 | impl 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: String = std::mem::take(&mut *self); |
195 | Poll::Ready(Some(Ok(Frame::data(buf: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)] |
211 | fn _assert_bounds() { |
212 | fn can_be_trait_object(_: &dyn Body<Data = std::io::Cursor<Vec<u8>>, Error = std::io::Error>) {} |
213 | } |
214 | |