desque/serial/events/
event_traits.rs

1use crate::serial::Simulation;
2use crate::{SimState, SimTime};
3use std::fmt::Debug;
4
5/// A behavior or state change that occurs within a simulation.
6///
7/// This trait has one required method that describes what happens when the implementing type executes. This trait is
8/// generic over the types used to represent simulation state and clock time to enable your implementations of each
9/// trait to work together within this framework.
10///
11/// Requiring implementors to be [`Debug`] enables printing the full contents of a [`Simulation`]'s internal event queue
12/// when necessary.
13///
14/// Note that desque does not directly support the notion of interrupting events, so if you need that functionality then
15/// you may wish to extend this trait or to otherwise provide a means for your interruptible events to determine whether
16/// they should execute when popped from the queue.
17pub trait Event<State, Time>: Debug
18where
19    State: SimState<Time>,
20    Time: SimTime,
21{
22    /// Update the simulation according to the specific type of event. The simulation will invoke this method during
23    /// [`Simulation::run()`] for each scheduled event in sequence. Exclusive access is provided to the simulation while
24    /// executing an event, allowing for both mutation of the simulation's state and scheduling of new events.
25    ///
26    /// This trait expects implementations of [`execute()`] to be fallible, and [`Simulation::run()`] will bubble any
27    /// errors back up to the client as an [`Error::BadExecution`]. Successful branches, as well as infallible
28    /// implementations, should simply return `Ok(())` to indicate to [`Simulation::run()`] that it may continue popping
29    /// events from the queue.
30    ///
31    /// Note that the simulation's clock time will update before invoking this method.
32    ///
33    /// # Errors
34    ///
35    /// This method signature allows for the possibility of encountering error conditions at runtime. Of particular note
36    /// here, the [`Error::BadExecution`] variant wraps a [`dyn std::error::Error`] and so enables client
37    /// implementations of this method to effectively shut down a simulation when encountering any problems that cannot
38    /// be handled at runtime without causing a panic or otherwise losing information about the error somewhere deep in
39    /// the event queue.
40    ///
41    /// See [`Error`] for more details on the variants of this error enum.
42    ///
43    /// [`Simulation::run()`]: Simulation::run
44    /// [`execute()`]: Event::execute
45    /// [`dyn std::error::Error`]: std::error::Error
46    /// [`Error`]: crate::Error
47    /// [`Error::BadExecution`]: crate::Error::BadExecution
48    fn execute(&mut self, simulation: &mut Simulation<State, Time>) -> crate::Result;
49}
50
51/// An [`Event`] that is guaranteed not to return an [`Error`] on execution.
52///
53/// The [`execute()`] method on this trait differs from [`Event::execute()`] only by omitting the return type. An
54/// implementation of [`Event`] is provided for all implementors of this trait which simply invokes
55/// [`OkEvent::execute()`] then returns `Ok(())`.
56///
57/// As with the requirement on [`Event`], implementing [`Debug`] enables a [`Simulation`] to print all of its contents
58/// when client code deems it necessary.
59///
60/// [`execute()`]: OkEvent::execute
61/// [`Event::execute()`]: Event::execute
62/// [`OkEvent::execute()`]: OkEvent::execute
63/// [`Error`]: crate::Error
64pub trait OkEvent<State, Time>: Debug
65where
66    State: SimState<Time>,
67    Time: SimTime,
68{
69    /// Update the simulation according to the specific type of event. The simulation will invoke this method during
70    /// [`Simulation::run()`] for each scheduled event in sequence. Exclusive access is provided to the simulation
71    /// while executing an event, allowing for both mutation of the simulation's state and scheduling of new events.
72    ///
73    /// Note that the simulation's clock time will update before invoking this method.
74    ///
75    /// [`Simulation::run()`]: Simulation::run
76    fn execute(&mut self, simulation: &mut Simulation<State, Time>);
77}
78
79impl<State, Time, OkEventType> Event<State, Time> for OkEventType
80where
81    State: SimState<Time>,
82    Time: SimTime,
83    OkEventType: OkEvent<State, Time>,
84{
85    fn execute(&mut self, simulation: &mut Simulation<State, Time>) -> crate::Result {
86        OkEvent::execute(self, simulation);
87        Ok(())
88    }
89}