Skip to content

Commit e7eba31

Browse files
committed
clock: add clock period modules
1 parent 66b5723 commit e7eba31

File tree

3 files changed

+196
-0
lines changed

3 files changed

+196
-0
lines changed

src/protocol/clock/clockperiod.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use std::num::TryFromIntError;
2+
use std::time::Duration;
3+
4+
use super::clock::{ClockType, StoppedClock, TimeNow, WorkingClock};
5+
use super::period::{PeriodCount, PeriodLength, Periods, SinceUnixEpochPeriods};
6+
7+
pub trait ClockPeriods<T>: Sized
8+
where
9+
T: TimeNow,
10+
{
11+
fn now(length: &PeriodLength) -> Option<Result<SinceUnixEpochPeriods, TryFromIntError>> {
12+
match T::now().as_nanos().checked_div((*length).as_nanos()) {
13+
None => None,
14+
Some(count) => Some(match PeriodCount::try_from(count) {
15+
Err(error) => Err(error),
16+
Ok(count) => Ok(SinceUnixEpochPeriods::new(&length, &count)),
17+
}),
18+
}
19+
}
20+
21+
fn now_add(length: &PeriodLength, add_time: &Duration) -> Option<Result<SinceUnixEpochPeriods, TryFromIntError>> {
22+
match T::add(add_time) {
23+
None => None,
24+
Some(time) => match time.as_nanos().checked_div(length.as_nanos()) {
25+
None => None,
26+
Some(count) => Some(match PeriodCount::try_from(count) {
27+
Err(error) => Err(error),
28+
Ok(count) => Ok(SinceUnixEpochPeriods::new(&length, &count)),
29+
}),
30+
},
31+
}
32+
}
33+
fn now_sub(length: &PeriodLength, sub_time: &Duration) -> Option<Result<SinceUnixEpochPeriods, TryFromIntError>> {
34+
match T::sub(sub_time) {
35+
None => None,
36+
Some(time) => match time.as_nanos().checked_div(length.as_nanos()) {
37+
None => None,
38+
Some(count) => Some(match PeriodCount::try_from(count) {
39+
Err(error) => Err(error),
40+
Ok(count) => Ok(SinceUnixEpochPeriods::new(&length, &count)),
41+
}),
42+
},
43+
}
44+
}
45+
}
46+
47+
#[derive(Debug)]
48+
pub struct PeriodClock<const T: usize> {}
49+
50+
pub type ClockPeriodWorking = PeriodClock<{ ClockType::WorkingClock as usize }>;
51+
52+
pub type StoppedPeriodClock = PeriodClock<{ ClockType::StoppedClock as usize }>;
53+
54+
impl ClockPeriods<WorkingClock> for ClockPeriodWorking {}
55+
56+
impl ClockPeriods<StoppedClock> for StoppedPeriodClock {}
57+
58+
#[cfg(not(test))]
59+
pub type DefaultPeriodClock = ClockPeriodWorking;
60+
61+
#[cfg(test)]
62+
pub type DefaultPeriodClock = StoppedPeriodClock;
63+
64+
#[cfg(test)]
65+
mod tests {
66+
use std::time::Duration;
67+
68+
use crate::protocol::clock::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime};
69+
use crate::protocol::clock::clockperiod::{ClockPeriods, DefaultPeriodClock};
70+
use crate::protocol::clock::period::Period;
71+
72+
#[test]
73+
fn it_should_get_the_current_period() {
74+
assert_eq!(
75+
DefaultPeriodClock::now(&Duration::from_secs(2)).unwrap().unwrap(),
76+
Period::from_sec(2, 0)
77+
);
78+
79+
DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(12387687123));
80+
81+
assert_eq!(
82+
DefaultPeriodClock::now(&Duration::from_secs(2)).unwrap().unwrap(),
83+
Period::from_sec(2, 6193843561)
84+
);
85+
}
86+
}

src/protocol/clock/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
pub mod clock;
2+
pub mod clockperiod;
3+
pub mod period;

src/protocol/clock/period.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use std::num::{IntErrorKind, TryFromIntError};
2+
use std::time::Duration;
3+
4+
pub type PeriodLength = Duration;
5+
pub type PeriodCount = u64;
6+
pub type PeriodTotalTime = Duration;
7+
8+
pub trait Periods: Sized + Default {
9+
fn new(length: &PeriodLength, count: &PeriodCount) -> Self;
10+
11+
fn add_count(&self, add: PeriodCount) -> Result<Self, IntErrorKind>;
12+
fn sub_count(&self, sub: PeriodCount) -> Result<Self, IntErrorKind>;
13+
}
14+
15+
pub trait PeriodsTotals: Periods {
16+
fn total_time(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError>;
17+
fn total_time_end(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError>;
18+
}
19+
20+
#[derive(Debug, Default, Hash, PartialEq)]
21+
pub struct Period {
22+
pub length: PeriodLength,
23+
pub count: PeriodCount,
24+
}
25+
26+
pub type SinceUnixEpochPeriods = Period;
27+
28+
impl Period {
29+
pub const fn from_sec(length: u64, count: u64) -> Self {
30+
Self {
31+
length: Duration::from_secs(length),
32+
count: count,
33+
}
34+
}
35+
}
36+
37+
impl Periods for Period {
38+
fn new(length: &PeriodLength, count: &PeriodCount) -> Self {
39+
Self {
40+
length: *length,
41+
count: *count,
42+
}
43+
}
44+
45+
fn add_count(&self, add: PeriodCount) -> Result<Period, IntErrorKind> {
46+
match self.count.checked_add(add) {
47+
None => Err(IntErrorKind::PosOverflow),
48+
Some(count) => Ok(Self {
49+
length: self.length,
50+
count: count,
51+
}),
52+
}
53+
}
54+
55+
fn sub_count(&self, sub: PeriodCount) -> Result<Period, IntErrorKind> {
56+
match self.count.checked_sub(sub) {
57+
None => Err(IntErrorKind::NegOverflow),
58+
Some(count) => Ok(Self {
59+
length: self.length,
60+
count: count,
61+
}),
62+
}
63+
}
64+
}
65+
66+
impl PeriodsTotals for Period {
67+
fn total_time(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError> {
68+
match u32::try_from(self.count) {
69+
Err(error) => Err(error),
70+
Ok(count) => Ok(self.length.checked_mul(count)),
71+
}
72+
}
73+
74+
fn total_time_end(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError> {
75+
match u32::try_from(self.count) {
76+
Err(e) => Err(e),
77+
Ok(count) => match count.checked_add(1) {
78+
None => Ok(None),
79+
Some(count) => match self.length.checked_mul(count) {
80+
None => Ok(None),
81+
Some(time) => Ok(Some(time)),
82+
},
83+
},
84+
}
85+
}
86+
}
87+
88+
#[cfg(test)]
89+
mod test {
90+
91+
use std::time::Duration;
92+
93+
use crate::protocol::clock::period::{Period, PeriodsTotals};
94+
95+
#[test]
96+
fn it_should_get_the_total_time_of_a_period() {
97+
assert_eq!(Period::default().total_time().unwrap().unwrap(), Duration::ZERO);
98+
99+
assert_eq!(
100+
Period::from_sec(12, 12).total_time().unwrap().unwrap(),
101+
Duration::from_secs(144)
102+
);
103+
assert_eq!(
104+
Period::from_sec(12, 12).total_time_end().unwrap().unwrap(),
105+
Duration::from_secs(156)
106+
);
107+
}
108+
}

0 commit comments

Comments
 (0)