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}