environment.rs 3.51 KB
Newer Older
Ralf's avatar
Ralf committed
1 2

use std::time::Duration;
Ralf's avatar
Ralf committed
3
use chan::Receiver;
Ralf's avatar
Ralf committed
4 5 6

use util::timeout_chan;
use input::Event;
Ralf's avatar
Ralf committed
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

#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum HandlerResult {
    Continue,
    QuitLoop,
}

// TODO: Consider making this a trait, or a type alias for a raw FnMut
pub struct EventHandler<'a> {
    run: Box<FnMut(Event) -> HandlerResult + 'a>,
}

impl<'a> EventHandler<'a> {
    pub fn new<F>(f: F) -> Self
        where F: FnMut(Event) -> HandlerResult + 'a
    {
        EventHandler { run: Box::new(f) }
    }

    pub fn new_boxed(f: Box<FnMut(Event) -> HandlerResult + 'a>) -> Self {
        EventHandler { run: f }
    }

    pub fn new_safe<F>(mut f: F) -> Self
        where F: FnMut(Event) + 'a
    {
        EventHandler {
            run: Box::new(move |ev| {
                f(ev);
                HandlerResult::Continue
            }),
        }
    }

    pub fn new_safe_boxed(mut f: Box<FnMut(Event) + 'a>) -> Self {
        EventHandler {
            run: Box::new(move |ev| {
                f(ev);
                HandlerResult::Continue
            }),
        }
    }

    #[inline]
    pub fn run(&mut self, ev: Event) -> HandlerResult {
        (self.run)(ev)
    }
}

Ralf's avatar
Ralf committed
57 58 59 60 61 62 63 64 65 66 67 68


#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum EventsResult {
    ShuttingDown,
    Timeout,
    Quit,
}

pub struct Environment {
    events: Receiver<Event>,
Ralf's avatar
Ralf committed
69
    door_locked: bool,
Ralf's avatar
Ralf committed
70 71
}

Ralf's avatar
Ralf committed
72
macro_rules! handle_events {
73 74 75 76 77 78
    ( $env:expr, $( $x:expr ),* ) => {
        { $env.handle_events(vec![$( $x, )*] ) }
    };
}

macro_rules! handle_events_timeout {
Ralf's avatar
Ralf committed
79
    ( $env:expr, $d:expr, $( $x:expr ),* ) => {
80
        { $env.handle_events_timeout($d, vec![$( $x, )*] ) }
Ralf's avatar
Ralf committed
81 82 83
    };
}

Ralf's avatar
Ralf committed
84
impl Environment {
Ralf's avatar
rustfmt  
Ralf committed
85 86
    pub fn handle_events(&mut self, mut handlers: Vec<EventHandler>) -> EventsResult {

87 88 89
        for ev in self.events.clone() {
            match self.handle_event(&mut handlers, ev) {
                Some(result) => return result,
Ralf's avatar
rustfmt  
Ralf committed
90
                _ => {}
91 92 93 94
            }
        }
        return EventsResult::ShuttingDown;
    }
Ralf's avatar
rustfmt  
Ralf committed
95 96


97
    pub fn handle_events_timeout(&mut self,
Ralf's avatar
rustfmt  
Ralf committed
98 99 100
                                 d: Duration,
                                 mut handlers: Vec<EventHandler>)
                                 -> EventsResult {
Ralf's avatar
Ralf committed
101
        let timeout_chan = timeout_chan(d);
Ralf's avatar
Ralf committed
102
        let events = self.events.clone();
Ralf's avatar
Ralf committed
103 104 105 106 107
        loop {
            chan_select! {
                timeout_chan.recv() => return EventsResult::Timeout,
                events.recv() -> ev => {
                    match ev {
Ralf's avatar
Ralf committed
108
                        None => return EventsResult::ShuttingDown,
Ralf's avatar
Ralf committed
109
                        Some(ev) => {
110 111 112
                            match self.handle_event(&mut handlers, ev) {
                                Some(result) => return result,
                                _ => {},
Ralf's avatar
Ralf committed
113 114 115 116 117 118 119
                            }
                        }
                    }
                }
            }
        }
    }
Ralf's avatar
rustfmt  
Ralf committed
120 121 122 123 124

    fn handle_event(&mut self,
                    handlers: &mut Vec<EventHandler>,
                    ev: Event)
                    -> Option<EventsResult> {
125 126 127
        self.record_state(&ev);
        for handler in handlers.iter_mut() {
            match handler.run(ev) {
Ralf's avatar
rustfmt  
Ralf committed
128
                HandlerResult::Continue => {}
129 130 131 132 133
                HandlerResult::QuitLoop => return Some(EventsResult::Quit),
            }
        }
        return None;
    }
Ralf's avatar
Ralf committed
134

Ralf's avatar
Ralf committed
135 136
    fn record_state(&mut self, ev: &Event) {
        match ev {
Ralf's avatar
rustfmt  
Ralf committed
137 138
            &Event::DoorLocked(b) => self.door_locked = b,
            _ => {}
Ralf's avatar
Ralf committed
139 140
        }
    }
Ralf's avatar
Ralf committed
141 142 143 144 145

    pub fn door_locked(&self) -> bool {
        true
    }
}