use crate::fab::Aligned;
use crate::fab::Alignment;
use crate::fab::Value;
use crate::fab::ValueAtom;
use serialize::{Deserializable, Serializable, Tagged, tag_enforcement_test};
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Sub;
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Default,
Serializable,
serde::Serialize,
serde::Deserialize,
)]
#[tag = "timestamp"]
pub struct Timestamp(u64);
tag_enforcement_test!(Timestamp);
impl Timestamp {
pub const MAX: Timestamp = Timestamp(u64::MAX);
pub const fn from_secs(s: u64) -> Self {
Timestamp(s)
}
pub fn to_secs(self) -> u64 {
self.0
}
}
impl rand::distributions::Distribution<Timestamp> for rand::distributions::Standard {
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Timestamp {
Timestamp(rng.r#gen())
}
}
impl Aligned for Timestamp {
fn alignment() -> Alignment {
u64::alignment()
}
}
impl From<Timestamp> for ValueAtom {
fn from(timestamp: Timestamp) -> ValueAtom {
ValueAtom::from(timestamp.0).normalize()
}
}
impl From<Timestamp> for Value {
fn from(val: Timestamp) -> Value {
Value(vec![val.into()])
}
}
impl Sub<Self> for Timestamp {
type Output = Duration;
fn sub(self, rhs: Self) -> Self::Output {
Duration(self.0 as i128 - rhs.0 as i128)
}
}
impl AddAssign<Duration> for Timestamp {
fn add_assign(&mut self, rhs: Duration) {
*self = *self + rhs;
}
}
impl Add<Duration> for Timestamp {
type Output = Timestamp;
fn add(self, rhs: Duration) -> Self::Output {
if rhs.0 >= 0 {
let result = self.0.saturating_add(rhs.0 as u64);
Timestamp(result)
} else {
let abs_duration: u64 = rhs
.0
.checked_abs()
.and_then(|val| u64::try_from(val).ok())
.unwrap_or(u64::MAX);
Timestamp(self.0.saturating_sub(abs_duration))
}
}
}
impl Sub<Duration> for Timestamp {
type Output = Timestamp;
fn sub(self, rhs: Duration) -> Self::Output {
if rhs.0 >= 0 {
let result = self.0.saturating_sub(rhs.0 as u64);
Timestamp(result)
} else {
let abs_duration: u64 = rhs
.0
.checked_abs()
.and_then(|val| u64::try_from(val).ok())
.unwrap_or(u64::MAX);
Timestamp(self.0.saturating_add(abs_duration))
}
}
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Serializable,
Hash,
Default,
serde::Serialize,
serde::Deserialize,
)]
#[serde(transparent)]
#[tag = "duration"]
pub struct Duration(i128);
tag_enforcement_test!(Duration);
impl Duration {
pub const fn from_secs(s: i128) -> Self {
Duration(s)
}
pub const fn from_hours(h: i128) -> Self {
Duration::from_secs(h * 60 * 60)
}
pub fn as_seconds(self) -> i128 {
self.0
}
}
impl Add<Duration> for Duration {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Duration(self.0.saturating_add(rhs.0))
}
}
impl Sub<Self> for Duration {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Duration(self.0.saturating_sub(rhs.0))
}
}