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}