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
#![allow(dead_code)]

use std::collections::BTreeMap;

/// Enumerator of the Event type. Whatever type E of Event::Args you implement here is the type E that will be used for the EventPublisher.
pub enum Event<E> {
    Args(E),
    Missing,
}

// To deal with handler functions - F: Rc<Box<Fn(&event<E>)>>
/// EventPublisher. Works similarly to C#'s event publishing pattern. Event handling functions are subscribed to the publisher.
/// Whenever the publisher fires an event it calls all subscribed event handler functions.
/// Use event::EventPublisher::<E>::new() to construct
pub struct EventPublisher<E> {
    //handlers: Vec<Rc<Box<Fn(&Event<E>) + 'static>>>,
    handlers: BTreeMap<usize, fn(&Event<E>)>,
}

impl<E> EventPublisher<E> {

    /// Event publisher constructor.
    pub fn new() -> EventPublisher<E> {
        EventPublisher{ 
            handlers: BTreeMap::<usize, fn(&Event<E>)>::new()
        }
    }
    /// Subscribes event handler functions to the EventPublisher.
    /// INPUT:  handler: fn(&Event<E>) handler is a pointer to a function to handle an event of the type E. The function must
    ///     be capable of handling references to the event type set up by the publisher, rather than the raw event itself.
    /// OUTPUT: void
    pub fn subscribe_handler(&mut self, handler: fn(&Event<E>)){
        let p_handler: usize;
        unsafe{
            p_handler = *(handler as *const usize);
        }
        self.handlers.insert(p_handler, handler);
    }
    
    /// Unsubscribes an event handler from the publisher.
    /// INPUT:  handler: fn(&Event<E>) handler is a pointer to a function to handle an event of the type E.
    /// OUTPUT: bool    output is a bool of whether or not the function was found in the list of subscribed event handlers and subsequently removed.
    pub fn unsubscribe_handler(&mut self, handler: fn(&Event<E>)) -> bool {
        let p_handler: usize;
        unsafe{
            p_handler = *(handler as *const usize);
        }
        match self.handlers.remove(&p_handler){
            Some(_) => true,
            None => false,
        }
    }
        
    // TODO: Implement this concurrently
    /// Publishes events, pushing the &Event<E> to all handler functions stored by the event publisher.
    /// INPUT: event: &Event<E>     Reference to the Event<E> being pushed to all handling functions.
    pub fn publish_event(&self, event: &Event<E>){
        for (_, handler) in self.handlers.iter(){
            handler(event);
        }
    }
}