use std::io;
use std::task::{Context, Poll};
use crate::platform::DeviceImpl;
use ::tokio::io::unix::AsyncFd as TokioAsyncFd;
use ::tokio::io::Interest;
pub struct AsyncDevice(pub(crate) TokioAsyncFd<DeviceImpl>);
impl AsyncDevice {
pub fn poll_readable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
self.0.poll_read_ready(cx).map_ok(|_| ())
}
pub fn poll_recv(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> {
loop {
return match self.0.poll_read_ready(cx) {
Poll::Ready(Ok(mut rs)) => {
let n = match rs.try_io(|dev| dev.get_ref().recv(buf)) {
Ok(rs) => rs?,
Err(_) => continue,
};
Poll::Ready(Ok(n))
}
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
Poll::Pending => Poll::Pending,
};
}
}
pub fn poll_writable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
self.0.poll_write_ready(cx).map_ok(|_| ())
}
pub fn poll_send(&self, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
loop {
return match self.0.poll_write_ready(cx) {
Poll::Ready(Ok(mut rs)) => {
let n = match rs.try_io(|dev| dev.get_ref().send(buf)) {
Ok(rs) => rs?,
Err(_) => continue,
};
Poll::Ready(Ok(n))
}
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
Poll::Pending => Poll::Pending,
};
}
}
}
impl AsyncDevice {
pub(crate) fn new_dev(device: DeviceImpl) -> io::Result<Self> {
device.set_nonblocking(true)?;
Ok(Self(TokioAsyncFd::new(device)?))
}
pub(crate) fn into_device(self) -> io::Result<DeviceImpl> {
Ok(self.0.into_inner())
}
pub(crate) async fn read_with<R>(
&self,
mut op: impl FnMut(&DeviceImpl) -> io::Result<R>,
) -> io::Result<R> {
self.0
.async_io(Interest::READABLE, |device| op(device))
.await
}
pub(crate) async fn write_with<R>(
&self,
mut op: impl FnMut(&DeviceImpl) -> io::Result<R>,
) -> io::Result<R> {
self.0
.async_io(Interest::WRITABLE, |device| op(device))
.await
}
pub(crate) fn try_read_io<R>(
&self,
f: impl FnOnce(&DeviceImpl) -> io::Result<R>,
) -> io::Result<R> {
self.0.try_io(Interest::READABLE, |device| f(device))
}
pub(crate) fn try_write_io<R>(
&self,
f: impl FnOnce(&DeviceImpl) -> io::Result<R>,
) -> io::Result<R> {
self.0.try_io(Interest::WRITABLE, |device| f(device))
}
pub(crate) fn get_ref(&self) -> &DeviceImpl {
self.0.get_ref()
}
}