1#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct Duration(u64);
9
10impl Duration {
11 pub const fn from_millis(ms: u64) -> Self {
13 Duration(ms)
14 }
15
16 pub const fn as_millis(self) -> u64 {
18 self.0
19 }
20
21 pub fn as_secs_f64(self) -> f64 {
23 self.0 as f64 * 1e-3
24 }
25
26 pub const fn to_std(self) -> std::time::Duration {
28 std::time::Duration::from_millis(self.0)
29 }
30}
31
32impl std::ops::Add for Duration {
33 type Output = Duration;
34 fn add(self, rhs: Duration) -> Duration {
35 Duration(self.0 + rhs.0)
36 }
37}
38
39impl std::ops::AddAssign for Duration {
40 fn add_assign(&mut self, rhs: Duration) {
41 self.0 += rhs.0;
42 }
43}
44
45impl std::ops::Sub for Duration {
46 type Output = Duration;
47 fn sub(self, rhs: Duration) -> Duration {
50 Duration(self.0.saturating_sub(rhs.0))
51 }
52}
53
54impl From<Duration> for std::time::Duration {
55 fn from(d: Duration) -> Self {
56 d.to_std()
57 }
58}
59
60impl std::fmt::Display for Duration {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 write!(f, "{} ms", self.0)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn arithmetic_and_conversion() {
72 let a = Duration::from_millis(1500);
73 let b = Duration::from_millis(500);
74 assert_eq!((a - b).as_millis(), 1000);
75 assert_eq!((b - a).as_millis(), 0);
76 assert_eq!((a + b).as_millis(), 2000);
77 assert!((a.as_secs_f64() - 1.5).abs() < 1e-12);
78 assert_eq!(
79 std::time::Duration::from(a),
80 std::time::Duration::from_millis(1500)
81 );
82 }
83}