use crate::io::Fd;
use crate::system::FdSet as FdSetTrait;
use std::mem::MaybeUninit;
use std::os::fd::RawFd;
#[derive(Clone)]
pub struct FdSet {
fds: MaybeUninit<libc::fd_set>,
upper_bound: Fd,
}
impl Default for FdSet {
fn default() -> Self {
let mut fds = MaybeUninit::<libc::fd_set>::uninit();
unsafe { libc::FD_ZERO(fds.as_mut_ptr()) };
Self {
fds,
upper_bound: Fd(0),
}
}
}
impl FdSetTrait for FdSet {
const MAX_FD: Fd = Fd(libc::FD_SETSIZE as RawFd - 1);
fn insert(&mut self, fd: Fd) {
if 0 <= fd.0 && fd <= Self::MAX_FD {
unsafe { libc::FD_SET(fd.0, self.fds.as_mut_ptr()) };
self.upper_bound = self.upper_bound.max(Fd(fd.0 + 1));
}
}
fn remove(&mut self, fd: Fd) {
if 0 <= fd.0 && fd <= Self::MAX_FD {
unsafe { libc::FD_CLR(fd.0, self.fds.as_mut_ptr()) };
}
}
fn contains(&self, fd: Fd) -> bool {
0 <= fd.0 && fd <= Self::MAX_FD && unsafe { libc::FD_ISSET(fd.0, self.fds.as_ptr()) }
}
}
impl std::fmt::Debug for FdSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let fds = (0..=Self::MAX_FD.0).filter(|&fd| self.contains(Fd(fd)));
f.debug_set().entries(fds).finish()
}
}
impl FdSet {
#[inline(always)]
#[must_use]
pub(super) fn as_mut_ptr(&mut self) -> *mut libc::fd_set {
self.fds.as_mut_ptr()
}
#[inline(always)]
#[must_use]
pub(super) fn upper_bound(&self) -> Fd {
self.upper_bound
}
}