1pub use xitca_http::body::{
4 Body, BodyExt, BoxBody, Empty, Frame, Full, RequestBody, ResponseBody, SizeHint, StreamBody, StreamDataBody,
5 Trailers,
6};
7
8pub(crate) use xitca_http::body::Either;
9
10use core::any::Any;
11
12use crate::{bytes::Bytes, error::BodyError};
13
14pub trait BodyStream: Body<Data: Into<Bytes> + AsRef<[u8]> + 'static, Error: Into<BodyError>> {}
16
17impl<B> BodyStream for B
18where
19 B: Body,
20 B::Data: Into<Bytes> + AsRef<[u8]> + 'static,
21 B::Error: Into<BodyError>,
22{
23}
24
25pub(crate) fn downcast_body<B: BodyStream + 'static>(body: B) -> RequestBody {
27 let body = &mut Some(body);
28 match (body as &mut dyn Any).downcast_mut::<Option<RequestBody>>() {
29 Some(body) => body.take().unwrap(),
30 None => RequestBody::Boxed(BoxBody::new(body.take().unwrap())),
31 }
32}
33
34#[cfg(feature = "nightly")]
35pub use nightly::AsyncBody;
36
37#[cfg(feature = "nightly")]
38mod nightly {
39 use core::{
40 async_iter::AsyncIterator,
41 pin::Pin,
42 task::{Context, Poll},
43 };
44
45 use pin_project_lite::pin_project;
46
47 use crate::{body::Frame, bytes::Bytes};
48
49 use super::*;
50
51 pin_project! {
52 pub struct AsyncBody<B> {
53 #[pin]
54 inner: B
55 }
56
57 }
58
59 impl<B, T, E> From<B> for AsyncBody<B>
60 where
61 B: AsyncIterator<Item = Result<T, E>> + 'static,
62 E: Into<BodyError>,
63 Bytes: From<T>,
64 {
65 fn from(inner: B) -> Self {
66 Self { inner }
67 }
68 }
69
70 impl<B, T, E> Body for AsyncBody<B>
71 where
72 B: AsyncIterator<Item = Result<T, E>>,
73 Bytes: From<T>,
74 {
75 type Data = Bytes;
76 type Error = E;
77
78 #[inline]
79 fn poll_frame(
80 self: Pin<&mut Self>,
81 cx: &mut Context<'_>,
82 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
83 AsyncIterator::poll_next(self.project().inner, cx).map_ok(|data| Frame::Data(data.into()))
84 }
85 }
86}