#[cfg(test)]
mod test;
use std::{
cmp::Ordering,
ops::{Add, AddAssign, Sub, SubAssign},
};
use super::ClockId;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ClockTime {
pub clock: ClockId,
pub ticks: u64,
pub fraction: f64,
}
impl ClockTime {
pub fn from_ticks_u64(clock: impl Into<ClockId>, ticks: u64) -> Self {
Self {
clock: clock.into(),
ticks,
fraction: 0.0,
}
}
pub fn from_ticks_f64(clock: impl Into<ClockId>, ticks: f64) -> Self {
Self {
clock: clock.into(),
ticks: ticks as u64,
fraction: ticks.fract(),
}
}
}
impl Add<u64> for ClockTime {
type Output = ClockTime;
fn add(self, ticks: u64) -> Self::Output {
Self {
clock: self.clock,
ticks: self.ticks + ticks,
fraction: self.fraction,
}
}
}
impl AddAssign<u64> for ClockTime {
fn add_assign(&mut self, ticks: u64) {
self.ticks += ticks;
}
}
impl Add<f64> for ClockTime {
type Output = ClockTime;
fn add(self, ticks: f64) -> Self::Output {
debug_assert!(
ticks.is_finite(),
"Cannot add a non-finite amount to ClockTime: {ticks:?}"
);
if ticks.is_sign_negative() {
return self.sub(-ticks);
}
let fraction = (self.fraction + ticks).fract();
let ticks = self.ticks + (self.fraction + ticks).trunc() as u64;
Self {
clock: self.clock,
ticks,
fraction,
}
}
}
impl AddAssign<f64> for ClockTime {
fn add_assign(&mut self, ticks: f64) {
*self = *self + ticks;
}
}
impl Sub<u64> for ClockTime {
type Output = ClockTime;
fn sub(self, ticks: u64) -> Self::Output {
Self {
clock: self.clock,
ticks: self.ticks - ticks,
fraction: self.fraction,
}
}
}
impl SubAssign<u64> for ClockTime {
fn sub_assign(&mut self, ticks: u64) {
self.ticks -= ticks;
}
}
impl Sub<f64> for ClockTime {
type Output = ClockTime;
fn sub(self, ticks: f64) -> Self::Output {
debug_assert!(
ticks.is_finite(),
"Cannot subtract a non-finite amount from ClockTime: {ticks:?}"
);
if ticks.is_sign_negative() {
return self.add(-ticks);
}
let fraction = ((self.fraction - ticks).fract() + 1.0) % 1.0;
let ticks = self
.ticks
.saturating_sub((ticks - self.fraction).ceil() as u64);
Self {
clock: self.clock,
ticks,
fraction,
}
}
}
impl SubAssign<f64> for ClockTime {
fn sub_assign(&mut self, ticks: f64) {
*self = *self - ticks;
}
}
impl PartialOrd for ClockTime {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.clock != other.clock {
return None;
}
match self.ticks.cmp(&other.ticks) {
Ordering::Equal => self.fraction.partial_cmp(&other.fraction),
ordering => Some(ordering),
}
}
}