use std::marker::PhantomData;
pub trait IoImplementation {}
#[cfg(feature = "tokio")]
pub struct Tokio;
#[cfg(feature = "tokio")]
impl IoImplementation for Tokio {}
#[cfg(feature = "futures-io")]
pub struct Futures;
#[cfg(feature = "futures-io")]
impl IoImplementation for Futures {}
pub trait EofCondition<Result> {
fn is_eof(read_result: &Result) -> bool;
}
pub struct ZeroReadEof;
impl<E> EofCondition<Result<usize, E>> for ZeroReadEof {
fn is_eof(read_result: &Result<usize, E>) -> bool {
matches!(read_result, Ok(ref n) if *n == 0)
}
}
#[derive(Debug)]
pub struct Reader<IoImplementation, Inner, EofCondition, Buffer> {
pub inner: Inner,
pub buf: Buffer,
pub phantom_data: PhantomData<(EofCondition, IoImplementation)>,
}
impl<IoImplementation, Inner, EofCondition, Buffer>
Reader<IoImplementation, Inner, EofCondition, Buffer>
{
pub fn new(inner: Inner, buf: Buffer) -> Self {
Self {
inner,
buf,
phantom_data: PhantomData,
}
}
}
#[cfg(feature = "tokio")]
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
impl<Inner, EofCondition> crate::Reader for Reader<Tokio, Inner, EofCondition, bytes::BytesMut>
where
Inner: tokio::io::AsyncRead + Unpin,
EofCondition: self::EofCondition<Result<usize, std::io::Error>>,
{
type Data<'data> = bytes::Bytes;
type Error = std::io::Error;
async fn next(&mut self) -> Option<Result<Self::Data<'_>, Self::Error>> {
use bytes::Buf;
use tokio::io::AsyncReadExt;
let result = self.inner.read_buf(&mut self.buf).await;
if EofCondition::is_eof(&result) {
return None;
}
match result {
Err(err) => Some(Err(err)),
Ok(n) => Some(Ok(self.buf.copy_to_bytes(n))),
}
}
}
#[cfg(feature = "futures-io")]
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
impl<Inner, EofCondition> crate::Reader for Reader<Futures, Inner, EofCondition, Vec<u8>>
where
Inner: futures_io::AsyncRead + Unpin,
EofCondition: self::EofCondition<Result<usize, std::io::Error>>,
{
type Data<'data> = &'data [u8];
type Error = std::io::Error;
async fn next(&mut self) -> Option<Result<Self::Data<'_>, Self::Error>> {
use futures_util::AsyncReadExt;
let result = self.inner.read(&mut self.buf).await;
if EofCondition::is_eof(&result) {
return None;
}
match result {
Err(err) => Some(Err(err)),
Ok(n) => Some(Ok(&self.buf[..n])),
}
}
}