use hyper::body::{Body, Buf, Frame};
use std::error::Error;
use std::pin::Pin;
use std::task::{Context, Poll};
trait ErasedBody: Send + Sync {
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Box<dyn Buf + Send>>, Box<dyn Error + Send + Sync>>>>;
}
impl<B> ErasedBody for B
where
B: Body + Send + Sync + 'static,
B::Data: Buf + Send + 'static,
B::Error: Error + Send + Sync + 'static,
{
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Box<dyn Buf + Send>>, Box<dyn Error + Send + Sync>>>> {
match <Self as Body>::poll_frame(self, cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(None) => Poll::Ready(None),
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(Box::new(e)))),
Poll::Ready(Some(Ok(frame))) => {
let mapped = frame.map_data(|d| Box::new(d) as Box<dyn Buf + Send>);
Poll::Ready(Some(Ok(mapped)))
}
}
}
}
pub struct VariantBody {
inner: Pin<Box<dyn ErasedBody + 'static>>,
}
impl VariantBody {
pub fn new<B>(body: B) -> Self
where
B: Body + Send + Sync + 'static,
B::Data: Buf + Send + 'static,
B::Error: Error + Send + Sync + 'static,
{
Self {
inner: Box::pin(body),
}
}
}
impl Body for VariantBody {
type Data = Box<dyn Buf + Send>;
type Error = Box<dyn Error + Send + Sync>;
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
self.get_mut().inner.as_mut().poll_frame(cx)
}
}
pub type Empty = http_body_util::Empty<hyper::body::Bytes>;
pub type Full = http_body_util::Full<hyper::body::Bytes>;
pub fn empty() -> VariantBody {
VariantBody::new(Empty::new())
}
pub fn variant_body<B>(body: B) -> VariantBody
where
B: Body + Send + Sync + 'static,
B::Data: Buf + Send + 'static,
B::Error: Error + Send + Sync + 'static,
{
VariantBody::new(body)
}