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}