use std::{
cell::RefCell,
fmt::Debug,
io,
ops::Deref,
pin::Pin,
task::{Context, Poll},
};
use compio_buf::{BufResult, IntoInner};
use compio_driver::{
AsFd, AsRawFd, BorrowedFd, RawFd, SharedFd, ToSharedFd,
op::{Interest, PollOnce},
};
use crate::Submit;
pub struct PollFd<T: AsFd> {
inner: SharedFd<T>,
read_submit: RefCell<Option<Submit<PollOnce<SharedFd<T>>>>>,
write_submit: RefCell<Option<Submit<PollOnce<SharedFd<T>>>>>,
}
impl<T: AsFd + Debug> Debug for PollFd<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PollFd")
.field("inner", &self.inner)
.finish()
}
}
impl<T: AsFd> PollFd<T> {
pub fn new(inner: SharedFd<T>) -> io::Result<Self> {
Ok(Self {
inner,
read_submit: RefCell::new(None),
write_submit: RefCell::new(None),
})
}
}
impl<T: AsFd + 'static> PollFd<T> {
pub fn poll_read_ready(&self, cx: &mut Context) -> Poll<io::Result<()>> {
let mut read_submit = self.read_submit.borrow_mut();
loop {
match read_submit.as_mut() {
None => {
let op = PollOnce::new(self.to_shared_fd(), Interest::Readable);
*read_submit = Some(crate::submit(op));
}
Some(f) => match Pin::new(f).poll(cx) {
Poll::Ready(BufResult(res, _)) => {
*read_submit = None;
break Poll::Ready(res.map(|_| ()));
}
Poll::Pending => break Poll::Pending,
},
}
}
}
pub fn poll_accept_ready(&self, cx: &mut Context) -> Poll<io::Result<()>> {
self.poll_read_ready(cx)
}
pub fn poll_write_ready(&self, cx: &mut Context) -> Poll<io::Result<()>> {
let mut write_submit = self.write_submit.borrow_mut();
loop {
match write_submit.as_mut() {
None => {
let op = PollOnce::new(self.to_shared_fd(), Interest::Writable);
*write_submit = Some(crate::submit(op));
}
Some(f) => match Pin::new(f).poll(cx) {
Poll::Ready(BufResult(res, _)) => {
*write_submit = None;
break Poll::Ready(res.map(|_| ()));
}
Poll::Pending => break Poll::Pending,
},
}
}
}
pub fn poll_connect_ready(&self, cx: &mut Context) -> Poll<io::Result<()>> {
self.poll_write_ready(cx)
}
}
impl<T: AsFd> IntoInner for PollFd<T> {
type Inner = SharedFd<T>;
fn into_inner(self) -> Self::Inner {
self.inner
}
}
impl<T: AsFd> ToSharedFd<T> for PollFd<T> {
fn to_shared_fd(&self) -> SharedFd<T> {
self.inner.clone()
}
}
impl<T: AsFd> AsFd for PollFd<T> {
fn as_fd(&self) -> BorrowedFd<'_> {
self.inner.as_fd()
}
}
impl<T: AsFd> AsRawFd for PollFd<T> {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_fd().as_raw_fd()
}
}
impl<T: AsFd> Deref for PollFd<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}