embedded_time/instant.rs
1//! An instant of time
2
3use crate::{
4 duration::{self, Duration},
5 fixed_point::FixedPoint,
6};
7use core::{
8 cmp::Ordering,
9 convert::TryFrom,
10 hash::{Hash, Hasher},
11 ops,
12};
13use num::traits::{WrappingAdd, WrappingSub};
14
15/// Represents an instant of time relative to a specific [`Clock`](clock/trait.Clock.html)
16///
17/// # Example
18///
19/// Typically an `Instant` will be obtained from a [`Clock`](clock/trait.Clock.html)
20///
21/// ```rust
22/// # use embedded_time::{fraction::Fraction, Instant, Clock as _};
23/// # #[derive(Debug)]
24/// # struct SomeClock;
25/// # impl embedded_time::Clock for SomeClock {
26/// # type T = u32;
27/// # const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
28/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {Ok(Instant::<Self>::new(23))}
29/// # }
30/// let some_clock = SomeClock;
31/// let some_instant = some_clock.try_now().unwrap();
32/// ```
33///
34/// However, an `Instant` can also be constructed directly. In this case the constructed `Instant`
35/// is `23 * SomeClock::SCALING_FACTOR` seconds since the clock's epoch
36///
37/// ```rust,no_run
38/// # use embedded_time::{fraction::Fraction, Instant};
39/// # #[derive(Debug)]
40/// # struct SomeClock;
41/// # impl embedded_time::Clock for SomeClock {
42/// # type T = u32;
43/// # const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
44/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
45/// # }
46/// Instant::<SomeClock>::new(23);
47/// ```
48#[derive(Debug)]
49#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50pub struct Instant<Clock: crate::Clock> {
51 ticks: Clock::T,
52}
53
54impl<Clock: crate::Clock> Instant<Clock> {
55 /// Construct a new Instant from the provided [`Clock`](clock/trait.Clock.html)
56 pub fn new(ticks: Clock::T) -> Self {
57 Self { ticks }
58 }
59
60 /// Returns the amount of time elapsed from another instant to this one as a
61 /// [`duration::Generic`] or [`None`] if the other instant is later than
62 /// this one.
63 ///
64 /// # Examples
65 ///
66 /// ```rust
67 /// # use embedded_time::{duration::*, Instant, ConversionError};
68 /// # use core::convert::TryInto;
69 /// # #[derive(Debug)]
70 /// struct Clock;
71 /// impl embedded_time::Clock for Clock {
72 /// type T = u32;
73 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
74 /// // ...
75 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
76 /// }
77 /// #
78 /// # let instant1 = Instant::<Clock>::new(3);
79 /// # let instant2 = Instant::<Clock>::new(5);
80 ///
81 /// // Given `instant1` at 3 `Clock` ticks
82 /// // Given `instant2` at 5 `Clock` ticks
83 /// let generic_duration = instant2.checked_duration_since(&instant1).unwrap();
84 ///
85 /// // Convert into a _named_ `Duration`
86 /// let microseconds: Microseconds<u32> = generic_duration.try_into().unwrap();
87 ///
88 /// assert_eq!(microseconds, Microseconds(2_000_u32));
89 /// ```
90 pub fn checked_duration_since(&self, other: &Self) -> Option<duration::Generic<Clock::T>> {
91 if self >= other {
92 Some(duration::Generic::new(
93 self.ticks.wrapping_sub(&other.ticks),
94 Clock::SCALING_FACTOR,
95 ))
96 } else {
97 None
98 }
99 }
100
101 /// Returns the amount of time elapsed from self until that given instant
102 /// [`duration::Generic`] or [`None`] if the other instant is later than
103 /// this one.
104 ///
105 /// # Examples
106 ///
107 /// ```rust
108 /// # use embedded_time::{duration::*, Instant, ConversionError};
109 /// # use core::convert::TryInto;
110 /// # #[derive(Debug)]
111 /// struct Clock;
112 /// impl embedded_time::Clock for Clock {
113 /// type T = u32;
114 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
115 /// // ...
116 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
117 /// }
118 /// #
119 /// # let instant1 = Instant::<Clock>::new(3);
120 /// # let instant2 = Instant::<Clock>::new(5);
121 ///
122 /// // Given `instant1` at 3 `Clock` ticks
123 /// // Given `instant2` at 5 `Clock` ticks
124 /// let generic_duration = instant1.checked_duration_until(&instant2).unwrap();
125 ///
126 /// // Convert into a _named_ `Duration`
127 /// let microseconds: Microseconds<u32> = generic_duration.try_into().unwrap();
128 ///
129 /// assert_eq!(microseconds, Microseconds(2_000_u32));
130 /// ```
131 pub fn checked_duration_until(&self, other: &Self) -> Option<duration::Generic<Clock::T>> {
132 if self <= other {
133 Some(duration::Generic::new(
134 other.ticks.wrapping_sub(&self.ticks),
135 Clock::SCALING_FACTOR,
136 ))
137 } else {
138 None
139 }
140 }
141
142 /// Returns the [`Duration`] (in the provided units) since the beginning of time (the
143 /// [`Clock`](clock/trait.Clock.html)'s 0)
144 pub fn duration_since_epoch(&self) -> duration::Generic<Clock::T> {
145 duration::Generic::new(self.ticks, Clock::SCALING_FACTOR)
146 }
147
148 /// This `Instant` + [`Duration`] = later (future) `Instant`
149 ///
150 /// Returns [`None`] if the [`Duration`] is too large
151 ///
152 /// # Examples
153 ///
154 /// ```rust
155 /// # use embedded_time::{fraction::Fraction, duration::*, Instant, ConversionError};
156 /// # #[derive(Debug)]
157 /// struct Clock;
158 /// impl embedded_time::Clock for Clock {
159 /// type T = u32;
160 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
161 /// // ...
162 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
163 /// }
164 ///
165 /// assert_eq!(
166 /// Instant::<Clock>::new(0).checked_add(Milliseconds(u32::MAX/2)),
167 /// Some(Instant::<Clock>::new(u32::MAX/2))
168 /// );
169 ///
170 /// assert_eq!(
171 /// Instant::<Clock>::new(0).checked_add(Milliseconds(u32::MAX/2 + 1)),
172 /// None
173 /// );
174 /// ```
175 pub fn checked_add<Dur: Duration>(self, duration: Dur) -> Option<Self>
176 where
177 Dur: FixedPoint,
178 Clock::T: TryFrom<Dur::T> + core::ops::Div<Output = Clock::T>,
179 {
180 let add_ticks: Clock::T = duration.into_ticks(Clock::SCALING_FACTOR).ok()?;
181 if add_ticks <= (<Clock::T as num::Bounded>::max_value() / 2.into()) {
182 Some(Self {
183 ticks: self.ticks.wrapping_add(&add_ticks),
184 })
185 } else {
186 None
187 }
188 }
189
190 /// This `Instant` - [`Duration`] = earlier `Instant`
191 ///
192 /// Returns [`None`] if the [`Duration`] is too large
193 ///
194 /// # Examples
195 ///
196 /// ```rust
197 /// # use embedded_time::{fraction::Fraction, duration::*, Instant, ConversionError};
198 /// # #[derive(Debug)]
199 /// struct Clock;
200 /// impl embedded_time::Clock for Clock {
201 /// type T = u32;
202 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
203 /// // ...
204 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
205 /// }
206 ///
207 /// assert_eq!(Instant::<Clock>::new(u32::MAX).checked_sub(Milliseconds(u32::MAX/2)),
208 /// Some(Instant::<Clock>::new(u32::MAX - u32::MAX/2)));
209 ///
210 /// assert_eq!(Instant::<Clock>::new(u32::MAX).checked_sub(Milliseconds(u32::MAX/2 + 1)),
211 /// None);
212 /// ```
213 pub fn checked_sub<Dur: Duration>(self, duration: Dur) -> Option<Self>
214 where
215 Dur: FixedPoint,
216 Clock::T: TryFrom<Dur::T> + core::ops::Div<Output = Clock::T>,
217 {
218 let sub_ticks: Clock::T = duration.into_ticks(Clock::SCALING_FACTOR).ok()?;
219 if sub_ticks <= (<Clock::T as num::Bounded>::max_value() / 2.into()) {
220 Some(Self {
221 ticks: self.ticks.wrapping_sub(&sub_ticks),
222 })
223 } else {
224 None
225 }
226 }
227}
228
229impl<Clock: crate::Clock> Copy for Instant<Clock> {}
230
231impl<Clock: crate::Clock> Clone for Instant<Clock> {
232 fn clone(&self) -> Self {
233 Self { ticks: self.ticks }
234 }
235}
236
237impl<Clock: crate::Clock> PartialEq for Instant<Clock> {
238 fn eq(&self, other: &Self) -> bool {
239 self.ticks == other.ticks
240 }
241}
242
243impl<Clock: crate::Clock> Eq for Instant<Clock> {}
244
245impl<Clock: crate::Clock> PartialOrd for Instant<Clock> {
246 /// Calculates the difference between two `Instant`s resulting in a [`Duration`]
247 ///
248 /// ```rust
249 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
250 /// # #[derive(Debug)]
251 /// struct Clock;
252 /// impl embedded_time::Clock for Clock {
253 /// type T = u32;
254 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
255 /// // ...
256 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
257 /// }
258 ///
259 /// assert!(Instant::<Clock>::new(5) > Instant::<Clock>::new(3));
260 /// assert!(Instant::<Clock>::new(5) == Instant::<Clock>::new(5));
261 /// assert!(Instant::<Clock>::new(u32::MAX) < Instant::<Clock>::new(u32::MIN));
262 /// assert!(Instant::<Clock>::new(5) <= Instant::<Clock>::new(5));
263 /// ```
264 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
265 Some(self.cmp(&other))
266 }
267}
268
269impl<Clock> Ord for Instant<Clock>
270where
271 Clock: crate::Clock,
272 Clock::T: ops::Div<Output = Clock::T>,
273{
274 fn cmp(&self, other: &Self) -> Ordering {
275 if self.ticks == other.ticks {
276 Ordering::Equal
277 } else {
278 self.ticks
279 .wrapping_sub(&other.ticks)
280 .cmp(&(<Clock::T as num::Bounded>::max_value() / 2.into()))
281 .reverse()
282 }
283 }
284}
285
286impl<Clock: crate::Clock, Dur: Duration> ops::Add<Dur> for Instant<Clock>
287where
288 Clock::T: TryFrom<Dur::T>,
289 Dur: FixedPoint,
290{
291 type Output = Self;
292
293 /// Add a [`Duration`] to an `Instant` resulting in a new, later `Instant`
294 ///
295 /// # Examples
296 ///
297 /// ```rust
298 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
299 /// # #[derive(Debug)]
300 /// struct Clock;
301 /// impl embedded_time::Clock for Clock {
302 /// type T = u32;
303 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
304 /// // ...
305 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
306 /// }
307 ///
308 /// assert_eq!(Instant::<Clock>::new(1) + Seconds(3_u32),
309 /// Instant::<Clock>::new(3_001));
310 /// assert_eq!(Instant::<Clock>::new(1) + Milliseconds(700_u32),
311 /// Instant::<Clock>::new(701));
312 /// assert_eq!(Instant::<Clock>::new(1) + Milliseconds(700_u64),
313 /// Instant::<Clock>::new(701));
314 ///
315 /// // maximum duration allowed
316 /// assert_eq!(Instant::<Clock>::new(0) + Milliseconds(i32::MAX as u32),
317 /// Instant::<Clock>::new(u32::MAX/2));
318 /// ```
319 ///
320 /// # Panics
321 ///
322 /// Virtually the same reason the integer operation would panic. Namely, if the
323 /// result overflows the type. Specifically, if the duration is more than half
324 /// the wrap-around period of the clock.
325 ///
326 /// ```rust,should_panic
327 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
328 /// # #[derive(Debug)]
329 /// struct Clock;
330 /// impl embedded_time::Clock for Clock {
331 /// type T = u32;
332 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
333 /// // ...
334 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
335 /// }
336 ///
337 /// Instant::<Clock>::new(0) + Milliseconds(u32::MAX/2 + 1);
338 /// ```
339 fn add(self, rhs: Dur) -> Self::Output {
340 if let Some(v) = self.checked_add(rhs) {
341 v
342 } else {
343 panic!("Add failed")
344 }
345 }
346}
347
348impl<Clock: crate::Clock, Dur: Duration> ops::Sub<Dur> for Instant<Clock>
349where
350 Clock::T: TryFrom<Dur::T>,
351 Dur: FixedPoint,
352{
353 type Output = Self;
354
355 /// Subtract a [`Duration`] from an `Instant` resulting in a new, earlier `Instant`
356 ///
357 /// # Examples
358 ///
359 /// ```rust
360 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
361 /// # #[derive(Debug)]
362 /// struct Clock;
363 /// impl embedded_time::Clock for Clock {
364 /// type T = u32;
365 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
366 /// // ...
367 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
368 /// }
369 ///
370 /// assert_eq!(Instant::<Clock>::new(5_001) - Seconds(3_u32),
371 /// Instant::<Clock>::new(2_001));
372 /// assert_eq!(Instant::<Clock>::new(800) - Milliseconds(700_u32),
373 /// Instant::<Clock>::new(100));
374 /// assert_eq!(Instant::<Clock>::new(5_000) - Milliseconds(700_u64),
375 /// Instant::<Clock>::new(4_300));
376 ///
377 /// // maximum duration allowed
378 /// assert_eq!(Instant::<Clock>::new(u32::MAX) - Milliseconds(i32::MAX as u32),
379 /// Instant::<Clock>::new(u32::MAX/2 + 1));
380 /// ```
381 ///
382 /// # Panics
383 ///
384 /// Virtually the same reason the integer operation would panic. Namely, if the
385 /// result overflows the type. Specifically, if the duration is more than half
386 /// the wrap-around period of the clock.
387 ///
388 /// ```rust,should_panic
389 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
390 /// # #[derive(Debug)]
391 /// struct Clock;
392 /// impl embedded_time::Clock for Clock {
393 /// type T = u32;
394 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
395 /// // ...
396 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
397 /// }
398 ///
399 /// Instant::<Clock>::new(u32::MAX) - Milliseconds(u32::MAX/2 + 1);
400 /// ```
401 fn sub(self, rhs: Dur) -> Self::Output {
402 if let Some(v) = self.checked_sub(rhs) {
403 v
404 } else {
405 panic!("Sub failed")
406 }
407 }
408}
409
410impl<Clock: crate::Clock> ops::Sub<Instant<Clock>> for Instant<Clock> {
411 type Output = duration::Generic<Clock::T>;
412
413 /// Subtract a two `Instant`s resulting in a `Duration`
414 ///
415 /// # Examples
416 ///
417 /// ```rust
418 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
419 /// # #[derive(Debug)]
420 /// struct Clock;
421 /// impl embedded_time::Clock for Clock {
422 /// type T = u32;
423 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
424 /// // ...
425 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
426 /// }
427 ///
428 /// assert_eq!((Instant::<Clock>::new(5_001) - Instant::<Clock>::new(5_000)).integer(), 1);
429 /// ```
430 ///
431 /// # Panics
432 ///
433 /// Virtually the same reason the integer operation would panic. Namely, if the
434 /// result overflows the type. Specifically, if the right hand side `Instant` is
435 /// larger than the left hand side.
436 ///
437 /// ```rust,should_panic
438 /// # use embedded_time::{fraction::Fraction, duration::*, Instant};
439 /// # #[derive(Debug)]
440 /// struct Clock;
441 /// impl embedded_time::Clock for Clock {
442 /// type T = u32;
443 /// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
444 /// // ...
445 /// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
446 /// }
447 ///
448 /// Instant::<Clock>::new(0) - Instant::<Clock>::new(1);
449 /// ```
450 fn sub(self, rhs: Instant<Clock>) -> Self::Output {
451 if let Some(v) = self.checked_duration_since(&rhs) {
452 v
453 } else {
454 panic!("Sub failed")
455 }
456 }
457}
458
459impl<Clock: crate::clock::Clock> Hash for Instant<Clock> {
460 fn hash<H: Hasher>(&self, state: &mut H) {
461 Clock::SCALING_FACTOR.hash(state);
462 self.ticks.hash(state);
463 }
464}
465
466#[cfg(test)]
467mod tests {}