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}