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
/// An event handler registered on a test loop. Each event handler usually
/// handles only some events, so we will usually have multiple event handlers
/// registered to cover all event types.
pub struct LoopEventHandler<Data: 'static, Event: 'static>(
    Box<dyn FnMut(Event, &mut Data) -> Result<(), Event>>,
);

impl<Data, Event> LoopEventHandler<Data, Event> {
    /// Creates a handler from the handling logic function. The function is
    /// called on each event. It should return Ok(()) if the event was handled,
    /// or Err(event) if the event was not handled (which will cause it to be
    /// passed to the next handler).
    pub fn new(handler: impl FnMut(Event, &mut Data) -> Result<(), Event> + 'static) -> Self {
        Self(Box::new(handler))
    }

    /// Like new(), but the handler is not given the ability to reject the event.
    pub fn new_simple(mut handler: impl FnMut(Event, &mut Data) + 'static) -> Self {
        Self::new(move |event, data| {
            handler(event, data);
            Ok(())
        })
    }

    /// Adapts this handler to a handler whose data is a superset of our data
    /// and whose event is a superset of our event.
    ///   For data, A is a superset of B if A implements AsRef<B> and AsMut<B>.
    ///   For event, A is a superset of B if A implements From<B> and
    ///     TryIntoOrSelf<B>.
    pub fn widen<
        OuterData: AsMut<Data>,
        OuterEvent: TryIntoOrSelf<Event> + From<Event> + 'static,
    >(
        mut self,
    ) -> LoopEventHandler<OuterData, OuterEvent> {
        LoopEventHandler(Box::new(move |event, data| {
            let mut inner_data = data.as_mut();
            let inner_event = event.try_into_or_self()?;
            self.0(inner_event, &mut inner_data)?;
            Ok(())
        }))
    }

    /// Adapts this handler to a handler whose data is a vector of our data,
    /// and whose event is a is the tuple (index, our event), for a specific
    /// index.
    pub fn for_index(mut self, index: usize) -> LoopEventHandler<Vec<Data>, (usize, Event)> {
        LoopEventHandler(Box::new(move |event, data| {
            if event.0 == index {
                self.0(event.1, &mut data[index]).map_err(|event| (index, event))
            } else {
                Err(event)
            }
        }))
    }

    pub(crate) fn handle(&mut self, event: Event, data: &mut Data) -> Result<(), Event> {
        self.0(event, data)
    }
}

/// A convenient trait to TryInto, or else return the original object. It's useful
/// for implementing event handlers.
pub trait TryIntoOrSelf<R>: Sized {
    fn try_into_or_self(self) -> Result<R, Self>;
}

impl<R, T: TryInto<R, Error = T>> TryIntoOrSelf<R> for T {
    fn try_into_or_self(self) -> Result<R, Self> {
        self.try_into()
    }
}

/// An event handler that puts the event into a vector in the Data, as long as
/// the Data contains a Vec<CapturedEvent>. (Use widen() right after).
///
/// This is used on output events so that after the test loop finishes running
/// we can assert on those events.
pub fn capture_events<Event>() -> LoopEventHandler<Vec<Event>, Event> {
    LoopEventHandler::new_simple(|event, data: &mut Vec<Event>| data.push(event))
}

/// An event handler that ignores all events.
pub fn ignore_events<Event>() -> LoopEventHandler<(), Event> {
    LoopEventHandler::new_simple(|_, _| {})
}