a653rs/apex/
time.rs

1/// bindings for ARINC653P1-5 3.4.2 time
2pub mod basic {
3    use crate::apex::types::basic::*;
4
5    /// ARINC653P1-5 3.4.1
6    pub type ApexSystemTime = ApexLongInteger;
7    pub const INFINITE_TIME_VALUE: ApexSystemTime = -1;
8
9    /// ARINC653P4 3.4 required functions for time management functionality
10    pub trait ApexTimeP4 {
11        /// APEX653P4 3.4.2.2 wait until next release
12        ///
13        /// # Errors
14        /// - [ErrorReturnCode::InvalidMode]: calling process is not a periodic process
15        /// - (P1/P2 only) [ErrorReturnCode::InvalidMode]: calling process holds a mutex
16        /// - (P1/P2 only) [ErrorReturnCode::InvalidMode]: calling process is error handler
17        /// - (P1/P2 only) [ErrorReturnCode::InvalidConfig]: deadline calulation failed
18        fn periodic_wait() -> Result<(), ErrorReturnCode>;
19
20        /// APEX653P4 3.4.2.3
21        fn get_time() -> ApexSystemTime;
22    }
23
24    /// ARINC653P1-5 3.4 required functions for time management functionality
25    pub trait ApexTimeP1: ApexTimeP4 {
26        /// ARINC653P1-5 3.4.2.1
27        ///
28        /// # Errors
29        /// - [ErrorReturnCode::InvalidMode]: calling process holds a mutex
30        /// - [ErrorReturnCode::InvalidMode]: calling process is error handler
31        /// - [ErrorReturnCode::InvalidParam]: `delay_time` is too large
32        /// - [ErrorReturnCode::InvalidParam]: `delay_time` is negative (infinite)
33        fn timed_wait(delay_time: ApexSystemTime) -> Result<(), ErrorReturnCode>;
34
35        /// ARINC653P1-5 3.4.2.4 update deadline
36        ///
37        /// # Errors
38        /// - [ErrorReturnCode::InvalidParam]: `budget_time` is invalid
39        /// - [ErrorReturnCode::InvalidMode]: calling process is periodic AND calulated deadline exceeds next release point
40        /// - [ErrorReturnCode::NoAction]: calling process is error handler
41        /// - [ErrorReturnCode::NoAction]: our current operating mode is not [OperatingMode::Normal](crate::prelude::OperatingMode::Normal)
42        fn replenish(budget_time: ApexSystemTime) -> Result<(), ErrorReturnCode>;
43    }
44}
45
46/// abstractions for ARINC653P1-5 3.4.2 time
47pub mod abstraction {
48    use core::time::Duration;
49
50    use super::basic::{ApexSystemTime, ApexTimeP1, ApexTimeP4, INFINITE_TIME_VALUE};
51    use crate::prelude::*;
52
53    /// Abstracted SystemTime Variant making use of Rusts [Duration]
54    /// Includes Infinite-variant since [Duration] does not allow for negative values
55    ///
56    /// # Size
57    ///
58    /// [ApexSystemTime] => 8-Byte  
59    /// [Duration] => 16-Byte  
60    /// [SystemTime] => 24-Byte
61    #[repr(C)]
62    #[derive(Clone, Debug, PartialEq, Eq)]
63    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
64    pub enum SystemTime {
65        Infinite,
66        Normal(Duration),
67    }
68
69    impl SystemTime {
70        pub fn new(time: ApexSystemTime) -> Self {
71            time.into()
72        }
73
74        /// # Panics
75        /// If this SystemTime is [SystemTime::Infinite]
76        pub fn unwrap_duration(self) -> Duration {
77            if let SystemTime::Normal(time) = self {
78                return time;
79            }
80            panic!("Is infinite")
81        }
82    }
83
84    impl From<Duration> for SystemTime {
85        fn from(time: Duration) -> Self {
86            Self::Normal(time)
87        }
88    }
89
90    impl From<SystemTime> for Option<Duration> {
91        fn from(time: SystemTime) -> Self {
92            match time {
93                SystemTime::Infinite => None,
94                SystemTime::Normal(time) => Some(time),
95            }
96        }
97    }
98
99    impl From<Option<Duration>> for SystemTime {
100        fn from(time: Option<Duration>) -> Self {
101            use SystemTime::*;
102            match time {
103                Some(time) => Normal(time),
104                None => Infinite,
105            }
106        }
107    }
108
109    impl From<ApexSystemTime> for SystemTime {
110        /// Converts ApexSystemTime to a [SystemTime]  
111        /// Should ApexSystemTime be less than 0, its considered to be infinite.  
112        /// As stated in ARINC653P1-5 3.4.1 all negative values should be treated as `INFINITE_TIME_VALUE`
113        fn from(time: ApexSystemTime) -> Self {
114            use SystemTime::*;
115            // This conversion can only fail, if ApexSystemTime is negative.
116            match u64::try_from(time) {
117                Ok(time) => Normal(Duration::from_nanos(time)),
118                Err(_) => Infinite,
119            }
120        }
121    }
122
123    impl From<SystemTime> for ApexSystemTime {
124        fn from(time: SystemTime) -> Self {
125            if let SystemTime::Normal(time) = time {
126                if let Ok(time) = ApexSystemTime::try_from(time.as_nanos()) {
127                    return time;
128                }
129            }
130            INFINITE_TIME_VALUE
131        }
132    }
133
134    /// Free extra functions for implementer of [ApexTimeP4]
135    pub trait ApexTimeP4Ext: ApexTimeP4 + Sized {
136        /// wait until next release
137        ///
138        /// # Errors
139        /// - [Error::InvalidMode]: calling process is not a periodic process
140        /// - (P1/P2 only) [Error::InvalidMode]: calling process holds a mutex
141        /// - (P1/P2 only) [Error::InvalidMode]: calling process is error handler
142        /// - (P1/P2 only) [Error::InvalidConfig]: deadline calulation failed
143        fn periodic_wait() -> Result<(), Error>;
144
145        fn get_time() -> SystemTime;
146    }
147
148    impl<T: ApexTimeP4> ApexTimeP4Ext for T {
149        fn periodic_wait() -> Result<(), Error> {
150            T::periodic_wait()?;
151            Ok(())
152        }
153
154        fn get_time() -> SystemTime {
155            T::get_time().into()
156        }
157    }
158
159    /// Free extra functions for implementer of [ApexTimeP1]
160    pub trait ApexTimeP1Ext: ApexTimeP1 + Sized {
161        /// # Errors
162        /// - [Error::InvalidMode]: calling process holds a mutex
163        /// - [Error::InvalidMode]: calling process is error handler
164        /// - [Error::InvalidParam]: `delay_time` is too large
165        fn timed_wait(delay_time: Duration) -> Result<(), Error>;
166
167        /// update deadline
168        ///
169        /// # Errors
170        /// - [Error::InvalidParam]: `budget_time` is invalid
171        /// - [Error::InvalidMode]: calling process is periodic AND calulated deadline exceeds next release point
172        /// - [Error::NoAction]: calling process is error handler
173        /// - [Error::NoAction]: our current operating mode is not [OperatingMode::Normal]
174        fn replenish(budget_time: Duration) -> Result<(), Error>;
175    }
176
177    impl<T: ApexTimeP1> ApexTimeP1Ext for T {
178        fn timed_wait(delay_time: Duration) -> Result<(), Error> {
179            T::timed_wait(SystemTime::Normal(delay_time).into())?;
180            Ok(())
181        }
182
183        fn replenish(budget_time: Duration) -> Result<(), Error> {
184            T::replenish(SystemTime::Normal(budget_time).into())?;
185            Ok(())
186        }
187    }
188}