use super::{Bufferable, Status};
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, ReadBuf};
pub trait TokioReadLayered: AsyncRead + Bufferable {
fn poll_read_with_status(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<((), Status)>>;
#[inline]
fn minimum_buffer_size(&self) -> usize {
0
}
}
#[inline]
pub fn tokio_default_poll_read<Inner: TokioReadLayered + ?Sized>(
inner: Pin<&mut Inner>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<()>> {
let start_len = buf.filled().len();
inner
.poll_read_with_status(cx, buf)
.map(|result| result.and_then(|((), status)| to_tokio_read_result(start_len, status, buf)))
}
impl<R: TokioReadLayered + Unpin> TokioReadLayered for Box<R> {
#[inline]
fn poll_read_with_status(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<((), Status)>> {
Pin::new(&mut **self).poll_read_with_status(cx, buf)
}
#[inline]
fn minimum_buffer_size(&self) -> usize {
Pin::new(&**self).minimum_buffer_size()
}
}
impl<R: TokioReadLayered + Unpin> TokioReadLayered for &mut R {
#[inline]
fn poll_read_with_status(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<((), Status)>> {
TokioReadLayered::poll_read_with_status(Pin::new(*self), cx, buf)
}
#[inline]
fn minimum_buffer_size(&self) -> usize {
(**self).minimum_buffer_size()
}
}
fn to_tokio_read_result(start_len: usize, status: Status, buf: &ReadBuf) -> io::Result<()> {
let size = buf.filled().len() - start_len;
match (size, status) {
(0, Status::Open(_)) => Err(io::Error::new(
io::ErrorKind::Interrupted,
"read zero bytes from stream",
)),
(_, _) => Ok(()),
}
}