use std::{
io,
os::fd::{AsFd, OwnedFd},
pin::Pin,
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf, unix::AsyncFd};
pub struct Stream(pub(super) AsyncFd<OwnedFd>);
impl AsyncRead for Stream {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
loop {
let mut ready = std::task::ready!(self.0.poll_read_ready(cx))?;
let read = ready.try_io(|inner| {
rustix::io::read(inner.get_ref().as_fd(), buf.initialize_unfilled())
.map_err(io::Error::from)
});
match read {
Ok(Ok(n)) => {
buf.advance(n);
return Poll::Ready(Ok(()));
}
Ok(Err(e)) => return Poll::Ready(Err(e)),
Err(_would_block) => continue,
}
}
}
}
impl AsyncWrite for Stream {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
loop {
let mut ready = std::task::ready!(self.0.poll_write_ready(cx))?;
let written = ready.try_io(|inner| {
rustix::io::write(inner.get_ref().as_fd(), buf).map_err(io::Error::from)
});
match written {
Ok(result) => return Poll::Ready(result),
Err(_would_block) => continue,
}
}
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
}