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 {}