statime/time/
interval.rs

1#[allow(unused_imports)]
2use crate::float_polyfill::FloatPolyfill;
3
4/// A log2 representation of seconds used to describe the pacing of events in
5/// PTP
6#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
7pub struct Interval(i8);
8
9impl core::fmt::Debug for Interval {
10    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11        f.debug_struct("Interval")
12            .field("seconds", &self.as_f64())
13            .field("log_base_2", &self.0)
14            .finish()
15    }
16}
17
18impl Interval {
19    /// An Interval of one second
20    pub const ONE_SECOND: Self = Self(0);
21
22    /// An Interval of two seconds
23    pub const TWO_SECONDS: Self = Self(1);
24
25    /// Construct an [`Interval`] from log2 seconds.
26    ///
27    /// # Example
28    /// ```
29    /// # use std::time::Duration;
30    /// # use statime::time::Interval;
31    /// assert_eq!(Interval::from_log_2(2).as_core_duration(), Duration::from_secs(4));
32    /// assert_eq!(Interval::from_log_2(-2).as_core_duration(), Duration::from_millis(250));
33    /// ```
34    pub const fn from_log_2(log_2: i8) -> Self {
35        Self(log_2)
36    }
37
38    /// Turn `self` into a number of seconds as [`f64`]
39    ///
40    /// # Example
41    /// ```
42    /// # use statime::time::Interval;
43    /// assert_eq!(Interval::from_log_2(1).seconds(), 2.0);
44    /// assert_eq!(Interval::from_log_2(-1).seconds(), 0.5);
45    /// ```
46    pub fn seconds(self) -> f64 {
47        self.as_f64()
48    }
49
50    /// Turn this into a [`statime::time::Duration`](`crate::time::Duration`)
51    ///
52    /// # Example
53    /// ```
54    /// # use statime::time::{Duration, Interval};
55    /// assert_eq!(Interval::from_log_2(3).as_duration(), Duration::from_secs(8));
56    /// assert_eq!(Interval::from_log_2(-3).as_duration(), Duration::from_millis(125));
57    /// ```
58    pub fn as_duration(self) -> super::Duration {
59        super::Duration::from_interval(self)
60    }
61
62    /// Turn this into a [`core::time::Duration`]
63    ///
64    /// # Example
65    /// ```
66    /// # use statime::time::{Interval};
67    /// use core::time::Duration;
68    /// assert_eq!(Interval::from_log_2(3).as_core_duration(), Duration::from_secs(8));
69    /// assert_eq!(Interval::from_log_2(-3).as_core_duration(), Duration::from_millis(125));
70    /// ```
71    pub fn as_core_duration(self) -> core::time::Duration {
72        core::time::Duration::from_secs_f64(self.seconds())
73    }
74
75    fn as_f64(self) -> f64 {
76        2.0f64.powi(self.0 as i32)
77    }
78
79    /// Get the log2 of the numbers of seconds of this [`Interval`]
80    ///
81    /// # Example
82    /// ```
83    /// # use statime::time::{Interval};
84    /// use core::time::Duration;
85    /// assert_eq!(Interval::ONE_SECOND.as_log_2(), 0);
86    /// assert_eq!(Interval::TWO_SECONDS.as_log_2(), 1);
87    /// ```
88    pub fn as_log_2(self) -> i8 {
89        self.0
90    }
91}
92
93impl From<i8> for Interval {
94    fn from(value: i8) -> Self {
95        Self::from_log_2(value)
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn two() {
105        assert_eq!(Interval::TWO_SECONDS.as_f64(), 2.0f64)
106    }
107}