timer revelations
This commit is contained in:
parent
6a12d213e8
commit
852bbe6dad
193
src/timer.rs
193
src/timer.rs
@ -1,18 +1,26 @@
|
|||||||
use crate::integer::{Time,Ratio64};
|
use crate::integer::{Time,Ratio64};
|
||||||
|
|
||||||
//this could be about half as long if I only had
|
pub struct Paused{}
|
||||||
//scaled timers and just used a scale of 1
|
pub struct Unpaused{}
|
||||||
//but I thought the concept of a timer that could
|
|
||||||
//only be paused and not scaled was cool
|
|
||||||
|
|
||||||
trait TimerState:Copy{
|
pub trait PauseState{
|
||||||
fn get_time(&self,time:Time)->Time;
|
const IS_PAUSED:bool;
|
||||||
fn set_time(&mut self,time:Time,new_time:Time);
|
}
|
||||||
fn get_offset(&self)->Time;
|
impl PauseState for Paused{
|
||||||
fn set_offset(&mut self,offset:Time);
|
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{
|
pub struct Scaled{
|
||||||
scale:Ratio64,
|
scale:Ratio64,
|
||||||
offset:Time,
|
offset:Time,
|
||||||
@ -36,29 +44,12 @@ impl Scaled{
|
|||||||
self.set_time(time,new_time);
|
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 trait TimerState{
|
||||||
pub struct Realtime{
|
fn get_time(&self,time:Time)->Time;
|
||||||
offset:Time,
|
fn set_time(&mut self,time:Time,new_time:Time);
|
||||||
}
|
fn get_offset(&self)->Time;
|
||||||
impl Realtime{
|
fn set_offset(&mut self,offset:Time);
|
||||||
const fn identity()->Self{
|
|
||||||
Self{offset:Time::ZERO}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl TimerState for Realtime{
|
impl TimerState for Realtime{
|
||||||
fn get_time(&self,time:Time)->Time{
|
fn get_time(&self,time:Time)->Time{
|
||||||
@ -74,28 +65,33 @@ impl TimerState for Realtime{
|
|||||||
self.offset=offset;
|
self.offset=offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl TimerState for Scaled{
|
||||||
#[derive(Clone,Debug)]
|
fn get_time(&self,time:Time)->Time{
|
||||||
pub struct Timer<T>{
|
self.scale(time)+self.offset
|
||||||
state:T,
|
}
|
||||||
paused:bool,
|
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<Realtime>{
|
pub struct TimerFixed<T:TimerState,P:PauseState>{
|
||||||
pub fn realtime(time:Time,new_time:Time)->Self{
|
state:T,
|
||||||
let mut timer=Self{
|
paused:P,
|
||||||
state:Realtime::identity(),
|
}
|
||||||
paused:false,
|
|
||||||
};
|
pub enum Timer{
|
||||||
timer.set_time(time,new_time);
|
Paused(TimerFixed<Realtime,Paused>),
|
||||||
timer
|
Unpaused(TimerFixed<Realtime,Unpaused>),
|
||||||
}
|
}
|
||||||
pub fn realtime_paused(offset:Time)->Self{
|
pub enum TimerScaled{
|
||||||
Self{
|
Paused(TimerFixed<Scaled,Paused>),
|
||||||
state:Realtime{offset},
|
Unpaused(TimerFixed<Scaled,Unpaused>),
|
||||||
paused:true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -110,100 +106,45 @@ impl std::fmt::Display for Error{
|
|||||||
}
|
}
|
||||||
impl std::error::Error for Error{}
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
impl Timer<Scaled>{
|
impl<T:TimerState,P:PauseState> TimerFixed<T,P>{
|
||||||
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<T:TimerState> Timer<T>{
|
|
||||||
pub fn time(&self,time:Time)->Time{
|
pub fn time(&self,time:Time)->Time{
|
||||||
match self.paused{
|
match P::IS_PAUSED{
|
||||||
true=>self.state.get_offset(),
|
true=>self.state.get_offset(),
|
||||||
false=>self.state.get_time(time),
|
false=>self.state.get_time(time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set_time(&mut self,time:Time,new_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),
|
true=>self.state.set_offset(new_time),
|
||||||
false=>self.state.set_time(time,new_time),
|
false=>self.state.set_time(time,new_time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn pause(&mut self,time:Time)->Result<(),Error>{
|
pub fn pause(self,time:Time)->Result<TimerFixed<T,Paused>,Error>{
|
||||||
match self.paused{
|
match P::IS_PAUSED{
|
||||||
true=>Err(Error::AlreadyPaused),
|
true=>Err(Error::AlreadyPaused),
|
||||||
false=>{
|
false=>{
|
||||||
let new_time=self.time(time);
|
let new_time=self.time(time);
|
||||||
self.state.set_offset(new_time);
|
let mut timer=TimerFixed{
|
||||||
self.paused=true;
|
state:self.state,
|
||||||
Ok(())
|
paused:Paused{},
|
||||||
|
};
|
||||||
|
timer.set_time(time,new_time);
|
||||||
|
Ok(timer)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn unpause(&mut self,time:Time)->Result<(),Error>{
|
pub fn unpause(self,time:Time)->Result<TimerFixed<T,Unpaused>,Error>{
|
||||||
match self.paused{
|
match P::IS_PAUSED{
|
||||||
true=>{
|
true=>{
|
||||||
let new_time=self.time(time);
|
let new_time=self.time(time);
|
||||||
self.state.set_time(time,new_time);
|
let mut timer=TimerFixed{
|
||||||
self.paused=false;
|
state:self.state,
|
||||||
Ok(())
|
paused:Unpaused{},
|
||||||
|
};
|
||||||
|
timer.set_time(time,new_time);
|
||||||
|
Ok(timer)
|
||||||
},
|
},
|
||||||
false=>Err(Error::AlreadyUnpaused),
|
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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user