use std::os::fd;
use dope_sys::io::{poll, poll::Poll as _};
use o3::alloc::{self, VecExt};
use crate::{Backend, Errno};
pub struct Set<'fd> {
entries: Vec<poll::Entry<'fd>>,
}
impl<'fd> Set<'fd> {
pub fn try_new(
first: impl Iterator<Item = fd::BorrowedFd<'fd>>,
second: impl Iterator<Item = fd::BorrowedFd<'fd>>,
) -> Result<Self, alloc::Error> {
let sources = first.chain(second);
let mut entries = Vec::try_new(sources.size_hint().0)?;
for source in sources {
alloc::Vacant::try_new(&mut entries)?.insert(poll::Entry::readable(source));
}
if poll::nfds_t::try_from(entries.len()).is_err() {
return Err(alloc::Error::Overflow);
}
Ok(Self { entries })
}
pub fn poll(&mut self, timeout: i32) -> Result<Option<Ready<'_, 'fd>>, Errno> {
if Backend::wait::<_, Errno>(self, timeout)?.count() == 0 {
return Ok(None);
}
Ok(self
.entries
.iter_mut()
.enumerate()
.find_map(|(index, entry)| entry.is_ready().then_some(Ready { index, entry })))
}
}
pub struct Ready<'set, 'fd> {
index: usize,
entry: &'set mut poll::Entry<'fd>,
}
impl Ready<'_, '_> {
pub const fn index(&self) -> usize {
self.index
}
pub fn retire(self) {
self.entry.retire();
}
}
unsafe impl<'fd> poll::raw::Entries<'fd> for Set<'fd> {
const MAX: usize = poll::MAX_ENTRIES;
fn entries(&mut self) -> &mut [poll::Entry<'fd>] {
&mut self.entries
}
}