1use core::fmt::{Debug, Formatter};
4use core::iter::Sum;
5use core::ops::{Add, AddAssign, Div, Mul, Sub};
6
7mod util {
8 pub(crate) const fn lcm(a: super::UnitNumber, b: super::UnitNumber) -> super::UnitNumber {
12 if a == b {
13 a
14 } else {
15 a * b / gcd(a, b)
16 }
17 }
18
19 const fn gcd(mut a: super::UnitNumber, mut b: super::UnitNumber) -> super::UnitNumber {
21 while a != b {
22 if a > b {
23 a -= b
24 } else {
25 b -= a
26 }
27 }
28 a
29 }
30}
31
32pub type UnitNumber = usize;
34
35#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
37pub struct TimeUnit(UnitNumber);
38
39impl Debug for TimeUnit {
40 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
41 core::fmt::Debug::fmt(&self.0, f)
42 }
43}
44
45impl TimeUnit {
46 pub const ZERO: TimeUnit = TimeUnit(0);
48
49 pub const ONE: TimeUnit = TimeUnit(1);
51
52 #[must_use]
54 pub fn max(self, other: Self) -> Self {
55 TimeUnit(self.0.max(other.0))
56 }
57
58 #[must_use]
60 pub const fn lcm(self, other: Self) -> Self {
61 TimeUnit(util::lcm(self.0, other.0))
62 }
63
64 #[must_use]
66 pub const fn as_unit(self) -> UnitNumber {
67 self.0
68 }
69}
70
71impl From<UnitNumber> for TimeUnit {
72 fn from(time: UnitNumber) -> Self {
73 TimeUnit(time)
74 }
75}
76
77impl Div for TimeUnit {
78 type Output = UnitNumber;
79
80 fn div(self, rhs: Self) -> Self::Output {
81 self.0 / rhs.0
82 }
83}
84
85impl Mul<TimeUnit> for UnitNumber {
86 type Output = TimeUnit;
87
88 fn mul(self, rhs: TimeUnit) -> Self::Output {
89 TimeUnit(self * rhs.0)
90 }
91}
92
93impl Mul<UnitNumber> for TimeUnit {
94 type Output = TimeUnit;
95
96 fn mul(self, rhs: UnitNumber) -> Self::Output {
97 TimeUnit(self.0 * rhs)
98 }
99}
100
101impl Add for TimeUnit {
102 type Output = TimeUnit;
103
104 fn add(self, rhs: Self) -> Self::Output {
105 TimeUnit(self.0 + rhs.0)
106 }
107}
108
109impl AddAssign for TimeUnit {
110 fn add_assign(&mut self, rhs: Self) {
111 self.0 += rhs.0
112 }
113}
114
115impl AsRef<TimeUnit> for TimeUnit {
116 fn as_ref(&self) -> &TimeUnit {
117 self
118 }
119}
120
121impl<T: AsRef<TimeUnit>> Sub<T> for TimeUnit {
122 type Output = TimeUnit;
123
124 fn sub(self, rhs: T) -> Self::Output {
125 TimeUnit(self.0 - rhs.as_ref().0)
126 }
127}
128
129impl Sum for TimeUnit {
130 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
131 iter.fold(TimeUnit::from(0), Self::add)
132 }
133}