1use derive_more::{
2 Add, AddAssign, Binary, Deref, Display, Into, LowerHex, MulAssign, Octal, Sub, Sum, UpperHex,
3};
4use std::ops;
5
6#[derive(
8 Copy,
9 Clone,
10 Eq,
11 PartialEq,
12 Ord,
13 PartialOrd,
14 Hash,
15 Debug,
16 Display,
17 Deref,
18 Into,
19 Binary,
20 Octal,
21 LowerHex,
22 UpperHex,
23 Add,
24 Sum,
25 AddAssign,
26 MulAssign,
27)]
28#[display(fmt = "{_0}")]
29pub struct Frequency(pub(crate) u32);
30
31impl Frequency {
32 pub fn is_unitless(&self) -> bool {
33 self.0 == 0
34 }
35
36 pub fn get_raw(&self) -> u32 {
37 self.0
38 }
39}
40
41#[derive(
42 Copy,
43 Clone,
44 Eq,
45 PartialEq,
46 Ord,
47 PartialOrd,
48 Hash,
49 Debug,
50 Display,
51 Binary,
52 Octal,
53 LowerHex,
54 UpperHex,
55 Add,
56 Sub,
57 Sum,
58 AddAssign,
59 MulAssign,
60 Into,
61)]
62#[display(fmt = "{_0}")]
63pub struct Ticks(pub(crate) u32);
64
65impl Ticks {
66 pub const fn zero() -> Self {
67 Self(0)
68 }
69
70 pub const fn get_raw(&self) -> u32 {
71 self.0
72 }
73
74 pub fn new(ticks: u32) -> Self {
75 Self(ticks)
76 }
77}
78
79#[derive(
86 Copy,
87 Clone,
88 Eq,
89 PartialEq,
90 Ord,
91 PartialOrd,
92 Hash,
93 Debug,
94 Display,
95 Binary,
96 Octal,
97 LowerHex,
98 UpperHex,
99 Add,
100 Sub,
101 Sum,
102 AddAssign,
103 MulAssign,
104 Into,
105)]
106#[display(fmt = "{_0}")]
107pub struct Timestamp(pub(crate) u64);
108
109impl Timestamp {
110 pub const fn zero() -> Self {
111 Self(0)
112 }
113
114 pub const fn get_raw(&self) -> u64 {
115 self.0
116 }
117
118 pub const fn ticks(&self) -> u64 {
119 self.get_raw()
120 }
121}
122
123impl From<Ticks> for Timestamp {
124 fn from(t: Ticks) -> Self {
125 Timestamp(t.0.into())
126 }
127}
128
129impl ops::Add<DifferentialTimestamp> for Timestamp {
130 type Output = Timestamp;
131
132 fn add(self, dt: DifferentialTimestamp) -> Timestamp {
133 Timestamp(
134 self.0
135 .checked_add(u64::from(dt.0))
136 .expect("Overflow when adding differential time to timestamp"),
137 )
138 }
139}
140
141impl ops::AddAssign<DifferentialTimestamp> for Timestamp {
142 fn add_assign(&mut self, dt: DifferentialTimestamp) {
143 self.0 = self
144 .0
145 .checked_add(u64::from(dt.0))
146 .expect("Overflow when adding differential time to timestamp")
147 }
148}
149
150#[derive(
155 Copy,
156 Clone,
157 Eq,
158 PartialEq,
159 Ord,
160 PartialOrd,
161 Hash,
162 Debug,
163 Display,
164 Binary,
165 Octal,
166 LowerHex,
167 UpperHex,
168 Add,
169 Sum,
170 AddAssign,
171 MulAssign,
172)]
173#[display(fmt = "{_0}")]
174pub struct DifferentialTimestamp(pub(crate) u32);
175
176impl DifferentialTimestamp {
177 pub fn ticks(&self) -> Ticks {
178 Ticks(self.0)
179 }
180}
181
182impl DifferentialTimestamp {
183 pub(crate) fn from_xts8(xts_8: u8, xts_16: u16) -> Self {
187 DifferentialTimestamp(u32::from(xts_8) << 24 | (u32::from(xts_16) << 8))
188 }
189
190 pub(crate) fn from_xts16(xts_16: u16) -> Self {
194 DifferentialTimestamp(u32::from(xts_16) << 16)
195 }
196
197 pub const fn zero() -> Self {
198 Self(0)
199 }
200
201 pub fn clear(&mut self) {
202 self.0 = 0;
203 }
204}
205
206impl ops::AddAssign<Dts8> for DifferentialTimestamp {
207 fn add_assign(&mut self, dts: Dts8) {
208 self.0 = self
209 .0
210 .checked_add(u32::from(dts.0))
211 .expect("Overflow when adding DTS8 to differential time")
212 }
213}
214
215impl ops::AddAssign<Dts16> for DifferentialTimestamp {
216 fn add_assign(&mut self, dts: Dts16) {
217 self.0 = self
218 .0
219 .checked_add(u32::from(dts.0))
220 .expect("Overflow when adding DTS16 to differential time")
221 }
222}
223
224#[derive(
226 Copy,
227 Clone,
228 Eq,
229 PartialEq,
230 Ord,
231 PartialOrd,
232 Hash,
233 Debug,
234 Into,
235 Display,
236 Binary,
237 Octal,
238 LowerHex,
239 UpperHex,
240)]
241#[display(fmt = "{_0}")]
242pub struct Dts8(pub(crate) u8);
243
244#[derive(
246 Copy,
247 Clone,
248 Eq,
249 PartialEq,
250 Ord,
251 PartialOrd,
252 Hash,
253 Debug,
254 Into,
255 Display,
256 Binary,
257 Octal,
258 LowerHex,
259 UpperHex,
260)]
261#[display(fmt = "{_0}")]
262pub struct Dts16(pub(crate) u16);
263
264#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display)]
267#[display(fmt = "{}", "self.to_timestamp()")]
268pub struct StreamingInstant {
269 lower: u32,
270 upper: u32,
271}
272
273impl StreamingInstant {
274 pub const fn zero() -> Self {
275 Self { lower: 0, upper: 0 }
276 }
277
278 pub const fn new(lower: u32, upper: u32) -> Self {
279 Self { lower, upper }
280 }
281
282 pub const fn from_initial_value(initial_value: u64) -> Self {
283 Self {
284 lower: initial_value as u32,
285 upper: (initial_value >> 32) as u32,
286 }
287 }
288
289 pub fn elapsed(&mut self, now: Timestamp) -> Timestamp {
290 let now = now.0 as u32;
292
293 if now < self.lower {
295 self.upper += 1;
296 }
297
298 self.lower = now;
299
300 self.to_timestamp()
301 }
302
303 pub fn to_timestamp(&self) -> Timestamp {
304 Timestamp(u64::from(self.upper) << 32 | u64::from(self.lower))
305 }
306}
307
308#[cfg(test)]
309mod test {
310 use super::*;
311
312 #[test]
313 fn differential_time_xts16() {
314 let mut accumulated_time = Timestamp::zero();
315 accumulated_time.0 += 0x0F;
316 assert_eq!(accumulated_time.ticks(), 0x0F);
317
318 let xts_16 = 0x00_03;
319 let mut dts_for_next_event = DifferentialTimestamp::from_xts16(xts_16);
320 assert_eq!(dts_for_next_event.ticks().0, 0x00_03_00_00);
321
322 let dts = Dts16(0x5F_D5);
323 dts_for_next_event += dts;
324 assert_eq!(dts_for_next_event.ticks().0, 0x00_03_5F_D5);
325
326 accumulated_time += dts_for_next_event;
327 assert_eq!(accumulated_time.ticks(), 0x00_03_5F_D5 + 0x0F);
328 }
329
330 #[test]
331 fn differential_time_xts8() {
332 let mut accumulated_time = Timestamp::zero();
333 accumulated_time.0 += 0x0F;
334 assert_eq!(accumulated_time.ticks(), 0x0F);
335
336 let xts_16 = 0x11_22;
337 let xts_8 = 0xE1;
338 let mut dts_for_next_event = DifferentialTimestamp::from_xts8(xts_8, xts_16);
339 assert_eq!(dts_for_next_event.ticks().0, 0xE1_11_22_00);
340
341 let dts = Dts8(0x33);
342 dts_for_next_event += dts;
343 assert_eq!(dts_for_next_event.ticks().0, 0xE1_11_22_33);
344
345 accumulated_time += dts_for_next_event;
346 assert_eq!(accumulated_time.ticks(), 0xE1_11_22_33 + 0x0F);
347 }
348
349 #[test]
350 fn streaming_instant_rollover() {
351 let t0 = Timestamp(4_294_967_290);
353
354 let t1 = Timestamp(10);
356
357 let mut instant = StreamingInstant::zero();
358 assert_eq!(instant.elapsed(t0), t0);
359
360 let t2 = instant.elapsed(t1);
361 assert_eq!(t0.ticks() + 16, t2.ticks());
362 }
363
364 #[test]
365 fn streaming_instant_construction() {
366 let mut t = StreamingInstant::from_initial_value(u64::from(u32::MAX) + 1);
367 assert_eq!(t.lower, 0);
368 assert_eq!(t.upper, 1);
369 let t0 = Timestamp(2);
370 let instant = t.elapsed(t0);
371 assert_eq!(t.lower, 2);
372 assert_eq!(t.upper, 1);
373 assert_eq!(instant.0, u64::from(u32::MAX) + 3);
374 }
375}