1use crate::error::BodyError as Error;
9use alloc::borrow::ToOwned;
10use alloc::string::String;
11use bytes::Bytes;
12use http_body::{Body, Frame, SizeHint};
13use http_body_util::{BodyExt, Collected, Empty, Full};
14
15#[cfg(feature = "stream")]
16use alloc::boxed::Box;
17#[cfg(any(feature = "stream", feature = "incoming"))]
18use alloc::string::ToString;
19#[cfg(any(feature = "stream", feature = "box_body"))]
20use futures::Stream;
21#[cfg(feature = "stream")]
22use http_body_util::BodyStream;
23#[cfg(any(feature = "stream", feature = "box_body"))]
24use http_body_util::StreamBody;
25
26use product_os_http::{Request, Response};
27
28#[cfg(feature = "stream")]
29use crate::data_stream::{DataStream, DataStreamBody};
30#[cfg(any(feature = "incoming", feature = "stream"))]
31use hyper::body::Incoming;
32
33#[cfg(feature = "box_body")]
34use futures::TryStreamExt;
35#[cfg(feature = "box_body")]
36use futures_util::TryStream;
37#[cfg(feature = "box_body")]
38use http_body_util::combinators::BoxBody;
39
40#[cfg(feature = "std")]
41use std::{pin::Pin, task::Poll};
42
43#[derive(Debug)]
44enum Internal {
45 Collected(Collected<Bytes>),
46 Empty(Empty<Bytes>),
47 Full(Full<Bytes>),
48 String(String),
49 #[cfg(feature = "stream")]
50 BodyStream(BodyStream<Incoming>),
51 #[cfg(feature = "stream")]
52 Stream(StreamBody<DataStream<DataStreamBody>>),
53 #[cfg(feature = "box_body")]
54 BoxBody(BoxBody<Bytes, Error>),
55 #[cfg(feature = "incoming")]
56 Incoming(Incoming),
57}
58
59#[derive(Debug)]
108pub struct BodyBytes {
109 inner: Internal,
110}
111
112impl Default for BodyBytes {
113 fn default() -> Self {
114 Self::empty()
115 }
116}
117
118impl BodyBytes {
119 pub fn empty() -> Self {
120 Self::from(Empty::new())
121 }
122
123 pub fn new(bytes: Bytes) -> Self {
124 Self {
125 inner: Internal::Full(Full::new(bytes)),
126 }
127 }
128
129 #[cfg(feature = "stream")]
130 pub fn new_stream<
131 E: Into<Box<dyn core::error::Error + core::marker::Send + Sync + 'static>>,
132 >(
133 s: impl Stream<Item = Result<Bytes, E>> + Send + 'static,
134 ) -> Self {
135 let stream_body = DataStreamBody::stream(s);
136 let data_stream = DataStream(stream_body);
137
138 Self {
139 inner: Internal::Stream(StreamBody::new(data_stream)),
140 }
141 }
142
143 pub async fn convert_to_bytes(self) -> Result<Bytes, Error> {
144 match self.inner {
145 Internal::String(s) => Ok(Bytes::from(s.to_owned())),
146 Internal::Empty(e) => {
147 let bytes = e.collect().await.unwrap().to_bytes();
148 Ok(bytes)
149 }
150 Internal::Full(f) => {
151 let bytes = f.collect().await.unwrap().to_bytes();
152 Ok(bytes)
153 }
154 Internal::Collected(c) => {
155 let bytes = c.collect().await.unwrap().to_bytes();
156 Ok(bytes)
157 }
158 #[cfg(feature = "stream")]
159 Internal::BodyStream(b) => {
160 let bytes = BodyExt::collect(b).await.unwrap().to_bytes();
161 Ok(bytes)
162 }
163 #[cfg(feature = "stream")]
164 Internal::Stream(b) => {
165 let bytes = BodyExt::collect(b).await.unwrap().to_bytes();
166 Ok(bytes)
167 }
168 #[cfg(feature = "box_body")]
169 Internal::BoxBody(b) => {
170 let bytes = b.collect().await.unwrap().to_bytes();
171 Ok(bytes)
172 }
173 #[cfg(feature = "incoming")]
174 Internal::Incoming(i) => {
175 let bytes = i.collect().await.unwrap().to_bytes();
176 Ok(bytes)
177 }
178 }
179 }
180
181 pub async fn as_bytes(&mut self) -> Result<Bytes, Error> {
182 match &mut self.inner {
183 Internal::String(s) => Ok(Bytes::from(s.to_owned())),
184 Internal::Empty(e) => {
185 let bytes = e.collect().await.unwrap().to_bytes();
186 self.inner = Internal::Empty(Empty::new());
187 Ok(bytes)
188 }
189 Internal::Full(f) => {
190 let bytes = f.collect().await.unwrap().to_bytes();
191 self.inner = Internal::Full(Full::new(bytes.to_owned()));
192 Ok(bytes)
193 }
194 Internal::Collected(c) => {
195 let bytes = c.collect().await.unwrap().to_bytes();
196 self.inner =
197 Internal::Collected(Full::new(bytes.to_owned()).collect().await.unwrap());
198 Ok(bytes)
199 }
200 #[cfg(feature = "stream")]
201 Internal::BodyStream(b) => {
202 let bytes = BodyExt::collect(b).await.unwrap().to_bytes();
203 self.inner =
204 Internal::Collected(Full::new(bytes.to_owned()).collect().await.unwrap());
205 Ok(bytes)
206 }
207 #[cfg(feature = "stream")]
208 Internal::Stream(b) => {
209 let bytes = BodyExt::collect(b).await.unwrap().to_bytes();
210 self.inner =
211 Internal::Collected(Full::new(bytes.to_owned()).collect().await.unwrap());
212 Ok(bytes)
213 }
214 #[cfg(feature = "box_body")]
215 Internal::BoxBody(_b) => {
216 Err(Error::DecodeToBytes(String::from(
222 "Box body not yet implemented",
223 )))
224 }
225 #[cfg(feature = "incoming")]
226 Internal::Incoming(_i) => Err(Error::DecodeToBytes(String::from(
227 "Incoming not yet implemented",
228 ))),
229 }
230 }
231
232 #[cfg(feature = "box_body")]
233 pub fn from_stream<S>(stream: S) -> Self
234 where
235 S: TryStream + Send + Sync + 'static,
236 S::Ok: Into<Bytes>,
237 S::Error: Into<Error>,
238 {
239 Self {
240 inner: Internal::BoxBody(BoxBody::new(StreamBody::new(
241 stream
242 .map_ok(Into::into)
243 .map_ok(Frame::data)
244 .map_err(Into::into),
245 ))),
246 }
247 }
248}
249
250impl Body for BodyBytes {
251 type Data = Bytes;
252 type Error = Error;
253
254 fn poll_frame(
255 mut self: Pin<&mut Self>,
256 cx: &mut std::task::Context<'_>,
257 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
258 match &mut self.inner {
259 Internal::Collected(body) => Pin::new(body).poll_frame(cx).map_err(|e| match e {}),
260 Internal::Empty(body) => Pin::new(body).poll_frame(cx).map_err(|e| match e {}),
261 Internal::Full(body) => Pin::new(body).poll_frame(cx).map_err(|e| match e {}),
262 Internal::String(body) => Pin::new(body).poll_frame(cx).map_err(|e| match e {}),
263 #[cfg(feature = "stream")]
264 Internal::BodyStream(body) => match Pin::new(body).poll_frame(cx) {
265 Poll::Ready(Some(ready)) => match ready {
266 Ok(frame) => Poll::Ready(Some(Ok(frame))),
267 Err(e) => Poll::Ready(Some(Err(Error::Network(e.to_string())))),
268 },
269 Poll::Ready(None) => Poll::Ready(None),
270 Poll::Pending => Poll::Pending,
271 },
272 #[cfg(feature = "stream")]
273 Internal::Stream(body) => match Pin::new(body).poll_frame(cx) {
274 Poll::Ready(Some(ready)) => match ready {
275 Ok(frame) => Poll::Ready(Some(Ok(frame))),
276 Err(e) => Poll::Ready(Some(Err(Error::Network(e.to_string())))),
277 },
278 Poll::Ready(None) => Poll::Ready(None),
279 Poll::Pending => Poll::Pending,
280 },
281 #[cfg(feature = "box_body")]
282 Internal::BoxBody(body) => Pin::new(body).poll_frame(cx),
283 #[cfg(feature = "incoming")]
284 Internal::Incoming(body) => Pin::new(body)
285 .poll_frame(cx)
286 .map_err(|e| Error::Network(e.to_string())),
287 }
288 }
289
290 fn is_end_stream(&self) -> bool {
291 match &self.inner {
292 Internal::Collected(body) => body.is_end_stream(),
293 Internal::Empty(body) => body.is_end_stream(),
294 Internal::Full(body) => body.is_end_stream(),
295 Internal::String(body) => body.is_end_stream(),
296 #[cfg(feature = "stream")]
297 Internal::BodyStream(body) => body.is_end_stream(),
298 #[cfg(feature = "stream")]
299 Internal::Stream(body) => body.is_end_stream(),
300 #[cfg(feature = "box_body")]
301 Internal::BoxBody(body) => body.is_end_stream(),
302 #[cfg(feature = "incoming")]
303 Internal::Incoming(body) => body.is_end_stream(),
304 }
305 }
306
307 fn size_hint(&self) -> SizeHint {
308 match &self.inner {
309 Internal::Collected(body) => body.size_hint(),
310 Internal::Empty(body) => body.size_hint(),
311 Internal::Full(body) => body.size_hint(),
312 Internal::String(body) => body.size_hint(),
313 #[cfg(feature = "stream")]
314 Internal::BodyStream(body) => Body::size_hint(body),
315 #[cfg(feature = "stream")]
316 Internal::Stream(body) => Body::size_hint(body),
317 #[cfg(feature = "box_body")]
318 Internal::BoxBody(body) => body.size_hint(),
319 #[cfg(feature = "incoming")]
320 Internal::Incoming(body) => body.size_hint(),
321 }
322 }
323}
324
325impl From<Collected<Bytes>> for BodyBytes {
326 fn from(value: Collected<Bytes>) -> Self {
327 Self {
328 inner: Internal::Collected(value),
329 }
330 }
331}
332
333impl From<Empty<Bytes>> for BodyBytes {
334 fn from(value: Empty<Bytes>) -> Self {
335 Self {
336 inner: Internal::Empty(value),
337 }
338 }
339}
340
341impl From<Full<Bytes>> for BodyBytes {
342 fn from(value: Full<Bytes>) -> Self {
343 Self {
344 inner: Internal::Full(value),
345 }
346 }
347}
348
349#[cfg(feature = "stream")]
350impl From<BodyStream<Incoming>> for BodyBytes {
351 fn from(value: BodyStream<Incoming>) -> Self {
352 Self {
353 inner: Internal::BodyStream(value),
354 }
355 }
356}
357
358#[cfg(feature = "stream")]
359impl From<DataStreamBody> for BodyBytes {
360 fn from(value: DataStreamBody) -> Self {
361 let data_stream = DataStream(value);
362
363 Self {
364 inner: Internal::Stream(StreamBody::new(data_stream)),
365 }
366 }
367}
368
369#[cfg(feature = "box_body")]
370impl From<BoxBody<Bytes, Error>> for BodyBytes {
371 fn from(value: BoxBody<Bytes, Error>) -> Self {
372 Self {
373 inner: Internal::BoxBody(value),
374 }
375 }
376}
377
378#[cfg(feature = "incoming")]
379impl From<Incoming> for BodyBytes {
380 fn from(value: Incoming) -> Self {
381 Self {
382 inner: Internal::Incoming(value),
383 }
384 }
385}
386
387impl From<Bytes> for BodyBytes {
388 fn from(value: Bytes) -> Self {
389 Self {
390 inner: Internal::Full(Full::new(value)),
391 }
392 }
393}
394
395impl From<alloc::vec::Vec<u8>> for BodyBytes {
396 fn from(value: alloc::vec::Vec<u8>) -> Self {
397 Self {
398 inner: Internal::Full(Full::new(Bytes::from(value))),
399 }
400 }
401}
402
403impl From<String> for BodyBytes {
404 fn from(value: String) -> Self {
405 Self {
406 inner: Internal::String(value),
407 }
408 }
409}
410
411impl From<&'static str> for BodyBytes {
412 fn from(value: &'static str) -> Self {
413 Self {
414 inner: Internal::Full(Full::new(Bytes::from_static(value.as_bytes()))),
415 }
416 }
417}
418
419impl From<&'static [u8]> for BodyBytes {
420 fn from(value: &'static [u8]) -> Self {
421 Self {
422 inner: Internal::Full(Full::new(Bytes::from_static(value))),
423 }
424 }
425}
426
427impl<T> From<Request<T>> for BodyBytes
428where
429 T: Into<BodyBytes>,
430{
431 fn from(value: Request<T>) -> Self {
432 value.into_body().into()
433 }
434}
435
436impl<T> From<Response<T>> for BodyBytes
437where
438 T: Into<BodyBytes>,
439{
440 fn from(value: Response<T>) -> Self {
441 value.into_body().into()
442 }
443}
444
445#[cfg(feature = "box_body")]
446impl<S> From<StreamBody<S>> for BodyBytes
447where
448 S: Stream<Item = Result<Frame<Bytes>, Error>> + Send + Sync + 'static,
449{
450 fn from(value: StreamBody<S>) -> Self {
451 Self {
452 inner: Internal::BoxBody(BoxBody::new(value)),
453 }
454 }
455}
456
457impl Clone for BodyBytes {
458 fn clone(&self) -> Self {
459 match &self.inner {
460 Internal::Empty(body) => Self {
468 inner: Internal::Empty(body.to_owned()),
469 },
470 Internal::Full(body) => Self {
471 inner: Internal::Full(body.to_owned()),
472 },
473 Internal::String(body) => Self {
474 inner: Internal::String(body.to_owned()),
475 },
476 #[cfg(feature = "box_body")]
477 Internal::BoxBody(_body) => {
478 panic!("Clone not yet implemented for BoxBody")
479 }
480 #[cfg(feature = "incoming")]
481 Internal::Incoming(_body) => {
482 panic!("Clone not yet implemented for Incoming")
483 }
484 _ => panic!("Unable to handle clone"),
485 }
486 }
487}
488
489#[cfg(feature = "axum")]
490impl axum_core::response::IntoResponse for BodyBytes {
491 fn into_response(self) -> axum_core::response::Response {
492 axum_core::response::Response::new(axum_core::body::Body::new(self))
493 }
494}