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> {
16 type Output;
17 }
18}
19
20macro_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
36const fn multiple_of_value<T, U, Output>(_: T) -> Output
39where
40 T: MultipleOf<U, Output> + Copy,
41{
42 T::VALUE
43}
44
45macro_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 $(#[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 $(#[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}