time_core/
convert.rs

1//! Conversion between units of time.
2
3use self::sealed::{DefaultOutput, MultipleOf};
4
5mod sealed {
6    /// A trait for defining the ratio of two units of time.
7    ///
8    /// This trait is used to implement the `per` method on the various structs.
9    #[diagnostic::on_unimplemented(message = "`{Self}` is not an integer multiple of `{T}`")]
10    pub trait MultipleOf<T, Output> {
11        /// The number of one unit of time in the other.
12        const VALUE: Output;
13    }
14
15    pub trait DefaultOutput<T> {
16        type Output;
17    }
18}
19
20/// Given the list of types, stringify them as a list.
21macro_rules! stringify_outputs {
22    (@inner $first:ty) => {
23        concat!("or `", stringify!($first), "`")
24    };
25    (@inner $first:ty, $($t:ty),+) => {
26        concat!(stringify_outputs!($first), ", ", stringify_outputs!(@inner $($t),+))
27    };
28    ($first:ty) => {
29        concat!("`", stringify!($first), "`")
30    };
31    ($($t:ty),+) => {
32        stringify_outputs!(@inner $($t),+)
33    };
34}
35
36// Split this out to a separate function to permit naming `T` while also using `impl Trait` as a
37// parameter in the public API.`
38const fn multiple_of_value<T, U, Output>(_: T) -> Output
39where
40    T: MultipleOf<U, Output> + Copy,
41{
42    T::VALUE
43}
44
45/// Declare and implement `Per` for all relevant types. Identity implementations are automatic.
46macro_rules! impl_per {
47    ($($t:ident ($str:literal) per {$(
48        $larger:ident : [$default_output:ty]
49
50        $($int_output:ty)|+ = $int_value:expr;
51        $($float_output:ty)|+ = $float_value:expr;
52    )+})*) => {$(
53        #[doc = concat!("A unit of time representing exactly one ", $str, ".")]
54        #[derive(Debug, Clone, Copy)]
55        pub struct $t;
56
57        impl $t {
58            #[doc = concat!("Obtain the number of times `", stringify!($t), "` can fit into `T`.")]
59            #[doc = concat!("If `T` is smaller than `", stringify!($t), "`, the code will fail to")]
60            /// compile. The return type is the smallest unsigned integer type that can represent
61            /// the value.
62            ///
63            /// Valid calls:
64            ///
65            $(#[doc = concat!(
66                "  - `", stringify!($t), "::per(", stringify!($larger), ")` (returns `",
67                stringify!($default_output), "`)"
68            )])+
69            #[inline]
70            pub const fn per<T>(_larger: T) -> <T as DefaultOutput<Self>>::Output
71            where
72                T: MultipleOf<Self, T::Output> + DefaultOutput<Self> + Copy,
73            {
74                T::VALUE
75            }
76
77            #[doc = concat!("Obtain the number of times `", stringify!($t), "` can fit into `T`.")]
78            #[doc = concat!("If `T` is smaller than `", stringify!($t), "`, the code will fail to")]
79            /// compile. The return type is any primitive numeric type that can represent the value.
80            ///
81            /// Valid calls:
82            ///
83            $(#[doc = concat!(
84                "  - `", stringify!($t), "::per(", stringify!($larger), ")` (returns ",
85                stringify_outputs!($($int_output),+ , $($float_output),+), ")"
86            )])+
87            #[inline]
88            pub const fn per_t<Output>(larger: impl MultipleOf<Self, Output> + Copy) -> Output {
89                multiple_of_value(larger)
90            }
91        }
92
93        $(
94            $(impl MultipleOf<$t, $int_output> for $larger {
95                const VALUE: $int_output = $int_value;
96            })+
97
98            $(impl MultipleOf<$t, $float_output> for $larger {
99                const VALUE: $float_output = $float_value;
100            })+
101
102            impl DefaultOutput<$larger> for $t {
103                type Output = $default_output;
104            }
105        )+
106    )*};
107}
108
109impl_per! {
110    Nanosecond ("nanosecond") per {
111        Nanosecond: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
112        Microsecond: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_000; f32|f64 = 1_000.;
113        Millisecond: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 1_000_000; f32|f64 = 1_000_000.;
114        Second:
115            [u32] u32|u64|u128|usize|i32|i64|i128|isize = 1_000_000_000; f32|f64 = 1_000_000_000.;
116        Minute: [u64] u64|u128|i64|i128 = 60_000_000_000; f32|f64 = 60_000_000_000.;
117        Hour: [u64] u64|u128|i64|i128 = 3_600_000_000_000; f32|f64 = 3_600_000_000_000.;
118        Day: [u64] u64|u128|i64|i128 = 86_400_000_000_000; f32|f64 = 86_400_000_000_000.;
119        Week: [u64] u64|u128|i64|i128 = 604_800_000_000_000; f32|f64 = 604_800_000_000_000.;
120    }
121    Microsecond ("microsecond") per {
122        Microsecond: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
123        Millisecond: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_000; f32|f64 = 1_000.;
124        Second: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 1_000_000; f32|f64 = 1_000_000.;
125        Minute: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 60_000_000; f32|f64 = 60_000_000.;
126        Hour: [u32] u32|u64|u128|i64|i128 = 3_600_000_000; f32|f64 = 3_600_000_000.;
127        Day: [u64] u64|u128|i64|i128 = 86_400_000_000; f32|f64 = 86_400_000_000.;
128        Week: [u64] u64|u128|i64|i128 = 604_800_000_000; f32|f64 = 604_800_000_000.;
129    }
130    Millisecond ("millisecond") per {
131        Millisecond: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
132        Second: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_000; f32|f64 = 1_000.;
133        Minute: [u16] u16|u32|u64|u128|usize|i32|i64|i128|isize = 60_000; f32|f64 = 60_000.;
134        Hour: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 3_600_000; f32|f64 = 3_600_000.;
135        Day: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 86_400_000; f32|f64 = 86_400_000.;
136        Week: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 604_800_000; f32|f64 = 604_800_000.;
137    }
138    Second ("second") per {
139        Second: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
140        Minute: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 60; f32|f64 = 60.;
141        Hour: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 3_600; f32|f64 = 3_600.;
142        Day: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 86_400; f32|f64 = 86_400.;
143        Week: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 604_800; f32|f64 = 604_800.;
144    }
145    Minute ("minute") per {
146        Minute: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
147        Hour: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 60; f32|f64 = 60.;
148        Day: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_440; f32|f64 = 1_440.;
149        Week: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 10_080; f32|f64 = 10_080.;
150    }
151    Hour ("hour") per {
152        Hour: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
153        Day: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 24; f32|f64 = 24.;
154        Week: [u8] u8|u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 168; f32|f64 = 168.;
155    }
156    Day ("day") per {
157        Day: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
158        Week: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 7; f32|f64 = 7.;
159    }
160    Week ("week") per {
161        Week: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
162    }
163}