1use core::fmt;
2use core::ops::{Add, AddAssign, Sub, SubAssign};
3
4use super::{Duration, 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 pub fn now() -> Instant {
21 Instant {
22 ticks: embassy_time_driver::now(),
23 }
24 }
25
26 pub const fn from_ticks(ticks: u64) -> Self {
28 Self { ticks }
29 }
30
31 pub const fn from_micros(micros: u64) -> Self {
33 Self {
34 ticks: micros * (TICK_HZ / GCD_1M) / (1_000_000 / GCD_1M),
35 }
36 }
37
38 pub const fn from_millis(millis: u64) -> Self {
40 Self {
41 ticks: millis * (TICK_HZ / GCD_1K) / (1000 / GCD_1K),
42 }
43 }
44
45 pub const fn from_secs(seconds: u64) -> Self {
47 Self {
48 ticks: seconds * TICK_HZ,
49 }
50 }
51
52 pub const fn as_ticks(&self) -> u64 {
54 self.ticks
55 }
56
57 pub const fn as_secs(&self) -> u64 {
59 self.ticks / TICK_HZ
60 }
61
62 pub const fn as_millis(&self) -> u64 {
64 self.ticks * (1000 / GCD_1K) / (TICK_HZ / GCD_1K)
65 }
66
67 pub const fn as_micros(&self) -> u64 {
69 self.ticks * (1_000_000 / GCD_1M) / (TICK_HZ / GCD_1M)
70 }
71
72 pub fn duration_since(&self, earlier: Instant) -> Duration {
75 Duration {
76 ticks: unwrap!(self.ticks.checked_sub(earlier.ticks)),
77 }
78 }
79
80 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
82 if self.ticks < earlier.ticks {
83 None
84 } else {
85 Some(Duration {
86 ticks: self.ticks - earlier.ticks,
87 })
88 }
89 }
90
91 pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
94 Duration {
95 ticks: if self.ticks < earlier.ticks {
96 0
97 } else {
98 self.ticks - earlier.ticks
99 },
100 }
101 }
102
103 pub fn elapsed(&self) -> Duration {
105 Instant::now() - *self
106 }
107
108 pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
110 self.ticks.checked_add(duration.ticks).map(|ticks| Instant { ticks })
111 }
112
113 pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
115 self.ticks.checked_sub(duration.ticks).map(|ticks| Instant { ticks })
116 }
117}
118
119impl Add<Duration> for Instant {
120 type Output = Instant;
121
122 fn add(self, other: Duration) -> Instant {
123 self.checked_add(other)
124 .expect("overflow when adding duration to instant")
125 }
126}
127
128impl AddAssign<Duration> for Instant {
129 fn add_assign(&mut self, other: Duration) {
130 *self = *self + other;
131 }
132}
133
134impl Sub<Duration> for Instant {
135 type Output = Instant;
136
137 fn sub(self, other: Duration) -> Instant {
138 self.checked_sub(other)
139 .expect("overflow when subtracting duration from instant")
140 }
141}
142
143impl SubAssign<Duration> for Instant {
144 fn sub_assign(&mut self, other: Duration) {
145 *self = *self - other;
146 }
147}
148
149impl Sub<Instant> for Instant {
150 type Output = Duration;
151
152 fn sub(self, other: Instant) -> Duration {
153 self.duration_since(other)
154 }
155}
156
157impl<'a> fmt::Display for Instant {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 write!(f, "{} ticks", self.ticks)
160 }
161}