use core::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct Duration {
micros: i64,
}
impl Duration {
pub const ZERO: Duration = Duration { micros: 0 };
pub const MAX: Duration = Duration { micros: i64::MAX };
pub const MIN: Duration = Duration { micros: i64::MIN };
#[inline]
pub const fn from_micros(micros: i64) -> Self {
Self { micros }
}
#[inline]
pub fn from_millis(millis: i64) -> Self {
Self::from_micros(
millis
.checked_mul(1000)
.expect("Overflow converting from milliseconds to Duration"),
)
}
#[inline]
pub fn from_seconds(seconds: i64) -> Self {
Self::from_micros(
seconds
.checked_mul(1_000_000)
.expect("Overflow converting from seconds to Duration"),
)
}
#[inline]
pub const fn micros(&self) -> i64 {
self.micros
}
#[inline]
pub const fn millis(&self) -> i64 {
self.micros / 1000
}
#[inline]
pub const fn seconds(&self) -> i64 {
self.micros / 1_000_000
}
#[inline]
pub const fn subsec_micros(&self) -> i32 {
(self.micros % 1_000_000) as i32
}
#[inline]
pub fn checked_add(self, rhs: Self) -> Option<Self> {
self.micros.checked_add(rhs.micros).map(Self::from_micros)
}
#[inline]
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
self.micros.checked_sub(rhs.micros).map(Self::from_micros)
}
#[inline]
pub fn saturating_add(self, rhs: Self) -> Self {
Self::from_micros(self.micros.saturating_add(rhs.micros))
}
#[inline]
pub fn saturating_sub(self, rhs: Self) -> Self {
Self::from_micros(self.micros.saturating_sub(rhs.micros))
}
}
impl Add for Duration {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.checked_add(rhs)
.expect("Overflow when adding durations")
}
}
impl AddAssign for Duration {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl Sub for Duration {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.checked_sub(rhs)
.expect("Underflow when subtracting durations")
}
}
impl SubAssign for Duration {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn from_millis() {
let _ = Duration::from_millis(i64::MAX);
}
#[test]
#[should_panic]
fn from_seconds() {
let _ = Duration::from_seconds(i64::MAX);
}
#[test]
#[should_panic]
fn add() {
let lhs = Duration::MAX;
let rhs = Duration::from_micros(1);
let _ = lhs + rhs;
}
#[test]
#[should_panic]
fn add_assign() {
let mut lhs = Duration::MAX;
let rhs = Duration::from_micros(1);
lhs += rhs;
}
#[test]
#[should_panic]
fn sub() {
let lhs = Duration::MIN;
let rhs = Duration::from_micros(1);
let _ = lhs - rhs;
}
#[test]
#[should_panic]
fn sub_assign() {
let mut lhs = Duration::MIN;
let rhs = Duration::from_micros(1);
lhs -= rhs;
}
}