use std::fmt::{Display, Formatter};
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
use serde::{Deserialize, Serialize};
#[derive(
Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Default, Debug, Serialize, Deserialize,
)]
pub struct TickInstant(pub u64);
#[derive(
Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Default, Debug, Serialize, Deserialize,
)]
pub struct TickDuration {
pub ticks: i64,
}
impl TickInstant {
pub fn new(ticks: u64) -> Self {
TickInstant(ticks)
}
}
impl TickDuration {
pub const ZERO: Self = TickDuration { ticks: 0 };
pub const SINGLE_TICK: Self = TickDuration { ticks: 1 };
pub fn new(ticks: i64) -> TickDuration {
TickDuration { ticks }
}
}
impl Add<TickDuration> for TickInstant {
type Output = TickInstant;
fn add(self, rhs: TickDuration) -> Self::Output {
let mut result = self;
result += rhs;
result
}
}
impl AddAssign<TickDuration> for TickInstant {
fn add_assign(&mut self, rhs: TickDuration) {
self.0 = self
.0
.checked_add_signed(rhs.ticks)
.expect("overflow while adding tick duration to tick instant.");
}
}
impl Sub<TickDuration> for TickInstant {
type Output = TickInstant;
fn sub(self, rhs: TickDuration) -> Self::Output {
let mut result = self;
result -= rhs;
result
}
}
impl SubAssign<TickDuration> for TickInstant {
fn sub_assign(&mut self, rhs: TickDuration) {
if rhs.ticks.is_positive() {
self.0 = self
.0
.checked_sub(rhs.ticks.unsigned_abs())
.expect("overflow while subtracting duration from instant.");
} else if rhs.ticks.is_negative() {
self.0 = self
.0
.checked_add(rhs.ticks.unsigned_abs())
.expect("overflow while subtracting duration from instant.")
}
}
}
impl Sub for TickInstant {
type Output = TickDuration;
fn sub(self, rhs: TickInstant) -> Self::Output {
let minuend = (self.0 as i64).wrapping_add(i64::MIN);
let subtrahend = (rhs.0 as i64).wrapping_add(i64::MIN);
let (difference, overflowed) = minuend.overflowing_sub(subtrahend);
if overflowed {
panic!("overflow while subtracting two TickInstants.")
}
TickDuration { ticks: difference }
}
}
impl Add for TickDuration {
type Output = TickDuration;
fn add(self, rhs: Self) -> Self::Output {
let mut result = self;
result += rhs;
result
}
}
impl AddAssign for TickDuration {
fn add_assign(&mut self, rhs: Self) {
self.ticks = self
.ticks
.checked_add(rhs.ticks)
.expect("Overflow occurred while adding TickDuration instances.")
}
}
impl Sub for TickDuration {
type Output = TickDuration;
fn sub(self, rhs: Self) -> Self::Output {
let mut result = self;
result -= rhs;
result
}
}
impl SubAssign for TickDuration {
fn sub_assign(&mut self, rhs: Self) {
self.ticks = self
.ticks
.checked_sub(rhs.ticks)
.expect("Overflow occurred while subtracting TickDuration instances.");
}
}
impl Neg for TickDuration {
type Output = TickDuration;
fn neg(self) -> Self::Output {
TickDuration {
ticks: self
.ticks
.checked_neg()
.expect("Overflow while negating duration."),
}
}
}
impl Display for TickInstant {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}]", self.0)
}
}
impl Display for TickDuration {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<{}>", self.ticks)
}
}
impl From<TickInstant> for u64 {
fn from(value: TickInstant) -> Self {
value.0
}
}
impl From<TickDuration> for i64 {
fn from(value: TickDuration) -> Self {
value.ticks
}
}