timeout_trait/
duration.rs

1use crate::*;
2use core::{cmp::Ordering, marker::PhantomData, ops};
3
4#[derive(Clone, Copy)]
5pub struct TickDuration<T: TickInstant> {
6    ticks: u64,
7    _t: PhantomData<T>,
8}
9
10impl<T: TickInstant> TickDuration<T> {
11    pub const ZERO: Self = Self::from_ticks(0);
12    pub const MAX: Self = Self::from_ticks(u64::MAX);
13
14    #[inline]
15    pub const fn from_ticks(ticks: u64) -> Self {
16        Self {
17            ticks,
18            _t: PhantomData,
19        }
20    }
21
22    #[inline]
23    pub const fn ticks(&self) -> u64 {
24        self.ticks
25    }
26
27    pub fn from_nanos(timeout: u32) -> Self {
28        let ns = timeout as u64;
29        Self::from_ticks((ns * T::frequency().to_kHz() as u64).div_ceil(1_000_000))
30    }
31
32    pub fn as_nanos(&self) -> u32 {
33        self.ticks
34            .saturating_mul(1_000_000)
35            .div_ceil(T::frequency().to_kHz() as u64) as u32
36    }
37
38    pub fn from_micros(timeout: u32) -> Self {
39        let us = timeout as u64;
40        Self::from_ticks((us * T::frequency().to_kHz() as u64).div_ceil(1_000))
41    }
42
43    pub fn as_micros(&self) -> u32 {
44        self.ticks
45            .saturating_mul(1_000)
46            .div_ceil(T::frequency().to_kHz() as u64) as u32
47    }
48
49    pub fn from_millis(timeout: u32) -> Self {
50        let ms = timeout as u64;
51        Self::from_ticks(ms * T::frequency().to_kHz() as u64)
52    }
53
54    pub fn as_millis(&self) -> u32 {
55        self.ticks.div_ceil(T::frequency().to_kHz() as u64) as u32
56    }
57
58    #[inline]
59    pub const fn is_zero(&self) -> bool {
60        self.ticks == 0
61    }
62}
63
64impl<T: TickInstant> PartialEq<Self> for TickDuration<T> {
65    #[inline]
66    fn eq(&self, other: &Self) -> bool {
67        self.ticks.eq(&other.ticks)
68    }
69}
70
71impl<T: TickInstant> PartialOrd<Self> for TickDuration<T> {
72    #[inline]
73    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
74        self.ticks.partial_cmp(&other.ticks)
75    }
76}
77
78impl<T: TickInstant> ops::Add<Self> for &TickDuration<T> {
79    type Output = TickDuration<T>;
80    #[inline]
81    fn add(self, rhs: Self) -> Self::Output {
82        TickDuration::from_ticks(self.ticks.saturating_add(rhs.ticks))
83    }
84}
85
86impl<T: TickInstant> ops::Sub<Self> for &TickDuration<T> {
87    type Output = TickDuration<T>;
88    #[inline]
89    fn sub(self, rhs: Self) -> Self::Output {
90        TickDuration::from_ticks(self.ticks.saturating_sub(rhs.ticks))
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use crate::mock::MockInstant;
98    type Duration = TickDuration<MockInstant>;
99
100    #[test]
101    fn duration() {
102        let d = Duration::from_nanos(123);
103        assert_eq!(d.as_nanos(), 123);
104
105        let d = Duration::from_nanos(123_000);
106        assert_eq!(d.as_nanos(), 123_000);
107
108        let d = Duration::from_micros(5234);
109        assert_eq!(d.as_micros(), 5234);
110
111        let d = Duration::from_millis(472);
112        assert_eq!(d.as_millis(), 472);
113
114        let d = Duration::from_micros(123);
115        assert_eq!(d.as_millis(), 1);
116    }
117}