Skip to main content

exdsdevs/
time.rs

1// Copyright 2023 Developers of the exdsdevs project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms
8
9/// Time representation module
10pub use std::{
11    collections::HashSet,
12    fmt::Display,
13    ops::{Add, Sub},
14    rc::Rc,
15};
16use std::{convert::TryFrom, fmt::Debug};
17
18use serde::{Deserialize, Serialize};
19
20use crate::{containers::Value, errors::ExdsdevsError};
21
22type Inner = i64;
23
24/// Simulation time value
25#[derive(Clone, Copy, Serialize, Deserialize)]
26pub enum Time {
27    /// Concrete time value
28    Value(Inner),
29    /// Infinite time (passive state)
30    Inf,
31    /// Simulation stop signal
32    StopSim,
33}
34
35impl Time {
36    /// Creates a new time value
37    pub fn new(value: Inner) -> Self {
38        Time::Value(value)
39    }
40
41    /// Infinite time constant
42    pub fn inf() -> Self {
43        Time::Inf
44    }
45
46    pub fn stop() -> Self {
47        Time::StopSim
48    }
49}
50
51impl From<&Time> for Value {
52    fn from(time: &Time) -> Self {
53        match time {
54            Time::Inf => Value::String("Inf".to_owned()),
55            Time::Value(value) => Value::Number(From::from(*value)),
56            Time::StopSim => Value::String("StopSim".to_owned()),
57        }
58    }
59}
60
61impl TryFrom<&str> for Time {
62    type Error = ExdsdevsError;
63
64    fn try_from(value: &str) -> Result<Self, Self::Error> {
65        match value {
66            "Inf" => Ok(Time::Inf),
67            "StopSim" => Ok(Time::StopSim),
68            time @ _ => Ok(Time::Value(time.parse::<Inner>()?)),
69        }
70    }
71}
72
73impl PartialEq for Time {
74    fn eq(&self, other: &Self) -> bool {
75        matches!(self.cmp(other), std::cmp::Ordering::Equal)
76    }
77}
78
79impl Eq for Time {}
80
81impl Ord for Time {
82    /// Compares time values
83    /// # Example
84    /// ```
85    /// let t1 = Time::Value(5);
86    /// let t2 = Time::Value(10);
87    /// assert!(t1 < t2);
88    /// assert!(Time::Inf > t2);
89    /// ```
90    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
91        match (self, other) {
92            (Self::Value(left), Self::Value(right)) => left.cmp(right),
93            (Self::Inf, Self::Value(_)) => std::cmp::Ordering::Greater,
94            (Self::Value(_), Self::Inf) => std::cmp::Ordering::Less,
95            (Self::Inf, Self::Inf) => std::cmp::Ordering::Equal,
96            (Self::StopSim, _) => std::cmp::Ordering::Less,
97            (_, Self::StopSim) => std::cmp::Ordering::Greater,
98        }
99    }
100}
101
102impl PartialOrd for Time {
103    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
104        Some(self.cmp(other))
105    }
106}
107
108impl Display for Time {
109    fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
110        match self {
111            Self::Inf => write!(f, "Inf"),
112            Self::Value(value) => write!(f, "{}", value),
113            Self::StopSim => write!(f, "StopSim"),
114        }
115    }
116}
117
118impl Debug for Time {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120        std::fmt::Display::fmt(&self, f)
121    }
122}
123
124impl Add for Time {
125    type Output = Self;
126
127    fn add(self, rhs: Self) -> Self::Output {
128        match (self, rhs) {
129            (Self::Inf, _) => Self::Inf,
130            (_, Self::Inf) => Self::Inf,
131            (Self::Value(left), Self::Value(right)) => Self::Value(left + right),
132            (Self::StopSim, Self::StopSim) => Self::StopSim,
133            (Self::Value(val), Self::StopSim) => Self::Value(val),
134            (Self::StopSim, Self::Value(val)) => Self::Value(val),
135        }
136    }
137}
138
139impl Sub for Time {
140    type Output = Self;
141
142    fn sub(self, rhs: Self) -> Self::Output {
143        match (self, rhs) {
144            (Self::Inf, _) => Self::Inf,
145            (_, Self::Inf) => Self::Inf,
146            (Self::Value(left), Self::Value(right)) => Self::Value(left - right),
147            (Self::StopSim, Self::StopSim) => Self::StopSim,
148            (Self::Value(val), Self::StopSim) => Self::Value(val),
149            (Self::StopSim, Self::Value(val)) => Self::Value(val),
150        }
151    }
152}