event.rs

  1use std::marker::PhantomData;
  2use std::any::{TypeId, Any};
  3use std::fmt::Debug;
  4use std::collections::BTreeMap;
  5use std::cmp::Ordering;
  6use std::mem;
  7use std::sync::Mutex;
  8
  9use minidom::Element;
 10
 11/// A marker trait which marks all events.
 12pub trait Event: Any + Debug {}
 13
 14/// A trait which is implemented for all event handlers.
 15trait EventHandler: Any {
 16    /// Handle an event, returns whether to propagate the event to the remaining handlers.
 17    fn handle(&self, event: &AbstractEvent) -> Propagation;
 18}
 19
 20/// An abstract event.
 21pub struct AbstractEvent {
 22    inner: Box<Any>,
 23}
 24
 25impl AbstractEvent {
 26    /// Creates an abstract event from a concrete event.
 27    pub fn new<E: Event>(event: E) -> AbstractEvent {
 28        AbstractEvent {
 29            inner: Box::new(event),
 30        }
 31    }
 32
 33    /// Downcasts this abstract event into a concrete event.
 34    pub fn downcast<E: Event + 'static>(&self) -> Option<&E> {
 35        self.inner.downcast_ref::<E>()
 36    }
 37
 38    /// Checks whether this abstract event is a specific concrete event.
 39    pub fn is<E: Event + 'static>(&self) -> bool {
 40        self.inner.is::<E>()
 41    }
 42}
 43
 44struct Record<P, T>(P, T);
 45
 46impl<P: PartialEq, T> PartialEq for Record<P, T> {
 47    fn eq(&self, other: &Record<P, T>) -> bool {
 48        self.0 == other.0
 49    }
 50}
 51
 52impl<P: Eq, T> Eq for Record<P, T> {}
 53
 54impl<P: PartialOrd, T> PartialOrd for Record<P, T> {
 55    fn partial_cmp(&self, other: &Record<P, T>) -> Option<Ordering> {
 56        self.0.partial_cmp(&other.0)
 57    }
 58}
 59
 60impl<P: Ord, T> Ord for Record<P, T> {
 61    fn cmp(&self, other: &Record<P, T>) -> Ordering {
 62        self.0.cmp(&other.0)
 63    }
 64}
 65
 66/// An enum representing whether to keep propagating an event or to stop the propagation.
 67pub enum Propagation {
 68    /// Stop the propagation of the event, the remaining handlers will not get invoked.
 69    Stop,
 70    /// Continue propagating the event.
 71    Continue,
 72}
 73
 74/// An event dispatcher, this takes care of dispatching events to their respective handlers.
 75pub struct Dispatcher {
 76    handlers: Mutex<BTreeMap<TypeId, Vec<Record<Priority, Box<EventHandler>>>>>,
 77    queue: Mutex<Vec<(TypeId, AbstractEvent)>>,
 78}
 79
 80impl Dispatcher {
 81    /// Create a new `Dispatcher`.
 82    pub fn new() -> Dispatcher {
 83        Dispatcher {
 84            handlers: Mutex::new(BTreeMap::new()),
 85            queue: Mutex::new(Vec::new()),
 86        }
 87    }
 88
 89    /// Register an event handler.
 90    pub fn register<E, F>(&self, priority: Priority, func: F)
 91        where
 92            E: Event,
 93            F: Fn(&E) -> Propagation + 'static {
 94        struct Handler<E, F> where E: Event, F: Fn(&E) -> Propagation {
 95            func: F,
 96            _marker: PhantomData<E>,
 97        }
 98
 99        impl<E: Event, F: Fn(&E) -> Propagation + 'static> EventHandler for Handler<E, F> {
100            fn handle(&self, evt: &AbstractEvent) -> Propagation {
101                if let Some(e) = evt.downcast::<E>() {
102                    (self.func)(e)
103                }
104                else {
105                    Propagation::Continue
106                }
107            }
108        }
109
110        let handler: Box<EventHandler> = Box::new(Handler {
111            func: func,
112            _marker: PhantomData,
113        }) as Box<EventHandler>;
114        let mut guard = self.handlers.lock().unwrap();
115        let ent = guard.entry(TypeId::of::<E>())
116                       .or_insert_with(|| Vec::new());
117        ent.push(Record(priority, handler));
118        ent.sort();
119    }
120
121    /// Append an event to the queue.
122    pub fn dispatch<E>(&self, event: E) where E: Event {
123        self.queue.lock().unwrap().push((TypeId::of::<E>(), AbstractEvent::new(event)));
124    }
125
126    /// Flush all events in the queue so they can be handled by their respective handlers.
127    /// Returns whether there are still pending events.
128    pub fn flush(&self) -> bool {
129        let mut q = Vec::new();
130        {
131            let mut my_q = self.queue.lock().unwrap();
132            mem::swap(my_q.as_mut(), &mut q);
133        }
134        'evts: for (t, evt) in q {
135            if let Some(handlers) = self.handlers.lock().unwrap().get_mut(&t) {
136                for &mut Record(_, ref mut handler) in handlers {
137                    match handler.handle(&evt) {
138                        Propagation::Stop => { continue 'evts; },
139                        Propagation::Continue => (),
140                    }
141                }
142            }
143        }
144        !self.queue.lock().unwrap().is_empty()
145    }
146
147    /// Flushes all events, like `flush`, but keeps doing this until there is nothing left in the
148    /// queue.
149    pub fn flush_all(&self) {
150        while self.flush() {}
151    }
152}
153
154#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
155pub enum Priority {
156    Max,
157    Default,
158    Min,
159}
160
161impl Default for Priority {
162    fn default() -> Priority {
163        Priority::Default
164    }
165}
166
167#[derive(Debug)]
168pub struct SendElement(pub Element);
169
170impl Event for SendElement {}
171
172#[derive(Debug)]
173pub struct ReceiveElement(pub Element);
174
175impl Event for ReceiveElement {}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180
181    #[test]
182    #[should_panic(expected = "success")]
183    fn test() {
184        let disp = Dispatcher::new();
185
186        #[derive(Debug)]
187        struct MyEvent {
188            should_be_42: u32,
189        }
190
191        impl Event for MyEvent {}
192
193        disp.register(Priority::Max, |evt: &MyEvent| {
194            if evt.should_be_42 == 42 {
195                Propagation::Continue
196            }
197            else {
198                Propagation::Stop
199            }
200        });
201
202        disp.register(Priority::Min, |_: &MyEvent| {
203            panic!("should not be called");
204        });
205
206        disp.register(Priority::Default, |evt: &MyEvent| {
207            if evt.should_be_42 == 42 {
208                panic!("success");
209            }
210            else {
211                panic!("not 42");
212            }
213        });
214
215        disp.register(Priority::Min, |_: &MyEvent| {
216            panic!("should not be called");
217        });
218
219        disp.dispatch(MyEvent {
220            should_be_42: 39,
221        });
222
223        disp.dispatch(MyEvent {
224            should_be_42: 42,
225        });
226
227        disp.flush();
228    }
229}