desque/
error.rs

1/// Errors that may be encountered while executing a simulation.
2///
3/// The [`BackInTime`] variant originates from the safe interface of the [`serial::Simulation`] or
4/// [`threadsafe::Simulation`] to indicate that an event's scheduled execution time is prior to the simulation's current
5/// time. This error likely corresponds to a logical bug on the client side, e.g. forgetting to add an offset to the
6/// current time when scheduling a new event.
7///
8/// The [`BadExecution`] variant originates from client code, providing a wrapper that can pass through
9/// [`serial::Simulation::run()`] or [`threadsafe::Simulation::run()`] in a type-safe manner. Invoking [`source()`] on
10/// this variant will acquire a shared reference to the wrapped [`std::error::Error`] for handling on the client side.
11///
12/// [`serial::Simulation`]: crate::serial::Simulation
13/// [`threadsafe::Simulation`]: crate::threadsafe::Simulation
14/// [`serial::Simulation::run()`]: crate::serial::Simulation::run
15/// [`threadsafe::Simulation::run()`]: crate::threadsafe::Simulation::run
16/// [`BackInTime`]: Error::BackInTime
17/// [`BadExecution`]: Error::BadExecution
18/// [`source()`]: Error#method.source
19#[derive(Debug)]
20pub enum Error {
21    /// The event queue rejected an event that would have been scheduled for a time that has already passed.
22    BackInTime,
23    /// A client-generated error was encountered while executing an event. Call [`source()`] or unpack this value to
24    /// handle it directly.
25    ///
26    /// [`source()`]: #method.source
27    BadExecution(Box<dyn std::error::Error + Send + Sync + 'static>),
28}
29
30impl PartialEq for Error {
31    fn eq(&self, other: &Self) -> bool {
32        match (self, other) {
33            (Error::BackInTime, Error::BackInTime) => true,
34            (Error::BadExecution(e1), Error::BadExecution(e2)) => {
35                let e1: *const dyn std::error::Error = e1.as_ref();
36                let e2: *const dyn std::error::Error = e2.as_ref();
37                std::ptr::eq(e1, e2)
38            },
39            _ => false,
40        }
41    }
42}
43
44impl Eq for Error {}
45
46impl std::fmt::Display for Error {
47    #[allow(clippy::uninlined_format_args)] // compatibility with older Rust versions
48    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
49        let descriptor = match self {
50            Self::BackInTime => "event execution time is less than current simulation time".into(),
51            Self::BadExecution(e) => format!("error while executing event: {}", e),
52        };
53        write!(f, "{}", descriptor)
54    }
55}
56
57impl std::error::Error for Error {
58    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
59        match self {
60            Self::BackInTime => None,
61            Self::BadExecution(e) => Some(e.as_ref()),
62        }
63    }
64}
65
66/// Simplifies the signatures of various functions in desque.
67///
68/// [`desque::Error`]: Error
69pub type Result = std::result::Result<(), Error>;