diff --git a/src/timer.rs b/src/timer.rs index 4158124..fd34dac 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,18 +1,26 @@ use crate::integer::{Time,Ratio64}; -//this could be about half as long if I only had -//scaled timers and just used a scale of 1 -//but I thought the concept of a timer that could -//only be paused and not scaled was cool +pub struct Paused{} +pub struct Unpaused{} -trait TimerState:Copy{ - fn get_time(&self,time:Time)->Time; - fn set_time(&mut self,time:Time,new_time:Time); - fn get_offset(&self)->Time; - fn set_offset(&mut self,offset:Time); +pub trait PauseState{ + const IS_PAUSED:bool; +} +impl PauseState for Paused{ + const IS_PAUSED:bool=true; +} +impl PauseState for Unpaused{ + const IS_PAUSED:bool=false; } -#[derive(Clone,Copy,Debug)] +pub struct Realtime{ + offset:Time, +} +impl Realtime{ + const fn identity()->Self{ + Self{offset:Time::ZERO} + } +} pub struct Scaled{ scale:Ratio64, offset:Time, @@ -36,29 +44,12 @@ impl Scaled{ self.set_time(time,new_time); } } -impl TimerState for Scaled{ - fn get_time(&self,time:Time)->Time{ - self.scale(time)+self.offset - } - fn set_time(&mut self,time:Time,new_time:Time){ - self.offset=new_time-self.scale(time); - } - fn get_offset(&self)->Time{ - self.offset - } - fn set_offset(&mut self,offset:Time){ - self.offset=offset; - } -} -#[derive(Clone,Copy,Debug)] -pub struct Realtime{ - offset:Time, -} -impl Realtime{ - const fn identity()->Self{ - Self{offset:Time::ZERO} - } +pub trait TimerState{ + fn get_time(&self,time:Time)->Time; + fn set_time(&mut self,time:Time,new_time:Time); + fn get_offset(&self)->Time; + fn set_offset(&mut self,offset:Time); } impl TimerState for Realtime{ fn get_time(&self,time:Time)->Time{ @@ -74,28 +65,33 @@ impl TimerState for Realtime{ self.offset=offset; } } - -#[derive(Clone,Debug)] -pub struct Timer{ - state:T, - paused:bool, +impl TimerState for Scaled{ + fn get_time(&self,time:Time)->Time{ + self.scale(time)+self.offset + } + fn set_time(&mut self,time:Time,new_time:Time){ + self.offset=new_time-self.scale(time); + } + fn get_offset(&self)->Time{ + self.offset + } + fn set_offset(&mut self,offset:Time){ + self.offset=offset; + } } -impl Timer{ - pub fn realtime(time:Time,new_time:Time)->Self{ - let mut timer=Self{ - state:Realtime::identity(), - paused:false, - }; - timer.set_time(time,new_time); - timer - } - pub fn realtime_paused(offset:Time)->Self{ - Self{ - state:Realtime{offset}, - paused:true, - } - } +pub struct TimerFixed{ + state:T, + paused:P, +} + +pub enum Timer{ + Paused(TimerFixed), + Unpaused(TimerFixed), +} +pub enum TimerScaled{ + Paused(TimerFixed), + Unpaused(TimerFixed), } #[derive(Debug)] @@ -110,100 +106,45 @@ impl std::fmt::Display for Error{ } impl std::error::Error for Error{} -impl Timer{ - pub fn new(time:Time,new_time:Time,scale:Ratio64,paused:bool)->Self{ - let mut timer=Self{ - state:Scaled::with_scale(scale), - paused, - }; - timer.set_time(time,new_time); - timer - } - pub fn scaled(time:Time,new_time:Time,scale:Ratio64)->Self{ - let mut timer=Self{ - state:Scaled::with_scale(scale), - paused:false, - }; - timer.set_time(time,new_time); - timer - } - pub fn scaled_paused(time:Time,new_time:Time,scale:Ratio64)->Self{ - let mut timer=Self{ - state:Scaled::with_scale(scale), - paused:true, - }; - timer.set_time(time,new_time); - timer - } - pub const fn get_scale(&self)->Ratio64{ - self.state.get_scale() - } - pub fn set_scale(&mut self,time:Time,new_scale:Ratio64){ - self.state.set_scale(time,new_scale) - } -} - -impl Timer{ +impl TimerFixed{ pub fn time(&self,time:Time)->Time{ - match self.paused{ + match P::IS_PAUSED{ true=>self.state.get_offset(), false=>self.state.get_time(time), } } pub fn set_time(&mut self,time:Time,new_time:Time){ - match self.paused{ + match P::IS_PAUSED{ true=>self.state.set_offset(new_time), false=>self.state.set_time(time,new_time), } } - pub fn pause(&mut self,time:Time)->Result<(),Error>{ - match self.paused{ + pub fn pause(self,time:Time)->Result,Error>{ + match P::IS_PAUSED{ true=>Err(Error::AlreadyPaused), false=>{ let new_time=self.time(time); - self.state.set_offset(new_time); - self.paused=true; - Ok(()) + let mut timer=TimerFixed{ + state:self.state, + paused:Paused{}, + }; + timer.set_time(time,new_time); + Ok(timer) }, } } - pub fn unpause(&mut self,time:Time)->Result<(),Error>{ - match self.paused{ + pub fn unpause(self,time:Time)->Result,Error>{ + match P::IS_PAUSED{ true=>{ let new_time=self.time(time); - self.state.set_time(time,new_time); - self.paused=false; - Ok(()) + let mut timer=TimerFixed{ + state:self.state, + paused:Unpaused{}, + }; + timer.set_time(time,new_time); + Ok(timer) }, false=>Err(Error::AlreadyUnpaused), } } } -#[cfg(test)] -mod test{ - use super::{Time,Timer,Error}; - macro_rules! sec { - ($s: expr) => { - Time::from_secs($s) - }; - } - #[test] - fn test_timer()->Result<(),Error>{ - //create a paused timer that reads 0s - let mut timer=Timer::realtime_paused(sec!(0)); - //the paused timer at 1 second should read 0s - assert_eq!(timer.time(sec!(1)),sec!(0)); - - //unpause it after one second - timer.unpause(sec!(1))?; - //the timer at 6 seconds should read 5s - assert_eq!(timer.time(sec!(6)),sec!(5)); - - //pause the timer after 11 seconds - timer.pause(sec!(11))?; - //the paused timer at 20 seconds should read 10s - assert_eq!(timer.time(sec!(20)),sec!(10)); - - Ok(()) - } -}