use std::cell::RefCell;
use std::io;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc;
use std::sync::Arc;
use mio::{
event::{Event as MioEvent, Source as MioSource},
Interest, Registry, Token, Waker,
};
use crate::{EventDispatcher, EventSource};
pub struct Generic<E: MioSource + 'static> {
inner: Rc<RefCell<E>>,
interest: Interest,
}
impl<E: MioSource + 'static> Generic<E> {
pub fn new(source: E) -> Generic<E> {
Self::from_rc(Rc::new(RefCell::new(source)))
}
pub fn from_rc(source: Rc<RefCell<E>>) -> Generic<E> {
Generic {
inner: source,
interest: Interest::READABLE,
}
}
pub fn set_interest(&mut self, interest: Interest) {
self.interest = interest;
}
pub fn clone_inner(&self) -> Rc<RefCell<E>> {
self.inner.clone()
}
pub fn unwrap(self) -> Rc<RefCell<E>> {
self.inner
}
}
impl<Fd: AsRawFd> Generic<SourceFd<Fd>> {
#[cfg(unix)]
pub fn from_fd_source(source: Fd) -> Generic<SourceFd<Fd>> {
Generic::new(SourceFd(source))
}
}
impl Generic<SourceRawFd> {
#[cfg(unix)]
pub fn from_raw_fd(fd: RawFd) -> Generic<SourceRawFd> {
Generic::new(SourceRawFd(fd))
}
}
#[derive(Copy, Clone, Debug)]
pub struct Readiness {
pub readable: bool,
pub writable: bool,
pub error: bool,
}
impl Readiness {
fn empty() -> Readiness {
Readiness {
readable: false,
writable: false,
error: false,
}
}
}
pub struct Event<E: MioSource + 'static> {
pub source: Rc<RefCell<E>>,
pub readiness: Readiness,
}
#[cfg(unix)]
pub struct SourceFd<F: AsRawFd>(pub F);
impl<F: AsRawFd> MioSource for SourceFd<F> {
fn register(
&mut self,
registry: &Registry,
token: Token,
interest: Interest,
) -> io::Result<()> {
mio::unix::SourceFd(&self.0.as_raw_fd()).register(registry, token, interest)
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interest: Interest,
) -> io::Result<()> {
mio::unix::SourceFd(&self.0.as_raw_fd()).reregister(registry, token, interest)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
mio::unix::SourceFd(&self.0.as_raw_fd()).deregister(registry)
}
}
#[cfg(unix)]
pub struct SourceRawFd(pub RawFd);
impl MioSource for SourceRawFd {
fn register(
&mut self,
registry: &Registry,
token: Token,
interest: Interest,
) -> io::Result<()> {
mio::unix::SourceFd(&self.0).register(registry, token, interest)
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interest: Interest,
) -> io::Result<()> {
mio::unix::SourceFd(&self.0).reregister(registry, token, interest)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
mio::unix::SourceFd(&self.0).deregister(registry)
}
}
impl<E: MioSource + 'static> MioSource for Generic<E> {
fn register(
&mut self,
registry: &Registry,
token: Token,
interest: Interest,
) -> io::Result<()> {
self.inner.borrow_mut().register(registry, token, interest)
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interest: Interest,
) -> io::Result<()> {
self.inner
.borrow_mut()
.reregister(registry, token, interest)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
self.inner.borrow_mut().deregister(registry)
}
}
impl<E: MioSource + 'static> EventSource for Generic<E> {
type Event = Event<E>;
fn interest(&self) -> Interest {
self.interest
}
fn as_mio_source(&mut self) -> Option<&mut dyn MioSource> {
Some(self)
}
fn make_dispatcher<Data: 'static, F: FnMut(Event<E>, &mut Data) + 'static>(
&mut self,
callback: F,
_: &Arc<Waker>,
) -> Rc<RefCell<dyn EventDispatcher<Data>>> {
Rc::new(RefCell::new(Dispatcher {
_data: ::std::marker::PhantomData,
inner: self.inner.clone(),
callback,
}))
}
}
struct Dispatcher<Data, E: MioSource + 'static, F: FnMut(Event<E>, &mut Data)> {
_data: ::std::marker::PhantomData<fn(&mut Data)>,
inner: Rc<RefCell<E>>,
callback: F,
}
impl<Data, E: MioSource + 'static, F: FnMut(Event<E>, &mut Data)> EventDispatcher<Data>
for Dispatcher<Data, E, F>
{
fn ready(&mut self, event: Option<&MioEvent>, data: &mut Data) {
let readiness = event
.map(|event| Readiness {
readable: event.is_readable(),
writable: event.is_writable(),
error: event.is_error(),
})
.unwrap_or_else(Readiness::empty);
(self.callback)(
Event {
source: self.inner.clone(),
readiness,
},
data,
)
}
}
#[cfg(test)]
mod test {
use std::io::{self, Read, Write};
use super::{Event, Generic};
#[cfg(unix)]
#[test]
fn dispatch_unix() {
use std::os::unix::net::UnixStream;
let mut event_loop = crate::EventLoop::new().unwrap();
let handle = event_loop.handle();
let (mut tx, rx) = UnixStream::pair().unwrap();
let mut generic = Generic::from_fd_source(rx);
generic.set_interest(mio::Interest::READABLE);
let mut dispached = false;
let _source = handle
.insert_source(generic, move |Event { source, readiness }, d| {
assert!(readiness.readable);
assert!(!readiness.writable);
let mut buffer = vec![0; 10];
let ret = source.borrow_mut().0.read(&mut buffer).unwrap();
assert_eq!(ret, 6);
assert_eq!(&buffer[..6], &[1, 2, 3, 4, 5, 6]);
*d = true;
})
.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::new().unwrap();
let handle = event_loop.handle();
let (mut tx, rx) = UnixStream::pair().unwrap();
let mut generic = Generic::from_fd_source(rx);
generic.set_interest(mio::Interest::READABLE);
let mut dispached = false;
let source = handle
.insert_source(generic, move |Event { .. }, d| {
*d = true;
})
.map_err(Into::<io::Error>::into)
.unwrap();
event_loop
.dispatch(Some(::std::time::Duration::from_millis(0)), &mut dispached)
.unwrap();
assert!(!dispached);
let generic = source.remove();
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 _source = handle
.insert_source(generic, move |Event { source, readiness }, d| {
assert!(readiness.readable);
assert!(!readiness.writable);
let mut buffer = vec![0; 10];
let ret = source.borrow_mut().0.read(&mut buffer).unwrap();
assert_eq!(ret, 6);
assert_eq!(&buffer[..6], &[1, 2, 3, 4, 5, 6]);
*d = true;
})
.map_err(Into::<io::Error>::into)
.unwrap();
event_loop
.dispatch(Some(::std::time::Duration::from_millis(0)), &mut dispached)
.unwrap();
assert!(dispached);
}
}