1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::frequency::units::Hertz;
use crate::{duration::units::*, Period};
use core::{convert::TryFrom, convert::TryInto, fmt};

/// Create time-based values from primitive and core numeric types.
///
/// This trait can be imported with `use embedded-time::prelude::*`.
///
/// # Examples
/// Basic construction of time-based values.
/// ```rust
/// # use embedded_time::{prelude::*, units::*};
/// assert_eq!(5.nanoseconds(), Nanoseconds(5));
/// assert_eq!(5.microseconds(), Microseconds(5));
/// assert_eq!(5.milliseconds(), Milliseconds(5));
/// assert_eq!(5.seconds(), Seconds(5));
/// assert_eq!(5.minutes(), Minutes(5));
/// assert_eq!(5.hours(), Hours(5));
/// assert_eq!(5.hertz(), Hertz(5));
/// ```
///
/// Signed integers work as well!
/// ```rust
/// # use embedded_time::{prelude::*, units::*};
/// assert_eq!((-5).nanoseconds(), Nanoseconds(-5));
/// assert_eq!((-5).microseconds(), Microseconds(-5));
/// assert_eq!((-5).milliseconds(), Milliseconds(-5));
/// assert_eq!((-5).seconds(), Seconds(-5));
/// assert_eq!((-5).minutes(), Minutes(-5));
/// assert_eq!((-5).hours(), Hours(-5));
/// ```
pub trait TimeInt:
    Copy
    + num::Integer
    + num::Bounded
    + num::traits::WrappingAdd
    + num::traits::WrappingSub
    + num::CheckedMul
    + num::CheckedDiv
    + From<i32>
    + TryInto<i32>
    + TryFrom<i64>
    + Into<i64>
    + fmt::Display
    + fmt::Debug
{
    fn nanoseconds(self) -> Nanoseconds<Self>;
    fn microseconds(self) -> Microseconds<Self>;
    fn milliseconds(self) -> Milliseconds<Self>;
    fn seconds(self) -> Seconds<Self>;
    fn minutes(self) -> Minutes<Self>;
    fn hours(self) -> Hours<Self>;

    fn hertz(self) -> Hertz<Self>;

    /// ```rust
    /// # use embedded_time::{Period, prelude::*};
    /// assert_eq!(8_i32.checked_mul_period(&Period::new(1,2)), Some(4_i32));
    ///
    /// // the result is not rounded, but truncated
    /// assert_eq!(8_i32.checked_mul_period(&Period::new(1,3)), Some(2_i32));
    /// ```
    fn checked_mul_period(&self, period: &Period) -> Option<Self> {
        Some(<Self as num::CheckedDiv>::checked_div(
            &<Self as num::CheckedMul>::checked_mul(&self, &(*period.numerator()).into())?,
            &(*period.denominator()).into(),
        )?)
    }

    /// ```rust
    /// # use embedded_time::{Period, prelude::*};
    /// assert_eq!(8_i32.checked_div_period(&Period::new(1,2)), Some(16_i32));
    /// assert_eq!(8_i32.checked_div_period(&Period::new(3,2)), Some(5_i32));
    /// ```
    fn checked_div_period(&self, period: &Period) -> Option<Self> {
        Some(<Self as num::CheckedDiv>::checked_div(
            &<Self as num::CheckedMul>::checked_mul(&self, &(*period.denominator()).into())?,
            &(*period.numerator()).into(),
        )?)
    }
}

macro_rules! impl_time_ints {
    ($($type:ty),* $(,)?) => {
        $(
            impl TimeInt for $type {
                #[inline(always)]
                fn nanoseconds(self) -> Nanoseconds<$type> {
                    Nanoseconds(self)
                }

                #[inline(always)]
                fn microseconds(self) -> Microseconds<$type> {
                    Microseconds(self)
                }

                #[inline(always)]
                fn milliseconds(self) -> Milliseconds<$type> {
                    Milliseconds(self)
                }

                #[inline(always)]
                fn seconds(self) -> Seconds<$type> {
                    Seconds(self)
                }

                #[inline(always)]
                fn minutes(self) -> Minutes<$type> {
                    Minutes(self)
                }

                #[inline(always)]
                fn hours(self) -> Hours<$type> {
                    Hours(self)
                }

                #[inline(always)]
                fn hertz(self) -> Hertz<$type> {
                    Hertz(self)
                }
            }
        )*
    };
}

impl_time_ints![i32, i64];