1use self::sealed::{DefaultOutput, MultipleOf};
4
5mod sealed {
6 #[diagnostic::on_unimplemented(message = "`{Self}` is not an integer multiple of `{T}`")]
10 pub trait MultipleOf<T, Output> {
11 const VALUE: Output;
13 }
14
15 pub trait DefaultOutput<T> {
17 type Output;
19 }
20}
21
22macro_rules! stringify_outputs {
24 (@inner $first:ty) => {
25 concat!("or `", stringify!($first), "`")
26 };
27 (@inner $first:ty, $($t:ty),+) => {
28 concat!(stringify_outputs!($first), ", ", stringify_outputs!(@inner $($t),+))
29 };
30 ($first:ty) => {
31 concat!("`", stringify!($first), "`")
32 };
33 ($($t:ty),+) => {
34 stringify_outputs!(@inner $($t),+)
35 };
36}
37
38const fn multiple_of_value<T, U, Output>(_: T) -> Output
41where
42 T: MultipleOf<U, Output> + Copy,
43{
44 T::VALUE
45}
46
47macro_rules! impl_per {
49 ($($t:ident ($str:literal) per {$(
50 $larger:ident : [$default_output:ty]
51
52 $($int_output:ty)|+ = $int_value:expr;
53 $($float_output:ty)|+ = $float_value:expr;
54 )+})*) => {$(
55 #[doc = concat!("A unit of time representing exactly one ", $str, ".")]
56 #[derive(Debug, Clone, Copy)]
57 pub struct $t;
58
59 impl $t {
60 #[doc = concat!("Obtain the number of times `", stringify!($t), "` can fit into `T`.")]
61 #[doc = concat!("If `T` is smaller than `", stringify!($t), "`, the code will fail to")]
62 $(#[doc = concat!(
68 " - `", stringify!($t), "::per(", stringify!($larger), ")` (returns `",
69 stringify!($default_output), "`)"
70 )])+
71 #[inline]
72 pub const fn per<T>(_larger: T) -> <T as DefaultOutput<Self>>::Output
73 where
74 T: MultipleOf<Self, T::Output> + DefaultOutput<Self> + Copy,
75 {
76 T::VALUE
77 }
78
79 #[doc = concat!("Obtain the number of times `", stringify!($t), "` can fit into `T`.")]
80 #[doc = concat!("If `T` is smaller than `", stringify!($t), "`, the code will fail to")]
81 $(#[doc = concat!(
86 " - `", stringify!($t), "::per(", stringify!($larger), ")` (returns ",
87 stringify_outputs!($($int_output),+ , $($float_output),+), ")"
88 )])+
89 #[inline]
90 pub const fn per_t<Output>(larger: impl MultipleOf<Self, Output> + Copy) -> Output {
91 multiple_of_value(larger)
92 }
93 }
94
95 $(
96 $(impl MultipleOf<$t, $int_output> for $larger {
97 const VALUE: $int_output = $int_value;
98 })+
99
100 $(impl MultipleOf<$t, $float_output> for $larger {
101 const VALUE: $float_output = $float_value;
102 })+
103
104 impl DefaultOutput<$t> for $larger {
105 type Output = $default_output;
106 }
107 )+
108 )*};
109}
110
111impl_per! {
112 Nanosecond ("nanosecond") per {
113 Nanosecond: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
114 Microsecond: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_000; f32|f64 = 1_000.;
115 Millisecond: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 1_000_000; f32|f64 = 1_000_000.;
116 Second:
117 [u32] u32|u64|u128|usize|i32|i64|i128|isize = 1_000_000_000; f32|f64 = 1_000_000_000.;
118 Minute: [u64] u64|u128|i64|i128 = 60_000_000_000; f32|f64 = 60_000_000_000.;
119 Hour: [u64] u64|u128|i64|i128 = 3_600_000_000_000; f32|f64 = 3_600_000_000_000.;
120 Day: [u64] u64|u128|i64|i128 = 86_400_000_000_000; f32|f64 = 86_400_000_000_000.;
121 Week: [u64] u64|u128|i64|i128 = 604_800_000_000_000; f32|f64 = 604_800_000_000_000.;
122 }
123 Microsecond ("microsecond") per {
124 Microsecond: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
125 Millisecond: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_000; f32|f64 = 1_000.;
126 Second: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 1_000_000; f32|f64 = 1_000_000.;
127 Minute: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 60_000_000; f32|f64 = 60_000_000.;
128 Hour: [u32] u32|u64|u128|i64|i128 = 3_600_000_000; f32|f64 = 3_600_000_000.;
129 Day: [u64] u64|u128|i64|i128 = 86_400_000_000; f32|f64 = 86_400_000_000.;
130 Week: [u64] u64|u128|i64|i128 = 604_800_000_000; f32|f64 = 604_800_000_000.;
131 }
132 Millisecond ("millisecond") per {
133 Millisecond: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
134 Second: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_000; f32|f64 = 1_000.;
135 Minute: [u16] u16|u32|u64|u128|usize|i32|i64|i128|isize = 60_000; f32|f64 = 60_000.;
136 Hour: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 3_600_000; f32|f64 = 3_600_000.;
137 Day: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 86_400_000; f32|f64 = 86_400_000.;
138 Week: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 604_800_000; f32|f64 = 604_800_000.;
139 }
140 Second ("second") per {
141 Second: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
142 Minute: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 60; f32|f64 = 60.;
143 Hour: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 3_600; f32|f64 = 3_600.;
144 Day: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 86_400; f32|f64 = 86_400.;
145 Week: [u32] u32|u64|u128|usize|i32|i64|i128|isize = 604_800; f32|f64 = 604_800.;
146 }
147 Minute ("minute") per {
148 Minute: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
149 Hour: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 60; f32|f64 = 60.;
150 Day: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 1_440; f32|f64 = 1_440.;
151 Week: [u16] u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 10_080; f32|f64 = 10_080.;
152 }
153 Hour ("hour") per {
154 Hour: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
155 Day: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 24; f32|f64 = 24.;
156 Week: [u8] u8|u16|u32|u64|u128|usize|i16|i32|i64|i128|isize = 168; f32|f64 = 168.;
157 }
158 Day ("day") per {
159 Day: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
160 Week: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 7; f32|f64 = 7.;
161 }
162 Week ("week") per {
163 Week: [u8] u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize = 1; f32|f64 = 1.;
164 }
165}