use std::io;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
use crate::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory};
#[derive(Debug)]
pub struct Generic<F: AsRawFd> {
pub file: F,
pub interest: Interest,
pub mode: Mode,
token: Token,
}
#[derive(Debug)]
pub struct Fd(pub RawFd);
impl AsRawFd for Fd {
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
impl<F: AsRawFd> Generic<F> {
pub fn new(file: F, interest: Interest, mode: Mode) -> Generic<F> {
Generic {
file,
interest,
mode,
token: Token::invalid(),
}
}
pub fn unwrap(self) -> F {
self.file
}
}
impl Generic<Fd> {
pub fn from_fd(fd: RawFd, interest: Interest, mode: Mode) -> Generic<Fd> {
Self::new(Fd(fd), interest, mode)
}
}
impl<F: AsRawFd> EventSource for Generic<F> {
type Event = Readiness;
type Metadata = F;
type Ret = io::Result<PostAction>;
fn process_events<C>(
&mut self,
readiness: Readiness,
token: Token,
mut callback: C,
) -> std::io::Result<PostAction>
where
C: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
{
if token != self.token {
return Ok(PostAction::Continue);
}
callback(readiness, &mut self.file)
}
fn register(
&mut self,
poll: &mut Poll,
token_factory: &mut TokenFactory,
) -> std::io::Result<()> {
let token = token_factory.token();
poll.register(self.file.as_raw_fd(), self.interest, self.mode, token)?;
self.token = token;
Ok(())
}
fn reregister(
&mut self,
poll: &mut Poll,
token_factory: &mut TokenFactory,
) -> std::io::Result<()> {
let token = token_factory.token();
poll.reregister(self.file.as_raw_fd(), self.interest, self.mode, token)?;
self.token = token;
Ok(())
}
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
poll.unregister(self.file.as_raw_fd())?;
self.token = Token::invalid();
Ok(())
}
}
#[cfg(test)]
mod test {
use std::io::{self, 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)
})
.map_err(Into::<io::Error>::into)
.unwrap();
event_loop
.dispatch(Some(::std::time::Duration::from_millis(0)), &mut dispached)
.unwrap();
assert!(!dispached);
tx.write(&[1, 2, 3, 4, 5, 6]).unwrap();
tx.flush().unwrap();
event_loop
.dispatch(Some(::std::time::Duration::from_millis(0)), &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::from_millis(0)), &mut dispached)
.unwrap();
assert!(!dispached);
event_loop.handle().remove(generic_token);
tx.write(&[1, 2, 3, 4, 5, 6]).unwrap();
tx.flush().unwrap();
event_loop
.dispatch(Some(::std::time::Duration::from_millis(0)), &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)
})
.map_err(Into::<io::Error>::into)
.unwrap();
event_loop
.dispatch(Some(::std::time::Duration::from_millis(0)), &mut dispached)
.unwrap();
assert!(dispached);
}
}