| 1 | use std::time::Instant as StdInstant; |
| 2 | |
| 3 | use crate::Duration; |
| 4 | |
| 5 | /// Sealed trait to prevent downstream implementations. |
| 6 | mod sealed { |
| 7 | /// A trait that cannot be implemented by downstream users. |
| 8 | pub trait Sealed: Sized {} |
| 9 | impl Sealed for std::time::Instant {} |
| 10 | } |
| 11 | |
| 12 | /// An extension trait for [`std::time::Instant`] that adds methods for |
| 13 | /// [`time::Duration`](Duration)s. |
| 14 | pub trait InstantExt: sealed::Sealed { |
| 15 | /// # Panics |
| 16 | /// |
| 17 | /// This function may panic if the resulting point in time cannot be represented by the |
| 18 | /// underlying data structure. See [`InstantExt::checked_add_signed`] for a non-panicking |
| 19 | /// version. |
| 20 | fn add_signed(self, duration: Duration) -> Self { |
| 21 | self.checked_add_signed(duration) |
| 22 | .expect("overflow when adding duration to instant" ) |
| 23 | } |
| 24 | |
| 25 | /// # Panics |
| 26 | /// |
| 27 | /// This function may panic if the resulting point in time cannot be represented by the |
| 28 | /// underlying data structure. See [`InstantExt::checked_sub_signed`] for a non-panicking |
| 29 | /// version. |
| 30 | fn sub_signed(self, duration: Duration) -> Self { |
| 31 | self.checked_sub_signed(duration) |
| 32 | .expect("overflow when subtracting duration from instant" ) |
| 33 | } |
| 34 | |
| 35 | /// Returns `Some(t)` where `t` is the time `self.checked_add_signed(duration)` if `t` can be |
| 36 | /// represented as `Instant` (which means it's inside the bounds of the underlying data |
| 37 | /// structure), `None` otherwise. |
| 38 | fn checked_add_signed(&self, duration: Duration) -> Option<Self>; |
| 39 | |
| 40 | /// Returns `Some(t)` where `t` is the time `self.checked_sub_signed(duration)` if `t` can be |
| 41 | /// represented as `Instant` (which means it's inside the bounds of the underlying data |
| 42 | /// structure), `None` otherwise. |
| 43 | fn checked_sub_signed(&self, duration: Duration) -> Option<Self>; |
| 44 | |
| 45 | /// Returns the amount of time elapsed from another instant to this one. This will be negative |
| 46 | /// if `earlier` is later than `self`. |
| 47 | /// |
| 48 | /// # Example |
| 49 | /// |
| 50 | /// ```rust |
| 51 | /// # use std::thread::sleep; |
| 52 | /// # use std::time::{Duration, Instant}; |
| 53 | /// # use time::ext::InstantExt; |
| 54 | /// let now = Instant::now(); |
| 55 | /// sleep(Duration::new(1, 0)); |
| 56 | /// let new_now = Instant::now(); |
| 57 | /// println!("{:?}" , new_now.signed_duration_since(now)); // positive |
| 58 | /// println!("{:?}" , now.signed_duration_since(new_now)); // negative |
| 59 | /// ``` |
| 60 | fn signed_duration_since(&self, earlier: Self) -> Duration; |
| 61 | } |
| 62 | |
| 63 | impl InstantExt for StdInstant { |
| 64 | fn checked_add_signed(&self, duration: Duration) -> Option<Self> { |
| 65 | if duration.is_positive() { |
| 66 | self.checked_add(duration.unsigned_abs()) |
| 67 | } else if duration.is_negative() { |
| 68 | #[allow (clippy::unchecked_duration_subtraction)] |
| 69 | self.checked_sub(duration.unsigned_abs()) |
| 70 | } else { |
| 71 | debug_assert!(duration.is_zero()); |
| 72 | Some(*self) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | fn checked_sub_signed(&self, duration: Duration) -> Option<Self> { |
| 77 | if duration.is_positive() { |
| 78 | #[allow (clippy::unchecked_duration_subtraction)] |
| 79 | self.checked_sub(duration.unsigned_abs()) |
| 80 | } else if duration.is_negative() { |
| 81 | self.checked_add(duration.unsigned_abs()) |
| 82 | } else { |
| 83 | debug_assert!(duration.is_zero()); |
| 84 | Some(*self) |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | fn signed_duration_since(&self, earlier: Self) -> Duration { |
| 89 | if *self > earlier { |
| 90 | self.saturating_duration_since(earlier) |
| 91 | .try_into() |
| 92 | .unwrap_or(Duration::MAX) |
| 93 | } else { |
| 94 | earlier |
| 95 | .saturating_duration_since(*self) |
| 96 | .try_into() |
| 97 | .map_or(Duration::MIN, |d: Duration| -d) |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |