use std::ptr;
use std::time::Duration;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::FromRawDescriptor;
use crate::errno::errno_result;
use crate::errno::Error;
use crate::errno::Result;
use crate::sys::unix::RawDescriptor;
use crate::unix::duration_to_timespec;
use crate::unix::set_descriptor_cloexec;
use crate::SafeDescriptor;
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub(in crate::sys::macos) struct Kqueue {
queue: SafeDescriptor,
}
pub(in crate::sys::macos) fn make_kevent(filter: i16, flags: u16, fflags: u32) -> libc::kevent64_s {
libc::kevent64_s {
ident: 0,
filter,
flags,
fflags,
data: 0,
udata: 0,
ext: [0, 0],
}
}
impl Kqueue {
pub(in crate::sys::macos) fn new() -> Result<Kqueue> {
let raw_queue = unsafe { libc::kqueue() };
if raw_queue < 0 {
return crate::errno::errno_result();
}
let queue = unsafe { SafeDescriptor::from_raw_descriptor(raw_queue) };
set_descriptor_cloexec(&queue)?;
Ok(Kqueue { queue })
}
pub(in crate::sys::macos) fn kevent<'a>(
&self,
changelist: &[libc::kevent64_s],
eventlist: &'a mut [libc::kevent64_s],
timeout: Option<Duration>,
) -> Result<&'a mut [libc::kevent64_s]> {
let timespec = timeout.map(duration_to_timespec);
let res = unsafe {
libc::kevent64(
self.queue.as_raw_descriptor(),
changelist.as_ptr(),
changelist.len() as i32,
eventlist.as_mut_ptr(),
eventlist.len() as i32,
0,
if let Some(timeout) = timespec {
&timeout
} else {
ptr::null()
},
)
};
if res < 0 {
return errno_result();
}
let returned_events = eventlist.split_at_mut(res as usize).0;
for event in returned_events.iter() {
if event.flags & libc::EV_ERROR != 0 {
return Err(Error::new(event.data));
}
}
Ok(returned_events)
}
pub(in crate::sys::macos) fn try_clone(&self) -> Result<Kqueue> {
self.queue.try_clone().map(|queue| Kqueue { queue })
}
}
impl crate::AsRawDescriptor for Kqueue {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.queue.as_raw_descriptor()
}
}
impl crate::FromRawDescriptor for Kqueue {
unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
Kqueue {
queue: SafeDescriptor::from_raw_descriptor(descriptor),
}
}
}
impl crate::IntoRawDescriptor for Kqueue {
fn into_raw_descriptor(self) -> RawDescriptor {
self.queue.into_raw_descriptor()
}
}
impl From<Kqueue> for crate::SafeDescriptor {
fn from(queue: Kqueue) -> Self {
queue.queue
}
}
impl From<SafeDescriptor> for Kqueue {
fn from(queue: SafeDescriptor) -> Self {
Kqueue { queue }
}
}