use crate::{FromInner, HandleTrait, Inner, IntoInner};
use std::convert::TryFrom;
use uv::{uv_poll_init, uv_poll_init_socket, uv_poll_start, uv_poll_stop, uv_poll_t};
bitflags! {
pub struct PollEvents: u32 {
const DISCONNECT = uv::uv_poll_event_UV_DISCONNECT as _;
const PRIORITIZED = uv::uv_poll_event_UV_PRIORITIZED as _;
const READABLE = uv::uv_poll_event_UV_READABLE as _;
const WRITABLE = uv::uv_poll_event_UV_WRITABLE as _;
}
}
callbacks! {
pub PollCB(handle: PollHandle, status: crate::Result<u32>, events: PollEvents);
}
#[derive(Default)]
pub(crate) struct PollDataFields<'a> {
poll_cb: PollCB<'a>,
}
extern "C" fn uv_poll_cb(
handle: *mut uv_poll_t,
status: std::os::raw::c_int,
events: std::os::raw::c_int,
) {
let dataptr = crate::Handle::get_data(uv_handle!(handle));
if !dataptr.is_null() {
unsafe {
if let super::PollData(d) = &mut (*dataptr).addl {
let status = if status < 0 {
Err(crate::Error::from_inner(status as uv::uv_errno_t))
} else {
Ok(status as _)
};
d.poll_cb.call(
handle.into_inner(),
status,
PollEvents::from_bits_truncate(events as _),
)
}
}
}
}
#[derive(Clone, Copy)]
pub struct PollHandle {
handle: *mut uv_poll_t,
}
impl PollHandle {
pub fn new(r#loop: &crate::Loop, fd: crate::File) -> crate::Result<PollHandle> {
let layout = std::alloc::Layout::new::<uv_poll_t>();
let handle = unsafe { std::alloc::alloc(layout) as *mut uv_poll_t };
if handle.is_null() {
return Err(crate::Error::ENOMEM);
}
let ret = unsafe { uv_poll_init(r#loop.into_inner(), handle, fd) };
if ret < 0 {
unsafe { std::alloc::dealloc(handle as _, layout) };
return Err(crate::Error::from_inner(ret as uv::uv_errno_t));
}
crate::Handle::initialize_data(uv_handle!(handle), super::PollData(Default::default()));
Ok(PollHandle { handle })
}
pub fn new_socket(r#loop: &crate::Loop, socket: crate::Socket) -> crate::Result<PollHandle> {
let layout = std::alloc::Layout::new::<uv_poll_t>();
let handle = unsafe { std::alloc::alloc(layout) as *mut uv_poll_t };
if handle.is_null() {
return Err(crate::Error::ENOMEM);
}
let ret = unsafe { uv_poll_init_socket(r#loop.into_inner(), handle, socket as _) };
if ret < 0 {
unsafe { std::alloc::dealloc(handle as _, layout) };
return Err(crate::Error::from_inner(ret as uv::uv_errno_t));
}
crate::Handle::initialize_data(uv_handle!(handle), super::PollData(Default::default()));
Ok(PollHandle { handle })
}
pub fn start<CB: Into<PollCB<'static>>>(
&mut self,
events: PollEvents,
cb: CB,
) -> crate::Result<()> {
let cb = cb.into();
let uv_cb = use_c_callback!(uv_poll_cb, cb);
let dataptr = crate::Handle::get_data(uv_handle!(self.handle));
if !dataptr.is_null() {
if let super::PollData(d) = unsafe { &mut (*dataptr).addl } {
d.poll_cb = cb;
}
}
crate::uvret(unsafe { uv_poll_start(self.handle, events.bits() as _, uv_cb) })
}
pub fn stop(&mut self) -> crate::Result<()> {
crate::uvret(unsafe { uv_poll_stop(self.handle) })
}
}
impl FromInner<*mut uv_poll_t> for PollHandle {
fn from_inner(handle: *mut uv_poll_t) -> PollHandle {
PollHandle { handle }
}
}
impl Inner<*mut uv::uv_handle_t> for PollHandle {
fn inner(&self) -> *mut uv::uv_handle_t {
uv_handle!(self.handle)
}
}
impl From<PollHandle> for crate::Handle {
fn from(poll: PollHandle) -> crate::Handle {
crate::Handle::from_inner(Inner::<*mut uv::uv_handle_t>::inner(&poll))
}
}
impl crate::ToHandle for PollHandle {
fn to_handle(&self) -> crate::Handle {
crate::Handle::from_inner(Inner::<*mut uv::uv_handle_t>::inner(self))
}
}
impl TryFrom<crate::Handle> for PollHandle {
type Error = crate::ConversionError;
fn try_from(handle: crate::Handle) -> Result<Self, Self::Error> {
let t = handle.get_type();
if t != crate::HandleType::POLL {
Err(crate::ConversionError::new(t, crate::HandleType::POLL))
} else {
Ok((handle.inner() as *mut uv_poll_t).into_inner())
}
}
}
impl HandleTrait for PollHandle {}
impl crate::Loop {
pub fn poll(&self, fd: crate::File) -> crate::Result<PollHandle> {
PollHandle::new(self, fd)
}
pub fn poll_socket(&self, socket: crate::Socket) -> crate::Result<PollHandle> {
PollHandle::new_socket(self, socket)
}
}