use std::{
pin::Pin,
task::{Context, Poll},
};
use pin_project_lite::pin_project;
use super::{Frame, SizeHint, StreamingBody};
pin_project! {
#[derive(Debug, Clone)]
pub struct OptionalBody<B> {
#[pin]
inner: Option<B>,
}
}
impl<B> Default for OptionalBody<B> {
#[inline(always)]
fn default() -> Self {
Self::none()
}
}
impl<B> From<B> for OptionalBody<B> {
#[inline(always)]
fn from(value: B) -> Self {
Self::some(value)
}
}
impl<B> OptionalBody<B> {
#[inline(always)]
pub const fn some(inner: B) -> Self {
Self { inner: Some(inner) }
}
#[inline(always)]
pub const fn none() -> Self {
Self { inner: None }
}
#[inline(always)]
pub const fn as_ref(&self) -> Option<&B> {
self.inner.as_ref()
}
#[inline(always)]
pub const fn as_mut(&mut self) -> Option<&mut B> {
self.inner.as_mut()
}
}
impl<B> StreamingBody for OptionalBody<B>
where
B: StreamingBody,
{
type Data = B::Data;
type Error = B::Error;
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
match self.project().inner.as_pin_mut() {
Some(b) => b.poll_frame(cx),
None => Poll::Ready(None),
}
}
fn is_end_stream(&self) -> bool {
match &self.inner {
Some(b) => b.is_end_stream(),
None => true,
}
}
fn size_hint(&self) -> SizeHint {
match &self.inner {
Some(body) => body.size_hint(),
None => SizeHint::with_exact(0),
}
}
}