1use crate::helpers::{self, Helpers};
2use crate::Rate;
3use core::cmp::Ordering;
4use core::convert;
5use core::ops;
6
7#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
12#[cfg_attr(
13 feature = "postcard_max_size",
14 derive(postcard::experimental::max_size::MaxSize)
15)]
16#[derive(Clone, Copy, Debug)]
17pub struct Duration<T, const NOM: u32, const DENOM: u32> {
18 pub(crate) ticks: T,
19}
20
21macro_rules! shorthand {
22 ($i:ty, $nom:literal, $denum:literal, $unit:ident, $to_unit:ident, $unital:ident, $unitstr:literal) => {
23 #[doc = concat!("Convert the Duration to an integer number of ", $unitstr, ".")]
24 #[inline]
25 pub const fn $to_unit(&self) -> $i {
26 (Helpers::<$nom, $denum, NOM, DENOM>::LD_TIMES_RN as $i * self.ticks)
27 / Helpers::<$nom, $denum, NOM, DENOM>::RD_TIMES_LN as $i
28 }
29
30 #[doc = concat!("Shorthand for creating a duration which represents ", $unitstr, ".")]
31 #[inline]
32 pub const fn $unit(val: $i) -> Self {
33 Self::from_ticks(
34 (Helpers::<$nom, $denum, NOM, DENOM>::RD_TIMES_LN as $i * val)
35 / Helpers::<$nom, $denum, NOM, DENOM>::LD_TIMES_RN as $i
36 )
37 }
38
39 #[doc = concat!("Shorthand for creating a duration which represents ", $unitstr, " (ceil rounded).")]
40 #[inline]
41 pub const fn $unital(val: $i) -> Self {
42 let mul = Helpers::<$nom, $denum, NOM, DENOM>::RD_TIMES_LN as $i * val;
43 let ld_times_rn = Helpers::<$nom, $denum, NOM, DENOM>::LD_TIMES_RN as $i;
44 Self::from_ticks(if mul % ld_times_rn == 0 {
45 mul / ld_times_rn
46 } else {
47 mul / ld_times_rn + 1
48 })
49 }
50 };
51}
52
53macro_rules! impl_duration_for_integer {
54 ($i:ty) => {
55 impl<const NOM: u32, const DENOM: u32> Duration<$i, NOM, DENOM> {
56 #[doc = concat!("let _d = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(1);")]
61 #[inline]
63 pub const fn from_ticks(ticks: $i) -> Self {
64 helpers::greater_than_0::<NOM>();
65 helpers::greater_than_0::<DENOM>();
66
67 Duration { ticks }
68 }
69
70 #[doc = concat!("let d = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(234);")]
75 #[inline]
79 pub const fn ticks(&self) -> $i {
80 self.ticks
81 }
82
83 #[doc = concat!("let zero = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(0);")]
88 #[doc = concat!("let one = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(1);")]
89 #[inline]
94 pub const fn is_zero(&self) -> bool {
95 self.ticks == 0
96 }
97
98 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(1);")]
103 #[doc = concat!("let d2 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(2);")]
104 #[doc = concat!("let d3 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(", stringify!($i), "::MAX);")]
105 pub const fn checked_add<const O_NOM: u32, const O_DENOM: u32>(
110 self,
111 other: Duration<$i, O_NOM, O_DENOM>,
112 ) -> Option<Self> {
113 if Helpers::<NOM, DENOM, O_NOM, O_DENOM>::SAME_BASE {
114 if let Some(ticks) = self.ticks.checked_add(other.ticks) {
115 Some(Duration::<$i, NOM, DENOM>::from_ticks(ticks))
116 } else {
117 None
118 }
119 } else {
120 if let Some(lh) = other
121 .ticks
122 .checked_mul(Helpers::<NOM, DENOM, O_NOM, O_DENOM>::LD_TIMES_RN as $i)
123 {
124 let ticks = lh / Helpers::<NOM, DENOM, O_NOM, O_DENOM>::RD_TIMES_LN as $i;
125
126 if let Some(ticks) = self.ticks.checked_add(ticks) {
127 Some(Duration::<$i, NOM, DENOM>::from_ticks(ticks))
128 } else {
129 None
130 }
131 } else {
132 None
133 }
134 }
135 }
136
137 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(1);")]
142 #[doc = concat!("let d2 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(2);")]
143 #[doc = concat!("let d3 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(", stringify!($i), "::MAX);")]
144 pub const fn checked_sub<const O_NOM: u32, const O_DENOM: u32>(
149 self,
150 other: Duration<$i, O_NOM, O_DENOM>,
151 ) -> Option<Self> {
152 if Helpers::<NOM, DENOM, O_NOM, O_DENOM>::SAME_BASE {
153 if let Some(ticks) = self.ticks.checked_sub(other.ticks) {
154 Some(Duration::<$i, NOM, DENOM>::from_ticks(ticks))
155 } else {
156 None
157 }
158 } else {
159 if let Some(lh) = other
160 .ticks
161 .checked_mul(Helpers::<NOM, DENOM, O_NOM, O_DENOM>::LD_TIMES_RN as $i)
162 {
163 let ticks = lh / Helpers::<NOM, DENOM, O_NOM, O_DENOM>::RD_TIMES_LN as $i;
164
165 if let Some(ticks) = self.ticks.checked_sub(ticks) {
166 Some(Duration::<$i, NOM, DENOM>::from_ticks(ticks))
167 } else {
168 None
169 }
170 } else {
171 None
172 }
173 }
174 }
175
176 #[doc = concat!("Const `cmp` for ", stringify!($i))]
177 #[inline(always)]
178 const fn _const_cmp(a: $i, b: $i) -> Ordering {
179 if a < b {
180 Ordering::Less
181 } else if a > b {
182 Ordering::Greater
183 } else {
184 Ordering::Equal
185 }
186 }
187
188 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_00>::from_ticks(1);")]
193 #[doc = concat!("let d2 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(1);")]
194 #[inline]
198 pub const fn const_partial_cmp<const R_NOM: u32, const R_DENOM: u32>(
199 self,
200 other: Duration<$i, R_NOM, R_DENOM>
201 ) -> Option<Ordering> {
202 if Helpers::<NOM, DENOM, R_NOM, R_DENOM>::SAME_BASE {
218 Some(Self::_const_cmp(self.ticks, other.ticks))
220 } else {
221 let lh = self
222 .ticks
223 .checked_mul(Helpers::<NOM, DENOM, R_NOM, R_DENOM>::RD_TIMES_LN as $i);
224 let rh = other
225 .ticks
226 .checked_mul(Helpers::<NOM, DENOM, R_NOM, R_DENOM>::LD_TIMES_RN as $i);
227
228 if let (Some(lh), Some(rh)) = (lh, rh) {
229 Some(Self::_const_cmp(lh, rh))
230 } else {
231 None
232 }
233 }
234 }
235
236 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_00>::from_ticks(1);")]
241 #[doc = concat!("let d2 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(10);")]
242 #[inline]
246 pub const fn const_eq<const R_NOM: u32, const R_DENOM: u32>(
247 self,
248 other: Duration<$i, R_NOM, R_DENOM>
249 ) -> bool {
250 if Helpers::<NOM, DENOM, R_NOM, R_DENOM>::SAME_BASE {
251 self.ticks == other.ticks
253 } else {
254 let lh = self
255 .ticks
256 .checked_mul(Helpers::<NOM, DENOM, R_NOM, R_DENOM>::RD_TIMES_LN as $i);
257 let rh = other
258 .ticks
259 .checked_mul(Helpers::<NOM, DENOM, R_NOM, R_DENOM>::LD_TIMES_RN as $i);
260
261 if let (Some(lh), Some(rh)) = (lh, rh) {
262 lh == rh
263 } else {
264 false
265 }
266 }
267 }
268
269 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_00>::from_ticks(1);")]
274 #[doc = concat!("let d2 = Duration::<", stringify!($i), ", 1, 1_000>::const_try_from(d1);")]
275 pub const fn const_try_from<const I_NOM: u32, const I_DENOM: u32>(
279 duration: Duration<$i, I_NOM, I_DENOM>,
280 ) -> Option<Self> {
281 if Helpers::<I_NOM, I_DENOM, NOM, DENOM>::SAME_BASE {
282 Some(Self::from_ticks(duration.ticks))
283 } else {
284 if let Some(lh) = (duration.ticks as u64)
285 .checked_mul(Helpers::<I_NOM, I_DENOM, NOM, DENOM>::RD_TIMES_LN as u64)
286 {
287 let ticks = lh / Helpers::<I_NOM, I_DENOM, NOM, DENOM>::LD_TIMES_RN as u64;
288
289 if ticks <= <$i>::MAX as u64 {
290 Some(Self::from_ticks(ticks as $i))
291 } else {
292 None
293 }
294 } else {
295 None
296 }
297 }
298 }
299
300 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_00>::from_ticks(1);")]
305 #[doc = concat!("let d2: Option<Duration::<", stringify!($i), ", 1, 1_000>> = d1.const_try_into();")]
306 #[inline]
310 pub const fn const_try_into<const O_NOM: u32, const O_DENOM: u32>(
311 self,
312 ) -> Option<Duration<$i, O_NOM, O_DENOM>> {
313 Duration::<$i, O_NOM, O_DENOM>::const_try_from(self)
314 }
315
316 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_000>::from_ticks(2);")]
321 #[doc = concat!("let r1: Option<Rate::<", stringify!($i), ", 1, 1>> = d1.try_into_rate();")]
322 #[inline]
326 pub const fn try_into_rate<const O_NOM: u32, const O_DENOM: u32>(
327 self,
328 ) -> Option<Rate<$i, O_NOM, O_DENOM>> {
329 Rate::<$i, O_NOM, O_DENOM>::try_from_duration(self)
330 }
331
332 #[inline]
334 pub const fn into_rate<const O_NOM: u32, const O_DENOM: u32>(
335 self,
336 ) -> Rate<$i, O_NOM, O_DENOM> {
337 if let Some(v) = self.try_into_rate() {
338 v
339 } else {
340 panic!("Into rate failed, divide-by-zero!");
341 }
342 }
343
344 #[doc = concat!("let r1 = Rate::<", stringify!($i), ", 1, 1>::from_raw(1);")]
349 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 1_000>::try_from_rate(r1);")]
350 #[inline]
354 pub const fn try_from_rate<const I_NOM: u32, const I_DENOM: u32>(
355 rate: Rate<$i, I_NOM, I_DENOM>,
356 ) -> Option<Self> {
357 if rate.raw > 0 {
358 Some(Self::from_ticks(
359 Helpers::<I_NOM, I_DENOM, NOM, DENOM>::RATE_TO_DURATION_NUMERATOR as $i
360 / rate.raw
361 ))
362 } else {
363 None
364 }
365 }
366
367 #[inline]
369 pub const fn from_rate<const I_NOM: u32, const I_DENOM: u32>(
370 rate: Rate<$i, I_NOM, I_DENOM>,
371 ) -> Self {
372 if let Some(v) = Self::try_from_rate(rate) {
373 v
374 } else {
375 panic!("From rate failed, divide-by-zero!");
376 }
377 }
378
379 #[doc = concat!("let d1 = Duration::<", stringify!($i), ", 1, 100>::from_ticks(1);")]
386 #[doc = concat!("let d2: Duration::<", stringify!($i), ", 1, 1_000> = d1.convert();")]
387 #[doc = concat!("const TICKS: ", stringify!($i), "= ", stringify!($i), "::MAX - 10;")]
394 #[doc = concat!("const D1: Duration::<", stringify!($i), ", 1, 100> = Duration::<", stringify!($i), ", 1, 100>::from_ticks(TICKS);")]
395 #[doc = concat!("const D2: Duration::<", stringify!($i), ", 1, 200> = D1.convert();")]
397 #[inline]
398 pub const fn convert<const O_NOM: u32, const O_DENOM: u32>(
399 self,
400 ) -> Duration<$i, O_NOM, O_DENOM> {
401 if let Some(v) = self.const_try_into() {
402 v
403 } else {
404 panic!("Convert failed!");
405 }
406 }
407
408 shorthand!($i, 1, 1_000_000_000, nanos, to_nanos, nanos_at_least, "nanoseconds");
409 shorthand!($i, 1, 1_000_000, micros, to_micros, micros_at_least, "microseconds");
410 shorthand!($i, 1, 1_000, millis, to_millis, millis_at_least, "milliseconds");
411 shorthand!($i, 1, 1, secs, to_secs, secs_at_least, "seconds");
412 shorthand!($i, 60, 1, minutes, to_minutes, minutes_at_least, "minutes");
413 shorthand!($i, 3600, 1, hours, to_hours, hours_at_least, "hours");
414
415 #[inline]
417 #[allow(non_snake_case)]
418 pub const fn Hz(val: $i) -> Self {
419 Self::from_rate(crate::Hertz::<$i>::from_raw(val))
420 }
421
422 #[inline]
424 #[allow(non_snake_case)]
425 pub const fn kHz(val: $i) -> Self {
426 Self::from_rate(crate::Kilohertz::<$i>::from_raw(val))
427 }
428
429 #[inline]
431 #[allow(non_snake_case)]
432 pub const fn MHz(val: $i) -> Self {
433 Self::from_rate(crate::Megahertz::<$i>::from_raw(val))
434 }
435 }
436
437 impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32>
438 PartialOrd<Duration<$i, R_NOM, R_DENOM>> for Duration<$i, L_NOM, L_DENOM>
439 {
440 #[inline]
441 fn partial_cmp(&self, other: &Duration<$i, R_NOM, R_DENOM>) -> Option<Ordering> {
442 self.const_partial_cmp(*other)
443 }
444 }
445
446 impl<const NOM: u32, const DENOM: u32> Ord for Duration<$i, NOM, DENOM> {
447 #[inline]
448 fn cmp(&self, other: &Self) -> Ordering {
449 Self::_const_cmp(self.ticks, other.ticks)
450 }
451 }
452
453 impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32>
454 PartialEq<Duration<$i, R_NOM, R_DENOM>> for Duration<$i, L_NOM, L_DENOM>
455 {
456 #[inline]
457 fn eq(&self, other: &Duration<$i, R_NOM, R_DENOM>) -> bool {
458 self.const_eq(*other)
459 }
460 }
461
462 impl<const NOM: u32, const DENOM: u32> Eq for Duration<$i, NOM, DENOM> {}
463
464 impl<const NOM: u32, const DENOM: u32> ops::Sub<Duration<$i, NOM, DENOM>>
467 for Duration<$i, NOM, DENOM>
468 {
469 type Output = Duration<$i, NOM, DENOM>;
470
471 #[inline]
472 fn sub(self, other: Duration<$i, NOM, DENOM>) -> Self::Output {
473 if let Some(v) = self.checked_sub(other) {
474 v
475 } else {
476 panic!("Sub failed!");
477 }
478 }
479 }
480
481 impl<const NOM: u32, const DENOM: u32> ops::SubAssign<Duration<$i, NOM, DENOM>>
483 for Duration<$i, NOM, DENOM>
484 {
485 #[inline]
486 fn sub_assign(&mut self, other: Self) {
487 *self = *self - other;
488 }
489 }
490
491 impl<const NOM: u32, const DENOM: u32> ops::Add<Duration<$i, NOM, DENOM>>
494 for Duration<$i, NOM, DENOM>
495 {
496 type Output = Duration<$i, NOM, DENOM>;
497
498 #[inline]
499 fn add(self, other: Duration<$i, NOM, DENOM>) -> Self::Output {
500 if let Some(v) = self.checked_add(other) {
501 v
502 } else {
503 panic!("Add failed!");
504 }
505 }
506 }
507
508 impl<const NOM: u32, const DENOM: u32> ops::AddAssign<Duration<$i, NOM, DENOM>>
510 for Duration<$i, NOM, DENOM>
511 {
512 #[inline]
513 fn add_assign(&mut self, other: Self) {
514 *self = *self + other;
515 }
516 }
517
518 impl<const NOM: u32, const DENOM: u32> ops::Mul<Duration<$i, NOM, DENOM>> for u32 {
520 type Output = Duration<$i, NOM, DENOM>;
521
522 #[inline]
523 fn mul(self, mut other: Duration<$i, NOM, DENOM>) -> Self::Output {
524 other.ticks *= self as $i;
525 other
526 }
527 }
528
529 impl<const NOM: u32, const DENOM: u32> ops::Mul<u32> for Duration<$i, NOM, DENOM> {
531 type Output = Duration<$i, NOM, DENOM>;
532
533 #[inline]
534 fn mul(mut self, other: u32) -> Self::Output {
535 self.ticks *= other as $i;
536 self
537 }
538 }
539
540 impl<const NOM: u32, const DENOM: u32> ops::MulAssign<u32>
542 for Duration<$i, NOM, DENOM>
543 {
544 #[inline]
545 fn mul_assign(&mut self, other: u32) {
546 *self = *self * other;
547 }
548 }
549
550 impl<const NOM: u32, const DENOM: u32> ops::Div<u32> for Duration<$i, NOM, DENOM> {
552 type Output = Duration<$i, NOM, DENOM>;
553
554 #[inline]
555 fn div(mut self, other: u32) -> Self::Output {
556 self.ticks /= other as $i;
557 self
558 }
559 }
560
561 impl<const NOM: u32, const DENOM: u32> ops::DivAssign<u32>
563 for Duration<$i, NOM, DENOM>
564 {
565 #[inline]
566 fn div_assign(&mut self, other: u32) {
567 *self = *self / other;
568 }
569 }
570
571 impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32> ops::Div<Duration<$i, R_NOM, R_DENOM>>
573 for Duration<$i, L_NOM, L_DENOM>
574 {
575 type Output = $i;
576
577 #[inline]
578 fn div(self, other: Duration<$i, R_NOM, R_DENOM>) -> Self::Output {
579 let conv: Duration<$i, R_NOM, R_DENOM> = self.convert();
580 conv.ticks / other.ticks
581 }
582 }
583
584 #[cfg(feature = "defmt")]
585 impl<const NOM: u32, const DENOM: u32> defmt::Format for Duration<$i, NOM, DENOM>
586 {
587 fn format(&self, f: defmt::Formatter) {
588 if NOM == 3_600 && DENOM == 1 {
589 defmt::write!(f, "{} h", self.ticks)
590 } else if NOM == 60 && DENOM == 1 {
591 defmt::write!(f, "{} min", self.ticks)
592 } else if NOM == 1 && DENOM == 1 {
593 defmt::write!(f, "{} s", self.ticks)
594 } else if NOM == 1 && DENOM == 1_000 {
595 defmt::write!(f, "{} ms", self.ticks)
596 } else if NOM == 1 && DENOM == 1_000_000 {
597 defmt::write!(f, "{} us", self.ticks)
598 } else if NOM == 1 && DENOM == 1_000_000_000 {
599 defmt::write!(f, "{} ns", self.ticks)
600 } else {
601 defmt::write!(f, "{} ticks @ ({}/{})", self.ticks, NOM, DENOM)
602 }
603 }
604 }
605
606 impl<const NOM: u32, const DENOM: u32> core::fmt::Display for Duration<$i, NOM, DENOM> {
607 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
608 if NOM == 3_600 && DENOM == 1 {
609 write!(f, "{} h", self.ticks)
610 } else if NOM == 60 && DENOM == 1 {
611 write!(f, "{} min", self.ticks)
612 } else if NOM == 1 && DENOM == 1 {
613 write!(f, "{} s", self.ticks)
614 } else if NOM == 1 && DENOM == 1_000 {
615 write!(f, "{} ms", self.ticks)
616 } else if NOM == 1 && DENOM == 1_000_000 {
617 write!(f, "{} us", self.ticks)
618 } else if NOM == 1 && DENOM == 1_000_000_000 {
619 write!(f, "{} ns", self.ticks)
620 } else {
621 write!(f, "{} ticks @ ({}/{})", self.ticks, NOM, DENOM)
622 }
623 }
624 }
625 };
626}
627
628impl_duration_for_integer!(u32);
629impl_duration_for_integer!(u64);
630
631impl<const NOM: u32, const DENOM: u32> From<Duration<u32, NOM, DENOM>>
636 for Duration<u64, NOM, DENOM>
637{
638 #[inline]
639 fn from(val: Duration<u32, NOM, DENOM>) -> Duration<u64, NOM, DENOM> {
640 Duration::<u64, NOM, DENOM>::from_ticks(val.ticks() as u64)
641 }
642}
643
644impl<const NOM: u32, const DENOM: u32> convert::TryFrom<Duration<u64, NOM, DENOM>>
645 for Duration<u32, NOM, DENOM>
646{
647 type Error = ();
648
649 #[inline]
650 fn try_from(val: Duration<u64, NOM, DENOM>) -> Result<Duration<u32, NOM, DENOM>, ()> {
651 Ok(Duration::<u32, NOM, DENOM>::from_ticks(
652 val.ticks().try_into().map_err(|_| ())?,
653 ))
654 }
655}
656
657impl<const NOM: u32, const DENOM: u32> ops::Sub<Duration<u32, NOM, DENOM>>
660 for Duration<u64, NOM, DENOM>
661{
662 type Output = Duration<u64, NOM, DENOM>;
663
664 #[inline]
665 fn sub(self, other: Duration<u32, NOM, DENOM>) -> Self::Output {
666 if let Some(v) =
667 self.checked_sub(Duration::<u64, NOM, DENOM>::from_ticks(other.ticks() as u64))
668 {
669 v
670 } else {
671 panic!("Sub failed!");
672 }
673 }
674}
675
676impl<const NOM: u32, const DENOM: u32> ops::SubAssign<Duration<u32, NOM, DENOM>>
678 for Duration<u64, NOM, DENOM>
679{
680 #[inline]
681 fn sub_assign(&mut self, other: Duration<u32, NOM, DENOM>) {
682 *self = *self - other;
683 }
684}
685
686impl<const NOM: u32, const DENOM: u32> ops::Add<Duration<u32, NOM, DENOM>>
689 for Duration<u64, NOM, DENOM>
690{
691 type Output = Duration<u64, NOM, DENOM>;
692
693 #[inline]
694 fn add(self, other: Duration<u32, NOM, DENOM>) -> Self::Output {
695 if let Some(v) =
696 self.checked_add(Duration::<u64, NOM, DENOM>::from_ticks(other.ticks() as u64))
697 {
698 v
699 } else {
700 panic!("Add failed!");
701 }
702 }
703}
704
705impl<const NOM: u32, const DENOM: u32> ops::AddAssign<Duration<u32, NOM, DENOM>>
707 for Duration<u64, NOM, DENOM>
708{
709 #[inline]
710 fn add_assign(&mut self, other: Duration<u32, NOM, DENOM>) {
711 *self = *self + other;
712 }
713}
714
715impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32>
716 PartialOrd<Duration<u32, R_NOM, R_DENOM>> for Duration<u64, L_NOM, L_DENOM>
717{
718 #[inline]
719 fn partial_cmp(&self, other: &Duration<u32, R_NOM, R_DENOM>) -> Option<Ordering> {
720 self.partial_cmp(&Duration::<u64, R_NOM, R_DENOM>::from_ticks(
721 other.ticks() as u64
722 ))
723 }
724}
725
726impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32>
727 PartialEq<Duration<u32, R_NOM, R_DENOM>> for Duration<u64, L_NOM, L_DENOM>
728{
729 #[inline]
730 fn eq(&self, other: &Duration<u32, R_NOM, R_DENOM>) -> bool {
731 self.eq(&Duration::<u64, R_NOM, R_DENOM>::from_ticks(
732 other.ticks() as u64
733 ))
734 }
735}
736
737impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32>
738 PartialOrd<Duration<u64, R_NOM, R_DENOM>> for Duration<u32, L_NOM, L_DENOM>
739{
740 #[inline]
741 fn partial_cmp(&self, other: &Duration<u64, R_NOM, R_DENOM>) -> Option<Ordering> {
742 Duration::<u64, L_NOM, L_DENOM>::from_ticks(self.ticks as u64).partial_cmp(other)
743 }
744}
745
746impl<const L_NOM: u32, const L_DENOM: u32, const R_NOM: u32, const R_DENOM: u32>
747 PartialEq<Duration<u64, R_NOM, R_DENOM>> for Duration<u32, L_NOM, L_DENOM>
748{
749 #[inline]
750 fn eq(&self, other: &Duration<u64, R_NOM, R_DENOM>) -> bool {
751 Duration::<u64, L_NOM, L_DENOM>::from_ticks(self.ticks as u64).eq(other)
752 }
753}
754
755pub trait ExtU32 {
757 fn nanos<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
759
760 fn micros<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
762
763 fn millis<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
765
766 fn secs<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
768
769 fn minutes<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
771
772 fn hours<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
774}
775
776impl ExtU32 for u32 {
777 #[inline]
778 fn nanos<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
779 Duration::<u32, NOM, DENOM>::nanos(self)
780 }
781
782 #[inline]
783 fn micros<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
784 Duration::<u32, NOM, DENOM>::micros(self)
785 }
786
787 #[inline]
788 fn millis<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
789 Duration::<u32, NOM, DENOM>::millis(self)
790 }
791
792 #[inline]
793 fn secs<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
794 Duration::<u32, NOM, DENOM>::secs(self)
795 }
796
797 #[inline]
798 fn minutes<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
799 Duration::<u32, NOM, DENOM>::minutes(self)
800 }
801
802 #[inline]
803 fn hours<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
804 Duration::<u32, NOM, DENOM>::hours(self)
805 }
806}
807
808pub trait ExtU32Ceil {
810 fn nanos_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
812
813 fn micros_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
815
816 fn millis_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
818
819 fn secs_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
821
822 fn minutes_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
824
825 fn hours_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM>;
827}
828
829impl ExtU32Ceil for u32 {
830 #[inline]
831 fn nanos_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
832 Duration::<u32, NOM, DENOM>::nanos_at_least(self)
833 }
834
835 #[inline]
836 fn micros_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
837 Duration::<u32, NOM, DENOM>::micros_at_least(self)
838 }
839
840 #[inline]
841 fn millis_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
842 Duration::<u32, NOM, DENOM>::millis_at_least(self)
843 }
844
845 #[inline]
846 fn secs_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
847 Duration::<u32, NOM, DENOM>::secs_at_least(self)
848 }
849
850 #[inline]
851 fn minutes_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
852 Duration::<u32, NOM, DENOM>::minutes_at_least(self)
853 }
854
855 #[inline]
856 fn hours_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u32, NOM, DENOM> {
857 Duration::<u32, NOM, DENOM>::hours_at_least(self)
858 }
859}
860
861pub trait ExtU64 {
863 fn nanos<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
865
866 fn micros<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
868
869 fn millis<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
871
872 fn secs<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
874
875 fn minutes<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
877
878 fn hours<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
880}
881
882impl ExtU64 for u64 {
883 #[inline]
884 fn nanos<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
885 Duration::<u64, NOM, DENOM>::nanos(self)
886 }
887
888 #[inline]
889 fn micros<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
890 Duration::<u64, NOM, DENOM>::micros(self)
891 }
892
893 #[inline]
894 fn millis<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
895 Duration::<u64, NOM, DENOM>::millis(self)
896 }
897
898 #[inline]
899 fn secs<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
900 Duration::<u64, NOM, DENOM>::secs(self)
901 }
902
903 #[inline]
904 fn minutes<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
905 Duration::<u64, NOM, DENOM>::minutes(self)
906 }
907
908 #[inline]
909 fn hours<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
910 Duration::<u64, NOM, DENOM>::hours(self)
911 }
912}
913
914pub trait ExtU64Ceil {
916 fn nanos_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
918
919 fn micros_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
921
922 fn millis_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
924
925 fn secs_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
927
928 fn minutes_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
930
931 fn hours_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM>;
933}
934
935impl ExtU64Ceil for u64 {
936 #[inline]
937 fn nanos_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
938 Duration::<u64, NOM, DENOM>::nanos_at_least(self)
939 }
940
941 #[inline]
942 fn micros_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
943 Duration::<u64, NOM, DENOM>::micros_at_least(self)
944 }
945
946 #[inline]
947 fn millis_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
948 Duration::<u64, NOM, DENOM>::millis_at_least(self)
949 }
950
951 #[inline]
952 fn secs_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
953 Duration::<u64, NOM, DENOM>::secs_at_least(self)
954 }
955
956 #[inline]
957 fn minutes_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
958 Duration::<u64, NOM, DENOM>::minutes_at_least(self)
959 }
960
961 #[inline]
962 fn hours_at_least<const NOM: u32, const DENOM: u32>(self) -> Duration<u64, NOM, DENOM> {
963 Duration::<u64, NOM, DENOM>::hours_at_least(self)
964 }
965}