timeout_trait/
duration.rs1use 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}