Skip to content

Commit

Permalink
clock: add clock period modules
Browse files Browse the repository at this point in the history
  • Loading branch information
da2ce7 committed Sep 15, 2022
1 parent 66b5723 commit e7eba31
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/protocol/clock/clockperiod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use std::num::TryFromIntError;
use std::time::Duration;

use super::clock::{ClockType, StoppedClock, TimeNow, WorkingClock};
use super::period::{PeriodCount, PeriodLength, Periods, SinceUnixEpochPeriods};

pub trait ClockPeriods<T>: Sized
where
T: TimeNow,
{
fn now(length: &PeriodLength) -> Option<Result<SinceUnixEpochPeriods, TryFromIntError>> {
match T::now().as_nanos().checked_div((*length).as_nanos()) {
None => None,
Some(count) => Some(match PeriodCount::try_from(count) {
Err(error) => Err(error),
Ok(count) => Ok(SinceUnixEpochPeriods::new(&length, &count)),
}),
}
}

fn now_add(length: &PeriodLength, add_time: &Duration) -> Option<Result<SinceUnixEpochPeriods, TryFromIntError>> {
match T::add(add_time) {
None => None,
Some(time) => match time.as_nanos().checked_div(length.as_nanos()) {
None => None,
Some(count) => Some(match PeriodCount::try_from(count) {
Err(error) => Err(error),
Ok(count) => Ok(SinceUnixEpochPeriods::new(&length, &count)),
}),
},
}
}
fn now_sub(length: &PeriodLength, sub_time: &Duration) -> Option<Result<SinceUnixEpochPeriods, TryFromIntError>> {
match T::sub(sub_time) {
None => None,
Some(time) => match time.as_nanos().checked_div(length.as_nanos()) {
None => None,
Some(count) => Some(match PeriodCount::try_from(count) {
Err(error) => Err(error),
Ok(count) => Ok(SinceUnixEpochPeriods::new(&length, &count)),
}),
},
}
}
}

#[derive(Debug)]
pub struct PeriodClock<const T: usize> {}

pub type ClockPeriodWorking = PeriodClock<{ ClockType::WorkingClock as usize }>;

pub type StoppedPeriodClock = PeriodClock<{ ClockType::StoppedClock as usize }>;

impl ClockPeriods<WorkingClock> for ClockPeriodWorking {}

impl ClockPeriods<StoppedClock> for StoppedPeriodClock {}

#[cfg(not(test))]
pub type DefaultPeriodClock = ClockPeriodWorking;

#[cfg(test)]
pub type DefaultPeriodClock = StoppedPeriodClock;

#[cfg(test)]
mod tests {
use std::time::Duration;

use crate::protocol::clock::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime};
use crate::protocol::clock::clockperiod::{ClockPeriods, DefaultPeriodClock};
use crate::protocol::clock::period::Period;

#[test]
fn it_should_get_the_current_period() {
assert_eq!(
DefaultPeriodClock::now(&Duration::from_secs(2)).unwrap().unwrap(),
Period::from_sec(2, 0)
);

DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(12387687123));

assert_eq!(
DefaultPeriodClock::now(&Duration::from_secs(2)).unwrap().unwrap(),
Period::from_sec(2, 6193843561)
);
}
}
2 changes: 2 additions & 0 deletions src/protocol/clock/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub mod clock;
pub mod clockperiod;
pub mod period;
108 changes: 108 additions & 0 deletions src/protocol/clock/period.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use std::num::{IntErrorKind, TryFromIntError};
use std::time::Duration;

pub type PeriodLength = Duration;
pub type PeriodCount = u64;
pub type PeriodTotalTime = Duration;

pub trait Periods: Sized + Default {
fn new(length: &PeriodLength, count: &PeriodCount) -> Self;

fn add_count(&self, add: PeriodCount) -> Result<Self, IntErrorKind>;
fn sub_count(&self, sub: PeriodCount) -> Result<Self, IntErrorKind>;
}

pub trait PeriodsTotals: Periods {
fn total_time(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError>;
fn total_time_end(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError>;
}

#[derive(Debug, Default, Hash, PartialEq)]
pub struct Period {
pub length: PeriodLength,
pub count: PeriodCount,
}

pub type SinceUnixEpochPeriods = Period;

impl Period {
pub const fn from_sec(length: u64, count: u64) -> Self {
Self {
length: Duration::from_secs(length),
count: count,
}
}
}

impl Periods for Period {
fn new(length: &PeriodLength, count: &PeriodCount) -> Self {
Self {
length: *length,
count: *count,
}
}

fn add_count(&self, add: PeriodCount) -> Result<Period, IntErrorKind> {
match self.count.checked_add(add) {
None => Err(IntErrorKind::PosOverflow),
Some(count) => Ok(Self {
length: self.length,
count: count,
}),
}
}

fn sub_count(&self, sub: PeriodCount) -> Result<Period, IntErrorKind> {
match self.count.checked_sub(sub) {
None => Err(IntErrorKind::NegOverflow),
Some(count) => Ok(Self {
length: self.length,
count: count,
}),
}
}
}

impl PeriodsTotals for Period {
fn total_time(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError> {
match u32::try_from(self.count) {
Err(error) => Err(error),
Ok(count) => Ok(self.length.checked_mul(count)),
}
}

fn total_time_end(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError> {
match u32::try_from(self.count) {
Err(e) => Err(e),
Ok(count) => match count.checked_add(1) {
None => Ok(None),
Some(count) => match self.length.checked_mul(count) {
None => Ok(None),
Some(time) => Ok(Some(time)),
},
},
}
}
}

#[cfg(test)]
mod test {

use std::time::Duration;

use crate::protocol::clock::period::{Period, PeriodsTotals};

#[test]
fn it_should_get_the_total_time_of_a_period() {
assert_eq!(Period::default().total_time().unwrap().unwrap(), Duration::ZERO);

assert_eq!(
Period::from_sec(12, 12).total_time().unwrap().unwrap(),
Duration::from_secs(144)
);
assert_eq!(
Period::from_sec(12, 12).total_time_end().unwrap().unwrap(),
Duration::from_secs(156)
);
}
}

0 comments on commit e7eba31

Please sign in to comment.