1use hyper::body::{Body, Buf, Frame};
2use std::error::Error;
3use std::pin::Pin;
4use std::task::{Context, Poll};
5
6trait ErasedBody: Send + Sync {
8 fn poll_frame(
9 self: Pin<&mut Self>,
10 cx: &mut Context<'_>,
11 ) -> Poll<Option<Result<Frame<Box<dyn Buf + Send>>, Box<dyn Error + Send + Sync>>>>;
12}
13
14impl<B> ErasedBody for B
16where
17 B: Body + Send + Sync + 'static,
18 B::Data: Buf + Send + 'static,
19 B::Error: Error + Send + Sync + 'static,
20{
21 fn poll_frame(
22 self: Pin<&mut Self>,
23 cx: &mut Context<'_>,
24 ) -> Poll<Option<Result<Frame<Box<dyn Buf + Send>>, Box<dyn Error + Send + Sync>>>> {
25 match <Self as Body>::poll_frame(self, cx) {
26 Poll::Pending => Poll::Pending,
27 Poll::Ready(None) => Poll::Ready(None),
28 Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(Box::new(e)))),
29 Poll::Ready(Some(Ok(frame))) => {
30 let mapped = frame.map_data(|d| Box::new(d) as Box<dyn Buf + Send>);
31 Poll::Ready(Some(Ok(mapped)))
32 }
33 }
34 }
35}
36
37pub struct VariantBody {
39 inner: Pin<Box<dyn ErasedBody + 'static>>,
40}
41
42impl VariantBody {
43 pub fn new<B>(body: B) -> Self
44 where
45 B: Body + Send + Sync + 'static,
46 B::Data: Buf + Send + 'static,
47 B::Error: Error + Send + Sync + 'static,
48 {
49 Self {
50 inner: Box::pin(body),
51 }
52 }
53}
54
55impl Body for VariantBody {
57 type Data = Box<dyn Buf + Send>;
58 type Error = Box<dyn Error + Send + Sync>;
59
60 fn poll_frame(
61 self: Pin<&mut Self>,
62 cx: &mut Context<'_>,
63 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
64 self.get_mut().inner.as_mut().poll_frame(cx)
65 }
66}
67
68pub type Empty = http_body_util::Empty<hyper::body::Bytes>;
69
70pub type Full = http_body_util::Full<hyper::body::Bytes>;
71
72pub fn empty() -> VariantBody {
73 VariantBody::new(Empty::new())
74}
75
76pub fn variant_body<B>(body: B) -> VariantBody
77where
78 B: Body + Send + Sync + 'static,
79 B::Data: Buf + Send + 'static,
80 B::Error: Error + Send + Sync + 'static,
81{
82 VariantBody::new(body)
83}