Skip to main content

xitca_web/
body.rs

1//! http body types and traits.
2
3pub 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
13/// an extended trait for [Stream] that specify additional type info of the [Stream::Item] type.
14pub 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
24// conditional boxing body to convert generic body type to conrete
25pub(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}