xitca_web/
body.rs

1//! http body types and traits.
2
3use futures_core::stream::Stream;
4
5pub use xitca_http::body::{BoxBody, NONE_BODY_HINT, RequestBody, ResponseBody, none_body_hint};
6
7pub(crate) use xitca_http::body::Either;
8
9use crate::error::BodyError;
10
11/// an extended trait for [Stream] that specify additional type info of the [Stream::Item] type.
12pub trait BodyStream: Stream<Item = Result<Self::Chunk, Self::Error>> {
13    type Chunk: AsRef<[u8]> + 'static;
14    type Error: Into<BodyError>;
15}
16
17impl<S, T, E> BodyStream for S
18where
19    S: Stream<Item = Result<T, E>>,
20    T: AsRef<[u8]> + 'static,
21    E: Into<BodyError>,
22{
23    type Chunk = T;
24    type Error = E;
25}
26
27#[cfg(feature = "nightly")]
28pub use nightly::AsyncBody;
29
30#[cfg(feature = "nightly")]
31mod nightly {
32    use core::{
33        async_iter::AsyncIterator,
34        pin::Pin,
35        task::{Context, Poll},
36    };
37
38    use pin_project_lite::pin_project;
39
40    use crate::bytes::Bytes;
41
42    use super::*;
43
44    pin_project! {
45        pub struct AsyncBody<B> {
46            #[pin]
47            inner: B
48        }
49
50    }
51
52    impl<B, T, E> From<B> for AsyncBody<B>
53    where
54        B: AsyncIterator<Item = Result<T, E>> + 'static,
55        E: Into<BodyError>,
56        Bytes: From<T>,
57    {
58        fn from(inner: B) -> Self {
59            Self { inner }
60        }
61    }
62
63    impl<B, T, E> Stream for AsyncBody<B>
64    where
65        B: AsyncIterator<Item = Result<T, E>>,
66        Bytes: From<T>,
67    {
68        type Item = Result<Bytes, E>;
69
70        #[inline]
71        fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
72            AsyncIterator::poll_next(self.project().inner, cx).map_ok(Bytes::from)
73        }
74    }
75}