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 as_ticks(&self) -> u64 {
24        self.ticks
25    }
26
27    pub fn 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        if let Some(t) = self.ticks.checked_mul(1_000_000) {
34            let rst = t.div_ceil(T::frequency().to_kHz() as u64);
35            if rst <= u32::MAX as u64 {
36                return rst as u32;
37            }
38        }
39        panic!();
40    }
41
42    pub fn micros(timeout: u32) -> Self {
43        let us = timeout as u64;
44        Self::from_ticks((us * T::frequency().to_kHz() as u64).div_ceil(1_000))
45    }
46
47    pub fn as_micros(&self) -> u32 {
48        if let Some(t) = self.ticks.checked_mul(1_000) {
49            let rst = t.div_ceil(T::frequency().to_kHz() as u64);
50            if rst <= u32::MAX as u64 {
51                return rst as u32;
52            }
53        }
54        panic!();
55    }
56
57    pub fn millis(timeout: u32) -> Self {
58        let ms = timeout as u64;
59        Self::from_ticks(ms * T::frequency().to_kHz() as u64)
60    }
61
62    pub fn as_millis(&self) -> u32 {
63        let rst = self.ticks.div_ceil(T::frequency().to_kHz() as u64);
64        if rst <= u32::MAX as u64 {
65            return rst as u32;
66        }
67        panic!();
68    }
69
70    #[inline]
71    pub const fn is_zero(&self) -> bool {
72        self.ticks == 0
73    }
74}
75
76impl<T: TickInstant> PartialEq<Self> for TickDuration<T> {
77    #[inline]
78    fn eq(&self, other: &Self) -> bool {
79        self.ticks.eq(&other.ticks)
80    }
81}
82
83impl<T: TickInstant> PartialOrd<Self> for TickDuration<T> {
84    #[inline]
85    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
86        self.ticks.partial_cmp(&other.ticks)
87    }
88}
89
90impl<T: TickInstant> ops::Add<Self> for &TickDuration<T> {
91    type Output = TickDuration<T>;
92    #[inline]
93    fn add(self, rhs: Self) -> Self::Output {
94        TickDuration::from_ticks(self.ticks.saturating_add(rhs.ticks))
95    }
96}
97
98impl<T: TickInstant> ops::Sub<Self> for &TickDuration<T> {
99    type Output = TickDuration<T>;
100    #[inline]
101    fn sub(self, rhs: Self) -> Self::Output {
102        TickDuration::from_ticks(self.ticks.saturating_sub(rhs.ticks))
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109    use crate::mock::MockInstant;
110    type Duration = TickDuration<MockInstant>;
111
112    #[test]
113    fn duration() {
114        let d = Duration::nanos(123);
115        assert_eq!(d.as_nanos(), 123);
116
117        let d = Duration::nanos(123_000);
118        assert_eq!(d.as_nanos(), 123_000);
119
120        let d = Duration::micros(5234);
121        assert_eq!(d.as_micros(), 5234);
122
123        let d = Duration::millis(472);
124        assert_eq!(d.as_millis(), 472);
125
126        let d = Duration::micros(123);
127        assert_eq!(d.as_millis(), 1);
128    }
129}