1use core::fmt;
2use core::ops::{Add, AddAssign, Sub, SubAssign};
3
4use super::{Duration, GCD_1G, GCD_1K, GCD_1M, TICK_HZ};
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8pub struct Instant {
10 ticks: u64,
11}
12
13impl Instant {
14 pub const MIN: Instant = Instant { ticks: u64::MIN };
16 pub const MAX: Instant = Instant { ticks: u64::MAX };
18
19 #[inline]
21 pub fn now() -> Instant {
22 Instant {
23 ticks: embassy_time_driver::now(),
24 }
25 }
26
27 pub const fn from_ticks(ticks: u64) -> Self {
29 Self { ticks }
30 }
31
32 pub const fn from_nanos(nanos: u64) -> Self {
34 Self {
35 ticks: nanos * (TICK_HZ / GCD_1G) / (1_000_000_000 / GCD_1G),
36 }
37 }
38
39 pub const fn from_micros(micros: u64) -> Self {
41 Self {
42 ticks: micros * (TICK_HZ / GCD_1M) / (1_000_000 / GCD_1M),
43 }
44 }
45
46 pub const fn from_millis(millis: u64) -> Self {
48 Self {
49 ticks: millis * (TICK_HZ / GCD_1K) / (1000 / GCD_1K),
50 }
51 }
52
53 pub const fn from_secs(seconds: u64) -> Self {
55 Self {
56 ticks: seconds * TICK_HZ,
57 }
58 }
59
60 pub const fn try_from_nanos(nanos: u64) -> Option<Self> {
63 let Some(value) = nanos.checked_mul(TICK_HZ / GCD_1G) else {
64 return None;
65 };
66 Some(Self {
67 ticks: value / (1_000_000_000 / GCD_1G),
68 })
69 }
70
71 pub const fn try_from_micros(micros: u64) -> Option<Self> {
74 let Some(value) = micros.checked_mul(TICK_HZ / GCD_1M) else {
75 return None;
76 };
77 Some(Self {
78 ticks: value / (1_000_000 / GCD_1M),
79 })
80 }
81
82 pub const fn try_from_millis(millis: u64) -> Option<Self> {
85 let Some(value) = millis.checked_mul(TICK_HZ / GCD_1K) else {
86 return None;
87 };
88 Some(Self {
89 ticks: value / (1000 / GCD_1K),
90 })
91 }
92
93 pub const fn try_from_secs(seconds: u64) -> Option<Self> {
96 let Some(ticks) = seconds.checked_mul(TICK_HZ) else {
97 return None;
98 };
99 Some(Self { ticks })
100 }
101
102 pub const fn as_ticks(&self) -> u64 {
104 self.ticks
105 }
106
107 pub const fn as_secs(&self) -> u64 {
109 self.ticks / TICK_HZ
110 }
111
112 pub const fn as_millis(&self) -> u64 {
114 self.ticks * (1000 / GCD_1K) / (TICK_HZ / GCD_1K)
115 }
116
117 pub const fn as_micros(&self) -> u64 {
119 self.ticks * (1_000_000 / GCD_1M) / (TICK_HZ / GCD_1M)
120 }
121
122 pub const fn as_nanos(&self) -> u64 {
124 self.ticks * (1_000_000_000 / GCD_1G) / (TICK_HZ / GCD_1G)
125 }
126
127 pub fn duration_since(&self, earlier: Instant) -> Duration {
130 Duration {
131 ticks: unwrap!(self.ticks.checked_sub(earlier.ticks)),
132 }
133 }
134
135 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
137 if self.ticks < earlier.ticks {
138 None
139 } else {
140 Some(Duration {
141 ticks: self.ticks - earlier.ticks,
142 })
143 }
144 }
145
146 pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
149 Duration {
150 ticks: if self.ticks < earlier.ticks {
151 0
152 } else {
153 self.ticks - earlier.ticks
154 },
155 }
156 }
157
158 pub fn elapsed(&self) -> Duration {
160 Instant::now() - *self
161 }
162
163 pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
165 self.ticks.checked_add(duration.ticks).map(|ticks| Instant { ticks })
166 }
167
168 pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
170 self.ticks.checked_sub(duration.ticks).map(|ticks| Instant { ticks })
171 }
172
173 pub fn saturating_add(mut self, duration: Duration) -> Self {
175 self.ticks = self.ticks.saturating_add(duration.ticks);
176 self
177 }
178
179 pub fn saturating_sub(mut self, duration: Duration) -> Self {
181 self.ticks = self.ticks.saturating_sub(duration.ticks);
182 self
183 }
184}
185
186impl Add<Duration> for Instant {
187 type Output = Instant;
188
189 fn add(self, other: Duration) -> Instant {
190 self.checked_add(other)
191 .expect("overflow when adding duration to instant")
192 }
193}
194
195impl AddAssign<Duration> for Instant {
196 fn add_assign(&mut self, other: Duration) {
197 *self = *self + other;
198 }
199}
200
201impl Sub<Duration> for Instant {
202 type Output = Instant;
203
204 fn sub(self, other: Duration) -> Instant {
205 self.checked_sub(other)
206 .expect("overflow when subtracting duration from instant")
207 }
208}
209
210impl SubAssign<Duration> for Instant {
211 fn sub_assign(&mut self, other: Duration) {
212 *self = *self - other;
213 }
214}
215
216impl Sub<Instant> for Instant {
217 type Output = Duration;
218
219 fn sub(self, other: Instant) -> Duration {
220 self.duration_since(other)
221 }
222}
223
224impl<'a> fmt::Display for Instant {
225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 write!(f, "{} ticks", self.ticks)
227 }
228}