pub mod codec;
use std::pin::Pin;
use std::task::Poll;
use http_body_util::{BodyExt, combinators::BoxBody as InnerBoxBody};
type BoxBody = InnerBoxBody<::bytes::Bytes, crate::BoxError>;
#[derive(Debug)]
pub struct Body {
kind: Kind,
}
#[derive(Debug)]
enum Kind {
Empty,
Wrap(BoxBody),
}
impl Body {
fn from_kind(kind: Kind) -> Self {
Self { kind }
}
pub const fn empty() -> Self {
Self { kind: Kind::Empty }
}
pub fn new<B>(mut body: B) -> Self
where
B: http_body::Body<Data = bytes::Bytes> + Send + Sync + 'static,
B::Error: Into<crate::BoxError>,
{
if body.is_end_stream() {
return Self::empty();
}
if let Some(body) = <dyn std::any::Any>::downcast_mut::<Body>(&mut body) {
return std::mem::take(body);
}
if let Some(body) = <dyn std::any::Any>::downcast_mut::<BoxBody>(&mut body) {
return Self::from_kind(Kind::Wrap(std::mem::take(body)));
}
let body = body.map_err(Into::into).boxed();
Self::from_kind(Kind::Wrap(body))
}
}
impl Default for Body {
fn default() -> Self {
Self::empty()
}
}
impl http_body::Body for Body {
type Data = bytes::Bytes;
type Error = crate::BoxError;
fn poll_frame(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
match &mut self.kind {
Kind::Empty => Poll::Ready(None),
Kind::Wrap(body) => Pin::new(body).poll_frame(cx),
}
}
fn size_hint(&self) -> http_body::SizeHint {
match &self.kind {
Kind::Empty => http_body::SizeHint::with_exact(0),
Kind::Wrap(body) => body.size_hint(),
}
}
fn is_end_stream(&self) -> bool {
match &self.kind {
Kind::Empty => true,
Kind::Wrap(body) => body.is_end_stream(),
}
}
}