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