predawn_core/
body.rs

1use std::{
2    borrow::Cow,
3    convert::Infallible,
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8use bytes::{Bytes, BytesMut};
9use futures_core::TryStream;
10use futures_util::TryStreamExt;
11use http_body::SizeHint;
12use http_body_util::{combinators::UnsyncBoxBody, BodyExt, Empty, Full, Limited, StreamBody};
13use hyper::body::{Frame, Incoming};
14
15use crate::error::BoxError;
16
17pub type RequestBody = Limited<Incoming>;
18
19#[derive(Debug)]
20pub struct ResponseBody(UnsyncBoxBody<Bytes, BoxError>);
21
22impl ResponseBody {
23    pub fn new<B>(body: B) -> Self
24    where
25        B: http_body::Body + Send + 'static,
26        B::Data: Into<Bytes>,
27        B::Error: Into<BoxError>,
28    {
29        Self(
30            body.map_frame(|frame| frame.map_data(Into::into))
31                .map_err(Into::into)
32                .boxed_unsync(),
33        )
34    }
35
36    pub fn empty() -> Self {
37        Self::new(Empty::<Bytes>::new())
38    }
39
40    pub fn from_stream<S>(stream: S) -> Self
41    where
42        S: TryStream + Send + 'static,
43        S::Ok: Into<Bytes>,
44        S::Error: Into<BoxError>,
45    {
46        Self::new(StreamBody::new(
47            stream.map_ok(|data| Frame::data(data.into())),
48        ))
49    }
50
51    pub fn clear(&mut self) {
52        *self = Self::empty();
53    }
54}
55
56impl Default for ResponseBody {
57    fn default() -> Self {
58        Self::empty()
59    }
60}
61
62impl http_body::Body for ResponseBody {
63    type Data = Bytes;
64    type Error = BoxError;
65
66    #[inline]
67    fn poll_frame(
68        mut self: Pin<&mut Self>,
69        cx: &mut Context<'_>,
70    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
71        Pin::new(&mut self.0).poll_frame(cx)
72    }
73
74    #[inline]
75    fn is_end_stream(&self) -> bool {
76        self.0.is_end_stream()
77    }
78
79    #[inline]
80    fn size_hint(&self) -> SizeHint {
81        self.0.size_hint()
82    }
83}
84
85impl From<Full<Bytes>> for ResponseBody {
86    fn from(full: Full<Bytes>) -> Self {
87        Self::new(full)
88    }
89}
90
91macro_rules! impl_from_by_full {
92    ($($ty:ty),+ $(,)?) => {
93        $(
94            impl From<$ty> for ResponseBody {
95                fn from(value: $ty) -> Self {
96                    ResponseBody::from(Full::from(value))
97                }
98            }
99        )+
100    };
101}
102
103impl_from_by_full![
104    &'static [u8],
105    Cow<'static, [u8]>,
106    Vec<u8>,
107    Bytes,
108    &'static str,
109    Cow<'static, str>,
110    String,
111];
112
113impl From<Box<str>> for ResponseBody {
114    fn from(value: Box<str>) -> Self {
115        value.to_string().into()
116    }
117}
118
119impl From<Box<[u8]>> for ResponseBody {
120    fn from(value: Box<[u8]>) -> Self {
121        Vec::from(value).into()
122    }
123}
124
125impl From<BytesMut> for ResponseBody {
126    fn from(value: BytesMut) -> Self {
127        value.freeze().into()
128    }
129}
130
131impl<const N: usize> From<[u8; N]> for ResponseBody {
132    fn from(value: [u8; N]) -> Self {
133        value.to_vec().into()
134    }
135}
136
137impl<const N: usize> From<&'static [u8; N]> for ResponseBody {
138    fn from(value: &'static [u8; N]) -> Self {
139        value.as_slice().into()
140    }
141}
142
143impl From<()> for ResponseBody {
144    fn from(_: ()) -> Self {
145        Self::empty()
146    }
147}
148
149impl From<Infallible> for ResponseBody {
150    fn from(value: Infallible) -> Self {
151        match value {}
152    }
153}