1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
// std
use std::collections::HashMap;
use std::marker::PhantomData;

// uuid
extern crate uuid;
use uuid::Uuid;

#[cfg(test)]
#[macro_use]
extern crate lazy_static;
#[cfg(test)]
mod tests;

// Note: This doesn't support Copy or Clone for safety reasons.
// More specifically, it should be impossible to unregister the same handler more than once.
pub struct EventHandlerId<T: Event + ?Sized> {
  id: Uuid,
  _t: PhantomData<T>,
}
impl<T: Event + ?Sized> Eq for EventHandlerId<T> {}
impl<T: Event + ?Sized> PartialEq for EventHandlerId<T> {
  fn eq(&self, other: &Self) -> bool {
    // PhantomData is only included for completeness.
    self.id == other.id && self._t == other._t
  }
}

struct EventHandler<T: Event + ?Sized> {
  priority: i32,
  f: fn(&mut T), // Multiple handlers for the same event/bus.
  id: EventHandlerId<T>,
}

pub struct EventMetadata<T: Event + ?Sized> {
  // This should be changed to allow for non-static EventBus.
  handlers: HashMap<&'static EventBus, Vec<EventHandler<T>>>,
}

impl<T: Event + ?Sized> EventMetadata<T> {
  pub fn new() -> EventMetadata<T> {
    EventMetadata { handlers: HashMap::new() }
  }

  fn put(&mut self, bus: &'static EventBus, f: fn(&mut T), priority: i32) -> EventHandlerId<T> {
    // Sorted based on priority
    let vec = self.handlers.entry(bus).or_insert_with(Vec::new);
    let pos = vec.binary_search_by(|a| a.priority.cmp(&priority)).unwrap_or_else(|e| e);
    let id = Uuid::new_v4();
    vec.insert(pos, EventHandler { f: f, priority: priority, id: EventHandlerId { id: id, _t: PhantomData } });
    EventHandlerId { id: id, _t: PhantomData } // Single-use removal key
  }

  fn remove(&mut self, bus: &EventBus, f: EventHandlerId<T>) {
    let flag = self.handlers.get_mut(bus).iter_mut().any(|v| { v.retain(|x| x.id != f); v.is_empty() });
    if flag { self.handlers.remove(bus); }
  }

  fn post(&self, bus: &EventBus, event: &mut T) -> bool {
    self.handlers.get(bus).iter().flat_map(|x| x.iter()).any(|h| {
      (h.f)(event);
      event.cancelled()
    })
  }
}

pub trait Event {
  // type properties
  fn event_metadata<F, R>(F) -> R where F: FnOnce(&EventMetadata<Self>) -> R;

  fn mut_metadata<F, R>(F) -> R where F: FnOnce(&mut EventMetadata<Self>) -> R;

  fn cancellable() -> bool { false }

  // instance properties
  fn cancelled(&self) -> bool { false }

  fn cancel(&mut self, bool) { panic!() }
}

#[derive(PartialEq, Eq, Hash)]
pub struct EventBus {
  uuid: Uuid
}

impl EventBus {
  pub fn new() -> EventBus {
    EventBus { uuid: Uuid::new_v4() }
  }

  pub fn register<T>(&'static self, f: fn(&mut T), priority: i32) -> EventHandlerId<T> where T: Event {
    T::mut_metadata(|x| x.put(self, f, priority))
  }

  pub fn unregister<T>(&self, f: EventHandlerId<T>) where T: Event {
    T::mut_metadata(|x| x.remove(self, f))
  }

  pub fn post<T>(&self, event: &mut T) -> bool where T: Event {
    T::event_metadata(|x| x.post(self, event))
  }
}