use std::{marker::PhantomData, os::unix::io::AsRawFd};
use crate::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory};
#[derive(Debug)]
pub struct Generic<F: AsRawFd, E = std::io::Error> {
pub file: F,
pub interest: Interest,
pub mode: Mode,
token: Option<Token>,
_error_type: PhantomData<E>,
}
impl<F: AsRawFd> Generic<F, std::io::Error> {
pub fn new(file: F, interest: Interest, mode: Mode) -> Generic<F, std::io::Error> {
Generic {
file,
interest,
mode,
token: None,
_error_type: PhantomData::default(),
}
}
pub fn new_with_error<E>(file: F, interest: Interest, mode: Mode) -> Generic<F, E> {
Generic {
file,
interest,
mode,
token: None,
_error_type: PhantomData::default(),
}
}
}
impl<F: AsRawFd, E> Generic<F, E> {
pub fn unwrap(self) -> F {
self.file
}
}
impl<F, E> EventSource for Generic<F, E>
where
F: AsRawFd,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
type Event = Readiness;
type Metadata = F;
type Ret = Result<PostAction, E>;
type Error = E;
fn process_events<C>(
&mut self,
readiness: Readiness,
token: Token,
mut callback: C,
) -> Result<PostAction, Self::Error>
where
C: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
{
if self.token != Some(token) {
return Ok(PostAction::Continue);
}
callback(readiness, &mut self.file)
}
fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> {
let token = token_factory.token();
poll.register(self.file.as_raw_fd(), self.interest, self.mode, token)?;
self.token = Some(token);
Ok(())
}
fn reregister(
&mut self,
poll: &mut Poll,
token_factory: &mut TokenFactory,
) -> crate::Result<()> {
let token = token_factory.token();
poll.reregister(self.file.as_raw_fd(), self.interest, self.mode, token)?;
self.token = Some(token);
Ok(())
}
fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> {
poll.unregister(self.file.as_raw_fd())?;
self.token = None;
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::io::{Read, Write};
use super::Generic;
use crate::{Dispatcher, Interest, Mode, PostAction};
#[cfg(unix)]
#[test]
fn dispatch_unix() {
use std::os::unix::net::UnixStream;
let mut event_loop = crate::EventLoop::try_new().unwrap();
let handle = event_loop.handle();
let (mut tx, rx) = UnixStream::pair().unwrap();
let generic = Generic::new(rx, Interest::READ, Mode::Level);
let mut dispached = false;
let _generic_token = handle
.insert_source(generic, move |readiness, file, d| {
assert!(readiness.readable);
assert!(!readiness.writable);
let mut buffer = vec![0; 10];
let ret = file.read(&mut buffer).unwrap();
assert_eq!(ret, 6);
assert_eq!(&buffer[..6], &[1, 2, 3, 4, 5, 6]);
*d = true;
Ok(PostAction::Continue)
})
.unwrap();
event_loop
.dispatch(Some(::std::time::Duration::ZERO), &mut dispached)
.unwrap();
assert!(!dispached);
let ret = tx.write(&[1, 2, 3, 4, 5, 6]).unwrap();
assert_eq!(ret, 6);
tx.flush().unwrap();
event_loop
.dispatch(Some(::std::time::Duration::ZERO), &mut dispached)
.unwrap();
assert!(dispached);
}
#[test]
fn register_deregister_unix() {
use std::os::unix::net::UnixStream;
let mut event_loop = crate::EventLoop::try_new().unwrap();
let handle = event_loop.handle();
let (mut tx, rx) = UnixStream::pair().unwrap();
let generic = Generic::new(rx, Interest::READ, Mode::Level);
let dispatcher = Dispatcher::new(generic, move |_, _, d| {
*d = true;
Ok(PostAction::Continue)
});
let mut dispached = false;
let generic_token = handle.register_dispatcher(dispatcher.clone()).unwrap();
event_loop
.dispatch(Some(::std::time::Duration::ZERO), &mut dispached)
.unwrap();
assert!(!dispached);
event_loop.handle().remove(generic_token);
let ret = tx.write(&[1, 2, 3, 4, 5, 6]).unwrap();
assert_eq!(ret, 6);
tx.flush().unwrap();
event_loop
.dispatch(Some(::std::time::Duration::ZERO), &mut dispached)
.unwrap();
assert!(!dispached);
let generic = dispatcher.into_source_inner();
let _generic_token = handle
.insert_source(generic, move |readiness, file, d| {
assert!(readiness.readable);
assert!(!readiness.writable);
let mut buffer = vec![0; 10];
let ret = file.read(&mut buffer).unwrap();
assert_eq!(ret, 6);
assert_eq!(&buffer[..6], &[1, 2, 3, 4, 5, 6]);
*d = true;
Ok(PostAction::Continue)
})
.unwrap();
event_loop
.dispatch(Some(::std::time::Duration::ZERO), &mut dispached)
.unwrap();
assert!(dispached);
}
}