use std::cell::RefCell;
use std::io;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc;
use mio::{Evented, Poll, PollOpt, Ready, Token};
use {EventDispatcher, EventSource};
pub struct Generic<E: Evented + 'static> {
inner: Rc<RefCell<E>>,
interest: Ready,
pollopts: PollOpt,
}
impl<E: Evented + 'static> Generic<E> {
pub fn new(source: E) -> Generic<E> {
Generic {
inner: Rc::new(RefCell::new(source)),
interest: Ready::empty(),
pollopts: PollOpt::empty(),
}
}
pub fn from_rc(source: Rc<RefCell<E>>) -> Generic<E> {
Generic {
inner: source,
interest: Ready::empty(),
pollopts: PollOpt::empty(),
}
}
pub fn set_interest(&mut self, interest: Ready) {
self.interest = interest;
}
pub fn set_pollopts(&mut self, pollopts: PollOpt) {
self.pollopts = pollopts;
}
pub fn clone_inner(&self) -> Rc<RefCell<E>> {
self.inner.clone()
}
pub fn unwrap(self) -> Rc<RefCell<E>> {
self.inner
}
}
impl<Fd: AsRawFd> Generic<EventedFd<Fd>> {
#[cfg(unix)]
pub fn from_fd_source(source: Fd) -> Generic<EventedFd<Fd>> {
Generic::new(EventedFd(source))
}
}
impl Generic<EventedRawFd> {
#[cfg(unix)]
pub fn from_raw_fd(fd: RawFd) -> Generic<EventedRawFd> {
Generic::new(EventedRawFd(fd))
}
}
pub struct Event<E: Evented + 'static> {
pub source: Rc<RefCell<E>>,
pub readiness: Ready,
}
#[cfg(unix)]
pub struct EventedFd<F: AsRawFd>(pub F);
impl<F: AsRawFd> Evented for EventedFd<F> {
fn register(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> io::Result<()> {
::mio::unix::EventedFd(&self.0.as_raw_fd()).register(poll, token, interest, opts)
}
fn reregister(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> io::Result<()> {
::mio::unix::EventedFd(&self.0.as_raw_fd()).reregister(poll, token, interest, opts)
}
fn deregister(&self, poll: &Poll) -> io::Result<()> {
::mio::unix::EventedFd(&self.0.as_raw_fd()).deregister(poll)
}
}
#[cfg(unix)]
pub struct EventedRawFd(pub RawFd);
impl Evented for EventedRawFd {
fn register(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> io::Result<()> {
::mio::unix::EventedFd(&self.0).register(poll, token, interest, opts)
}
fn reregister(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> io::Result<()> {
::mio::unix::EventedFd(&self.0).reregister(poll, token, interest, opts)
}
fn deregister(&self, poll: &Poll) -> io::Result<()> {
::mio::unix::EventedFd(&self.0).deregister(poll)
}
}
impl<E: Evented + 'static> Evented for Generic<E> {
fn register(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> io::Result<()> {
self.inner.borrow().register(poll, token, interest, opts)
}
fn reregister(
&self,
poll: &Poll,
token: Token,
interest: Ready,
opts: PollOpt,
) -> io::Result<()> {
self.inner.borrow().reregister(poll, token, interest, opts)
}
fn deregister(&self, poll: &Poll) -> io::Result<()> {
self.inner.borrow().deregister(poll)
}
}
impl<E: Evented + 'static> EventSource for Generic<E> {
type Event = Event<E>;
fn interest(&self) -> Ready {
self.interest
}
fn pollopts(&self) -> PollOpt {
self.pollopts
}
fn make_dispatcher<Data: 'static, F: FnMut(Event<E>, &mut Data) + 'static>(
&self,
callback: F,
) -> Rc<RefCell<EventDispatcher<Data>>> {
Rc::new(RefCell::new(Dispatcher {
_data: ::std::marker::PhantomData,
inner: self.inner.clone(),
callback,
}))
}
}
struct Dispatcher<Data, E: Evented + 'static, F: FnMut(Event<E>, &mut Data)> {
_data: ::std::marker::PhantomData<fn(&mut Data)>,
inner: Rc<RefCell<E>>,
callback: F,
}
impl<Data, E: Evented + 'static, F: FnMut(Event<E>, &mut Data)> EventDispatcher<Data>
for Dispatcher<Data, E, F>
{
fn ready(&mut self, ready: Ready, data: &mut Data) {
(self.callback)(
Event {
source: self.inner.clone(),
readiness: ready,
},
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 = ::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::Ready::readable());
let mut dispached = false;
handle
.insert_source(generic, move |Event { source, readiness }, d| {
assert!(readiness.is_readable());
assert!(!readiness.is_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);
}
}