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