//! An instant of time
use crate::{
duration::{self, Duration},
fixed_point::FixedPoint,
};
use core::{
cmp::Ordering,
convert::TryFrom,
hash::{Hash, Hasher},
ops,
};
use num::traits::{WrappingAdd, WrappingSub};
/// Represents an instant of time relative to a specific [`Clock`](clock/trait.Clock.html)
///
/// # Example
///
/// Typically an `Instant` will be obtained from a [`Clock`](clock/trait.Clock.html)
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, Instant, Clock as _};
/// # #[derive(Debug)]
/// # struct SomeClock;
/// # impl embedded_time::Clock for SomeClock {
/// # type T = u32;
/// # const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {Ok(Instant::<Self>::new(23))}
/// # }
/// let some_clock = SomeClock;
/// let some_instant = some_clock.try_now().unwrap();
/// ```
///
/// However, an `Instant` can also be constructed directly. In this case the constructed `Instant`
/// is `23 * SomeClock::SCALING_FACTOR` seconds since the clock's epoch
///
/// ```rust,no_run
/// # use embedded_time::{fraction::Fraction, Instant};
/// # #[derive(Debug)]
/// # struct SomeClock;
/// # impl embedded_time::Clock for SomeClock {
/// # type T = u32;
/// # const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// # }
/// Instant::<SomeClock>::new(23);
/// ```
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Instant<Clock: crate::Clock> {
ticks: Clock::T,
}
impl<Clock: crate::Clock> Instant<Clock> {
/// Construct a new Instant from the provided [`Clock`](clock/trait.Clock.html)
pub fn new(ticks: Clock::T) -> Self {
Self { ticks }
}
/// Returns the amount of time elapsed from another instant to this one as a
/// [`duration::Generic`] or [`None`] if the other instant is later than
/// this one.
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{duration::*, Instant, ConversionError};
/// # use core::convert::TryInto;
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
/// #
/// # let instant1 = Instant::<Clock>::new(3);
/// # let instant2 = Instant::<Clock>::new(5);
///
/// // Given `instant1` at 3 `Clock` ticks
/// // Given `instant2` at 5 `Clock` ticks
/// let generic_duration = instant2.checked_duration_since(&instant1).unwrap();
///
/// // Convert into a _named_ `Duration`
/// let microseconds: Microseconds<u32> = generic_duration.try_into().unwrap();
///
/// assert_eq!(microseconds, Microseconds(2_000_u32));
/// ```
pub fn checked_duration_since(&self, other: &Self) -> Option<duration::Generic<Clock::T>> {
if self >= other {
Some(duration::Generic::new(
self.ticks.wrapping_sub(&other.ticks),
Clock::SCALING_FACTOR,
))
} else {
None
}
}
/// Returns the amount of time elapsed from self until that given instant
/// [`duration::Generic`] or [`None`] if the other instant is later than
/// this one.
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{duration::*, Instant, ConversionError};
/// # use core::convert::TryInto;
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
/// #
/// # let instant1 = Instant::<Clock>::new(3);
/// # let instant2 = Instant::<Clock>::new(5);
///
/// // Given `instant1` at 3 `Clock` ticks
/// // Given `instant2` at 5 `Clock` ticks
/// let generic_duration = instant1.checked_duration_until(&instant2).unwrap();
///
/// // Convert into a _named_ `Duration`
/// let microseconds: Microseconds<u32> = generic_duration.try_into().unwrap();
///
/// assert_eq!(microseconds, Microseconds(2_000_u32));
/// ```
pub fn checked_duration_until(&self, other: &Self) -> Option<duration::Generic<Clock::T>> {
if self <= other {
Some(duration::Generic::new(
other.ticks.wrapping_sub(&self.ticks),
Clock::SCALING_FACTOR,
))
} else {
None
}
}
/// Returns the [`Duration`] (in the provided units) since the beginning of time (the
/// [`Clock`](clock/trait.Clock.html)'s 0)
pub fn duration_since_epoch(&self) -> duration::Generic<Clock::T> {
duration::Generic::new(self.ticks, Clock::SCALING_FACTOR)
}
/// This `Instant` + [`Duration`] = later (future) `Instant`
///
/// Returns [`None`] if the [`Duration`] is too large
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, duration::*, Instant, ConversionError};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// assert_eq!(
/// Instant::<Clock>::new(0).checked_add(Milliseconds(u32::MAX/2)),
/// Some(Instant::<Clock>::new(u32::MAX/2))
/// );
///
/// assert_eq!(
/// Instant::<Clock>::new(0).checked_add(Milliseconds(u32::MAX/2 + 1)),
/// None
/// );
/// ```
pub fn checked_add<Dur: Duration>(self, duration: Dur) -> Option<Self>
where
Dur: FixedPoint,
Clock::T: TryFrom<Dur::T> + core::ops::Div<Output = Clock::T>,
{
let add_ticks: Clock::T = duration.into_ticks(Clock::SCALING_FACTOR).ok()?;
if add_ticks <= (<Clock::T as num::Bounded>::max_value() / 2.into()) {
Some(Self {
ticks: self.ticks.wrapping_add(&add_ticks),
})
} else {
None
}
}
/// This `Instant` - [`Duration`] = earlier `Instant`
///
/// Returns [`None`] if the [`Duration`] is too large
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, duration::*, Instant, ConversionError};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// assert_eq!(Instant::<Clock>::new(u32::MAX).checked_sub(Milliseconds(u32::MAX/2)),
/// Some(Instant::<Clock>::new(u32::MAX - u32::MAX/2)));
///
/// assert_eq!(Instant::<Clock>::new(u32::MAX).checked_sub(Milliseconds(u32::MAX/2 + 1)),
/// None);
/// ```
pub fn checked_sub<Dur: Duration>(self, duration: Dur) -> Option<Self>
where
Dur: FixedPoint,
Clock::T: TryFrom<Dur::T> + core::ops::Div<Output = Clock::T>,
{
let sub_ticks: Clock::T = duration.into_ticks(Clock::SCALING_FACTOR).ok()?;
if sub_ticks <= (<Clock::T as num::Bounded>::max_value() / 2.into()) {
Some(Self {
ticks: self.ticks.wrapping_sub(&sub_ticks),
})
} else {
None
}
}
}
impl<Clock: crate::Clock> Copy for Instant<Clock> {}
impl<Clock: crate::Clock> Clone for Instant<Clock> {
fn clone(&self) -> Self {
Self { ticks: self.ticks }
}
}
impl<Clock: crate::Clock> PartialEq for Instant<Clock> {
fn eq(&self, other: &Self) -> bool {
self.ticks == other.ticks
}
}
impl<Clock: crate::Clock> Eq for Instant<Clock> {}
impl<Clock: crate::Clock> PartialOrd for Instant<Clock> {
/// Calculates the difference between two `Instant`s resulting in a [`Duration`]
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// assert!(Instant::<Clock>::new(5) > Instant::<Clock>::new(3));
/// assert!(Instant::<Clock>::new(5) == Instant::<Clock>::new(5));
/// assert!(Instant::<Clock>::new(u32::MAX) < Instant::<Clock>::new(u32::MIN));
/// assert!(Instant::<Clock>::new(5) <= Instant::<Clock>::new(5));
/// ```
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
impl<Clock> Ord for Instant<Clock>
where
Clock: crate::Clock,
Clock::T: ops::Div<Output = Clock::T>,
{
fn cmp(&self, other: &Self) -> Ordering {
if self.ticks == other.ticks {
Ordering::Equal
} else {
self.ticks
.wrapping_sub(&other.ticks)
.cmp(&(<Clock::T as num::Bounded>::max_value() / 2.into()))
.reverse()
}
}
}
impl<Clock: crate::Clock, Dur: Duration> ops::Add<Dur> for Instant<Clock>
where
Clock::T: TryFrom<Dur::T>,
Dur: FixedPoint,
{
type Output = Self;
/// Add a [`Duration`] to an `Instant` resulting in a new, later `Instant`
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// assert_eq!(Instant::<Clock>::new(1) + Seconds(3_u32),
/// Instant::<Clock>::new(3_001));
/// assert_eq!(Instant::<Clock>::new(1) + Milliseconds(700_u32),
/// Instant::<Clock>::new(701));
/// assert_eq!(Instant::<Clock>::new(1) + Milliseconds(700_u64),
/// Instant::<Clock>::new(701));
///
/// // maximum duration allowed
/// assert_eq!(Instant::<Clock>::new(0) + Milliseconds(i32::MAX as u32),
/// Instant::<Clock>::new(u32::MAX/2));
/// ```
///
/// # Panics
///
/// Virtually the same reason the integer operation would panic. Namely, if the
/// result overflows the type. Specifically, if the duration is more than half
/// the wrap-around period of the clock.
///
/// ```rust,should_panic
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// Instant::<Clock>::new(0) + Milliseconds(u32::MAX/2 + 1);
/// ```
fn add(self, rhs: Dur) -> Self::Output {
if let Some(v) = self.checked_add(rhs) {
v
} else {
panic!("Add failed")
}
}
}
impl<Clock: crate::Clock, Dur: Duration> ops::Sub<Dur> for Instant<Clock>
where
Clock::T: TryFrom<Dur::T>,
Dur: FixedPoint,
{
type Output = Self;
/// Subtract a [`Duration`] from an `Instant` resulting in a new, earlier `Instant`
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// assert_eq!(Instant::<Clock>::new(5_001) - Seconds(3_u32),
/// Instant::<Clock>::new(2_001));
/// assert_eq!(Instant::<Clock>::new(800) - Milliseconds(700_u32),
/// Instant::<Clock>::new(100));
/// assert_eq!(Instant::<Clock>::new(5_000) - Milliseconds(700_u64),
/// Instant::<Clock>::new(4_300));
///
/// // maximum duration allowed
/// assert_eq!(Instant::<Clock>::new(u32::MAX) - Milliseconds(i32::MAX as u32),
/// Instant::<Clock>::new(u32::MAX/2 + 1));
/// ```
///
/// # Panics
///
/// Virtually the same reason the integer operation would panic. Namely, if the
/// result overflows the type. Specifically, if the duration is more than half
/// the wrap-around period of the clock.
///
/// ```rust,should_panic
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// Instant::<Clock>::new(u32::MAX) - Milliseconds(u32::MAX/2 + 1);
/// ```
fn sub(self, rhs: Dur) -> Self::Output {
if let Some(v) = self.checked_sub(rhs) {
v
} else {
panic!("Sub failed")
}
}
}
impl<Clock: crate::Clock> ops::Sub<Instant<Clock>> for Instant<Clock> {
type Output = duration::Generic<Clock::T>;
/// Subtract a two `Instant`s resulting in a `Duration`
///
/// # Examples
///
/// ```rust
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// assert_eq!((Instant::<Clock>::new(5_001) - Instant::<Clock>::new(5_000)).integer(), 1);
/// ```
///
/// # Panics
///
/// Virtually the same reason the integer operation would panic. Namely, if the
/// result overflows the type. Specifically, if the right hand side `Instant` is
/// larger than the left hand side.
///
/// ```rust,should_panic
/// # use embedded_time::{fraction::Fraction, duration::*, Instant};
/// # #[derive(Debug)]
/// struct Clock;
/// impl embedded_time::Clock for Clock {
/// type T = u32;
/// const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000);
/// // ...
/// # fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {unimplemented!()}
/// }
///
/// Instant::<Clock>::new(0) - Instant::<Clock>::new(1);
/// ```
fn sub(self, rhs: Instant<Clock>) -> Self::Output {
if let Some(v) = self.checked_duration_since(&rhs) {
v
} else {
panic!("Sub failed")
}
}
}
impl<Clock: crate::clock::Clock> Hash for Instant<Clock> {
fn hash<H: Hasher>(&self, state: &mut H) {
Clock::SCALING_FACTOR.hash(state);
self.ticks.hash(state);
}
}
#[cfg(test)]
mod tests {}