@@ -24,6 +24,20 @@ pub mod util {
2424 pub use http_body_util:: * ;
2525}
2626
27+ /// A HTTP Body.
28+ ///
29+ /// Construct this HTTP body using:
30+ /// * `Body::empty` for the empty body, or `impl From<()> for Body`
31+ /// * `From<&[u8]>` (which will make a clone) or `From<Vec<u8>>` or
32+ /// `From<Bytes>` for a `Body` from bytes.
33+ /// * `From<&str>` (which will make a clone) or `From<String>` for a `Body`
34+ /// from strings.
35+ /// * `Body::from_json` for a `Body` from a `Serialize` (requires feature
36+ /// `json`)
37+ /// * `Body::from_stream` or `Body::from_try_stream` for a `Body` from a
38+ /// `Stream` of `Into<Bytes>`
39+ ///
40+ /// Consume
2741#[ derive( Debug ) ]
2842pub struct Body ( BodyInner ) ;
2943
@@ -41,7 +55,7 @@ enum BodyInner {
4155}
4256
4357impl Body {
44- pub async fn send ( self , outgoing_body : WasiOutgoingBody ) -> Result < ( ) , Error > {
58+ pub ( crate ) async fn send ( self , outgoing_body : WasiOutgoingBody ) -> Result < ( ) , Error > {
4559 match self . 0 {
4660 BodyInner :: Incoming ( incoming) => incoming. send ( outgoing_body) . await ,
4761 BodyInner :: Boxed ( box_body) => {
@@ -107,17 +121,6 @@ impl Body {
107121 }
108122 }
109123
110- pub fn as_boxed_body ( & mut self ) -> & mut UnsyncBoxBody < Bytes , Error > {
111- let mut prev = Self :: empty ( ) ;
112- std:: mem:: swap ( self , & mut prev) ;
113- self . 0 = BodyInner :: Boxed ( prev. into_boxed_body ( ) ) ;
114-
115- match & mut self . 0 {
116- BodyInner :: Boxed ( ref mut b) => b,
117- _ => unreachable ! ( ) ,
118- }
119- }
120-
121124 pub async fn contents ( & mut self ) -> Result < & [ u8 ] , Error > {
122125 match & mut self . 0 {
123126 BodyInner :: Complete { ref data, .. } => Ok ( data. as_ref ( ) ) ,
@@ -154,34 +157,22 @@ impl Body {
154157 }
155158 }
156159
160+ /// Construct an empty Body
157161 pub fn empty ( ) -> Self {
158162 Body ( BodyInner :: Complete {
159163 data : Bytes :: new ( ) ,
160164 trailers : None ,
161165 } )
162166 }
163167
164- pub fn from_string ( s : impl Into < String > ) -> Self {
165- let s = s. into ( ) ;
166- Body ( BodyInner :: Complete {
167- data : Bytes :: from_owner ( s. into_bytes ( ) ) ,
168- trailers : None ,
169- } )
170- }
171-
172168 pub async fn str_contents ( & mut self ) -> Result < & str , Error > {
173169 let bs = self . contents ( ) . await ?;
174170 std:: str:: from_utf8 ( bs) . context ( "decoding body contents as string" )
175171 }
176172
177- pub fn from_bytes ( b : impl Into < Bytes > ) -> Self {
178- let b = b. into ( ) ;
179- Body :: from ( http_body_util:: Full :: new ( b) )
180- }
181-
182173 #[ cfg( feature = "json" ) ]
183174 pub fn from_json < T : serde:: Serialize > ( data : & T ) -> Result < Self , serde_json:: Error > {
184- Ok ( Self :: from_string ( serde_json:: to_string ( data) ?) )
175+ Ok ( Self :: from ( serde_json:: to_vec ( data) ?) )
185176 }
186177
187178 #[ cfg( feature = "json" ) ]
@@ -190,28 +181,38 @@ impl Body {
190181 serde_json:: from_str ( str) . context ( "decoding body contents as json" )
191182 }
192183
193- pub fn from_input_stream ( r : crate :: io:: AsyncInputStream ) -> Self {
194- use futures_lite:: stream:: StreamExt ;
195- Body ( BodyInner :: Boxed ( http_body_util:: BodyExt :: boxed_unsync (
196- http_body_util:: StreamBody :: new ( r. into_stream ( ) . map ( |res| {
197- res. map ( |bytevec| Frame :: data ( Bytes :: from_owner ( bytevec) ) )
198- . map_err ( Into :: into)
199- } ) ) ,
200- ) ) )
201- }
202-
203184 pub ( crate ) fn from_incoming ( body : WasiIncomingBody , size_hint : BodyHint ) -> Self {
204185 Body ( BodyInner :: Incoming ( Incoming { body, size_hint } ) )
205186 }
206- }
207187
208- impl < B > From < B > for Body
209- where
210- B : HttpBody + Send + ' static ,
211- <B as HttpBody >:: Data : Into < Bytes > ,
212- <B as HttpBody >:: Error : Into < Error > ,
213- {
214- fn from ( http_body : B ) -> Body {
188+ pub fn from_stream < S > ( stream : S ) -> Self
189+ where
190+ S : futures_lite:: Stream + Send + ' static ,
191+ <S as futures_lite:: Stream >:: Item : Into < Bytes > ,
192+ {
193+ use futures_lite:: StreamExt ;
194+ Self :: from_http_body ( http_body_util:: StreamBody :: new (
195+ stream. map ( |bs| Ok :: < _ , Error > ( Frame :: data ( bs. into ( ) ) ) ) ,
196+ ) )
197+ }
198+
199+ pub fn from_try_stream < S , D > ( stream : S ) -> Self
200+ where
201+ S : futures_lite:: Stream < Item = Result < D , Error > > + Send + ' static ,
202+ D : Into < Bytes > ,
203+ {
204+ use futures_lite:: StreamExt ;
205+ Self :: from_http_body ( http_body_util:: StreamBody :: new (
206+ stream. map ( |bs| Ok :: < _ , Error > ( Frame :: data ( bs?. into ( ) ) ) ) ,
207+ ) )
208+ }
209+
210+ pub fn from_http_body < B > ( http_body : B ) -> Self
211+ where
212+ B : HttpBody + Send + ' static ,
213+ <B as HttpBody >:: Data : Into < Bytes > ,
214+ <B as HttpBody >:: Error : Into < Error > ,
215+ {
215216 use util:: BodyExt ;
216217 Body ( BodyInner :: Boxed (
217218 http_body
@@ -222,9 +223,52 @@ where
222223 }
223224}
224225
225- impl From < Incoming > for Body {
226- fn from ( incoming : Incoming ) -> Body {
227- Body ( BodyInner :: Incoming ( incoming) )
226+ impl From < ( ) > for Body {
227+ fn from ( _: ( ) ) -> Body {
228+ Body :: empty ( )
229+ }
230+ }
231+ impl From < & [ u8 ] > for Body {
232+ fn from ( bytes : & [ u8 ] ) -> Body {
233+ Body :: from ( bytes. to_owned ( ) )
234+ }
235+ }
236+ impl From < Vec < u8 > > for Body {
237+ fn from ( bytes : Vec < u8 > ) -> Body {
238+ Body :: from ( Bytes :: from ( bytes) )
239+ }
240+ }
241+ impl From < Bytes > for Body {
242+ fn from ( data : Bytes ) -> Body {
243+ Body ( BodyInner :: Complete {
244+ data,
245+ trailers : None ,
246+ } )
247+ }
248+ }
249+ impl From < & str > for Body {
250+ fn from ( data : & str ) -> Body {
251+ Body :: from ( data. as_bytes ( ) )
252+ }
253+ }
254+ impl From < String > for Body {
255+ fn from ( data : String ) -> Body {
256+ Body :: from ( data. into_bytes ( ) )
257+ }
258+ }
259+
260+ impl From < crate :: io:: AsyncInputStream > for Body {
261+ fn from ( r : crate :: io:: AsyncInputStream ) -> Body {
262+ // TODO: with another BodyInner variant for a boxed AsyncRead for which
263+ // as_input_stream is_some, this could allow for use of
264+ // crate::io::copy.
265+ use futures_lite:: stream:: StreamExt ;
266+ Body ( BodyInner :: Boxed ( http_body_util:: BodyExt :: boxed_unsync (
267+ http_body_util:: StreamBody :: new ( r. into_stream ( ) . map ( |res| {
268+ res. map ( |bytevec| Frame :: data ( Bytes :: from_owner ( bytevec) ) )
269+ . map_err ( Into :: into)
270+ } ) ) ,
271+ ) ) )
228272 }
229273}
230274
0 commit comments