use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use std::io;
pub trait AsyncRead {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>>;
}
pub trait AsyncWrite {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>>;
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
}
pub trait AsyncTransport: AsyncRead + AsyncWrite + Send + Unpin {}
impl<T> AsyncTransport for T where T: AsyncRead + AsyncWrite + Send + Unpin + ?Sized {}
pub struct Read<'a, T: ?Sized> {
transport: &'a mut T,
buf: &'a mut [u8],
}
pub struct WriteAll<'a, T: ?Sized> {
transport: &'a mut T,
buf: &'a [u8],
written: usize,
}
pub fn read<'a, T>(transport: &'a mut T, buf: &'a mut [u8]) -> Read<'a, T>
where
T: AsyncRead + Unpin + ?Sized,
{
Read { transport, buf }
}
pub fn write_all<'a, T>(transport: &'a mut T, buf: &'a [u8]) -> WriteAll<'a, T>
where
T: AsyncWrite + Unpin + ?Sized,
{
WriteAll {
transport,
buf,
written: 0,
}
}
impl<T> Future for Read<'_, T>
where
T: AsyncRead + Unpin + ?Sized,
{
type Output = io::Result<usize>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.get_mut();
Pin::new(&mut *me.transport).poll_read(cx, me.buf)
}
}
impl<T> Future for WriteAll<'_, T>
where
T: AsyncWrite + Unpin + ?Sized,
{
type Output = io::Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.get_mut();
while me.written < me.buf.len() {
let rem = &me.buf[me.written..];
match Pin::new(&mut *me.transport).poll_write(cx, rem) {
Poll::Ready(Ok(0)) => {
return Poll::Ready(Err(io::Error::new(
io::ErrorKind::WriteZero,
"transport accepted zero bytes",
)));
}
Poll::Ready(Ok(n)) => me.written += n,
Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
Poll::Pending => return Poll::Pending,
}
}
Poll::Ready(Ok(()))
}
}