use std::io::{self, Read};
#[cfg(feature = "async")]
use {
futures_util::io::{AllowStdIo, AsyncRead, AsyncReadExt},
std::{
pin::Pin,
task::{Context, Poll},
},
};
enum PayloadKind {
#[cfg(feature = "async")]
Async(Box<dyn AsyncRead + Send + Sync + Unpin>),
Sync(Box<dyn Read + Send + Sync>),
Empty,
}
pub struct IppPayload {
inner: PayloadKind,
}
impl IppPayload {
pub fn empty() -> Self {
IppPayload {
inner: PayloadKind::Empty,
}
}
#[cfg(feature = "async")]
pub fn new_async<R>(r: R) -> Self
where
R: 'static + AsyncRead + Send + Sync + Unpin,
{
IppPayload {
inner: PayloadKind::Async(Box::new(r)),
}
}
pub fn new<R>(r: R) -> Self
where
R: 'static + Read + Send + Sync,
{
IppPayload {
inner: PayloadKind::Sync(Box::new(r)),
}
}
}
impl Default for IppPayload {
fn default() -> Self {
Self {
inner: PayloadKind::Empty,
}
}
}
#[cfg(feature = "async")]
impl AsyncRead for IppPayload {
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context, buf: &mut [u8]) -> Poll<io::Result<usize>> {
match self.inner {
PayloadKind::Async(ref mut inner) => Pin::new(&mut *inner).poll_read(cx, buf),
PayloadKind::Sync(ref mut inner) => Pin::new(&mut AllowStdIo::new(inner)).poll_read(cx, buf),
PayloadKind::Empty => Poll::Ready(Ok(0)),
}
}
}
impl Read for IppPayload {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.inner {
#[cfg(feature = "async")]
PayloadKind::Async(ref mut inner) => futures_executor::block_on(inner.read(buf)),
PayloadKind::Sync(ref mut inner) => inner.read(buf),
PayloadKind::Empty => Ok(0),
}
}
}