364 lines
8.6 KiB
Rust
Raw Normal View History

2024-07-31 12:10:35 -07:00
use crate::integer::{Time,Ratio64};
#[derive(Clone,Copy,Debug)]
pub struct Paused;
#[derive(Clone,Copy,Debug)]
pub struct Unpaused;
pub trait PauseState:Copy+std::fmt::Debug{
const IS_PAUSED:bool;
fn new()->Self;
}
impl PauseState for Paused{
const IS_PAUSED:bool=true;
fn new()->Self{
Self
}
}
impl PauseState for Unpaused{
const IS_PAUSED:bool=false;
fn new()->Self{
Self
}
}
2025-01-07 21:46:30 -08:00
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
enum Inner{}
type InnerTime=Time<Inner>;
2024-07-31 12:10:35 -07:00
#[derive(Clone,Copy,Debug)]
2025-01-07 21:46:30 -08:00
pub struct Realtime<In,Out>{
offset:InnerTime,
_in:core::marker::PhantomData<In>,
_out:core::marker::PhantomData<Out>,
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
impl<In,Out> Realtime<In,Out>{
pub const fn new(offset:InnerTime)->Self{
Self{
offset,
_in:core::marker::PhantomData,
_out:core::marker::PhantomData,
}
2024-07-31 12:10:35 -07:00
}
}
#[derive(Clone,Copy,Debug)]
2025-01-07 21:46:30 -08:00
pub struct Scaled<In,Out>{
2024-07-31 12:10:35 -07:00
scale:Ratio64,
2025-01-07 21:46:30 -08:00
offset:InnerTime,
_in:core::marker::PhantomData<In>,
_out:core::marker::PhantomData<Out>,
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
impl<In,Out> Scaled<In,Out>
where Time<In>:Copy,
{
pub const fn new(scale:Ratio64,offset:InnerTime)->Self{
Self{
scale,
offset,
_in:core::marker::PhantomData,
_out:core::marker::PhantomData,
}
2024-07-31 12:10:35 -07:00
}
const fn with_scale(scale:Ratio64)->Self{
2025-01-07 21:46:30 -08:00
Self::new(scale,InnerTime::ZERO)
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
const fn scale(&self,time:Time<In>)->InnerTime{
InnerTime::raw(self.scale.mul_int(time.get()))
2024-07-31 12:10:35 -07:00
}
const fn get_scale(&self)->Ratio64{
self.scale
}
2025-01-07 21:46:30 -08:00
fn set_scale(&mut self,time:Time<In>,new_scale:Ratio64){
2024-07-31 12:10:35 -07:00
let new_time=self.get_time(time);
self.scale=new_scale;
self.set_time(time,new_time);
}
}
2025-01-07 21:46:30 -08:00
pub trait TimerState{
type In;
type Out;
2024-07-31 12:10:35 -07:00
fn identity()->Self;
2025-01-07 21:46:30 -08:00
fn get_time(&self,time:Time<Self::In>)->Time<Self::Out>;
fn set_time(&mut self,time:Time<Self::In>,new_time:Time<Self::Out>);
fn get_offset(&self)->InnerTime;
fn set_offset(&mut self,offset:InnerTime);
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
impl<In,Out> TimerState for Realtime<In,Out>{
type In=In;
type Out=Out;
2024-07-31 12:10:35 -07:00
fn identity()->Self{
2025-01-07 21:46:30 -08:00
Self::new(InnerTime::ZERO)
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
fn get_time(&self,time:Time<In>)->Time<Out>{
time.coerce()+self.offset.coerce()
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
fn set_time(&mut self,time:Time<In>,new_time:Time<Out>){
self.offset=new_time.coerce()-time.coerce();
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
fn get_offset(&self)->InnerTime{
2024-07-31 12:10:35 -07:00
self.offset
}
2025-01-07 21:46:30 -08:00
fn set_offset(&mut self,offset:InnerTime){
2024-07-31 12:10:35 -07:00
self.offset=offset;
}
}
2025-01-07 21:46:30 -08:00
impl<In,Out> TimerState for Scaled<In,Out>
where Time<In>:Copy,
{
type In=In;
type Out=Out;
2024-07-31 12:10:35 -07:00
fn identity()->Self{
2025-01-07 21:46:30 -08:00
Self::new(Ratio64::ONE,InnerTime::ZERO)
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
fn get_time(&self,time:Time<In>)->Time<Out>{
(self.scale(time)+self.offset).coerce()
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
fn set_time(&mut self,time:Time<In>,new_time:Time<Out>){
self.offset=new_time.coerce()-self.scale(time);
2024-07-31 12:10:35 -07:00
}
2025-01-07 21:46:30 -08:00
fn get_offset(&self)->InnerTime{
2024-07-31 12:10:35 -07:00
self.offset
}
2025-01-07 21:46:30 -08:00
fn set_offset(&mut self,offset:InnerTime){
2024-07-31 12:10:35 -07:00
self.offset=offset;
}
}
#[derive(Clone,Copy,Debug)]
pub struct TimerFixed<T:TimerState,P:PauseState>{
state:T,
_paused:P,
}
//scaled timer methods are generic across PauseState
2025-01-07 21:46:30 -08:00
impl<P:PauseState,In,Out> TimerFixed<Scaled<In,Out>,P>
where Time<In>:Copy,
{
pub fn scaled(time:Time<In>,new_time:Time<Out>,scale:Ratio64)->Self{
2024-07-31 12:10:35 -07:00
let mut timer=Self{
state:Scaled::with_scale(scale),
_paused:P::new(),
};
timer.set_time(time,new_time);
timer
}
pub const fn get_scale(&self)->Ratio64{
self.state.get_scale()
}
2025-01-07 21:46:30 -08:00
pub fn set_scale(&mut self,time:Time<In>,new_scale:Ratio64){
2024-07-31 12:10:35 -07:00
self.state.set_scale(time,new_scale)
}
}
//pause and unpause is generic across TimerState
2025-01-07 21:46:30 -08:00
impl<T:TimerState> TimerFixed<T,Paused>
where Time<T::In>:Copy,
{
pub fn into_unpaused(self,time:Time<T::In>)->TimerFixed<T,Unpaused>{
2024-07-31 12:10:35 -07:00
let new_time=self.time(time);
let mut timer=TimerFixed{
state:self.state,
_paused:Unpaused,
};
timer.set_time(time,new_time);
timer
}
}
2025-01-07 21:46:30 -08:00
impl<T:TimerState> TimerFixed<T,Unpaused>
where Time<T::In>:Copy,
{
pub fn into_paused(self,time:Time<T::In>)->TimerFixed<T,Paused>{
2024-07-31 12:10:35 -07:00
let new_time=self.time(time);
let mut timer=TimerFixed{
state:self.state,
_paused:Paused,
};
timer.set_time(time,new_time);
timer
}
}
//the new constructor and time queries are generic across both
impl<T:TimerState,P:PauseState> TimerFixed<T,P>{
2025-01-07 21:46:30 -08:00
pub fn new(time:Time<T::In>,new_time:Time<T::Out>)->Self{
2024-07-31 12:10:35 -07:00
let mut timer=Self{
state:T::identity(),
_paused:P::new(),
};
timer.set_time(time,new_time);
timer
}
pub fn from_state(state:T)->Self{
Self{
state,
_paused:P::new(),
}
}
pub fn into_state(self)->T{
self.state
}
2025-01-07 21:46:30 -08:00
pub fn time(&self,time:Time<T::In>)->Time<T::Out>{
2024-07-31 12:10:35 -07:00
match P::IS_PAUSED{
2025-01-07 21:46:30 -08:00
true=>self.state.get_offset().coerce(),
2024-07-31 12:10:35 -07:00
false=>self.state.get_time(time),
}
}
2025-01-07 21:46:30 -08:00
pub fn set_time(&mut self,time:Time<T::In>,new_time:Time<T::Out>){
2024-07-31 12:10:35 -07:00
match P::IS_PAUSED{
2025-01-07 21:46:30 -08:00
true=>self.state.set_offset(new_time.coerce()),
2024-07-31 12:10:35 -07:00
false=>self.state.set_time(time,new_time),
}
}
}
#[derive(Debug)]
pub enum Error{
AlreadyPaused,
AlreadyUnpaused,
}
impl std::fmt::Display for Error{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for Error{}
//wrapper type which holds type state internally
#[derive(Clone,Debug)]
pub enum Timer<T:TimerState>{
Paused(TimerFixed<T,Paused>),
Unpaused(TimerFixed<T,Unpaused>),
}
2025-01-07 21:46:30 -08:00
impl<T:TimerState> Timer<T>
where
T:Copy,
Time<T::In>:Copy,
{
2024-07-31 12:10:35 -07:00
pub fn from_state(state:T,paused:bool)->Self{
match paused{
true=>Self::Paused(TimerFixed::from_state(state)),
false=>Self::Unpaused(TimerFixed::from_state(state)),
}
}
pub fn into_state(self)->(T,bool){
match self{
Self::Paused(timer)=>(timer.into_state(),true),
Self::Unpaused(timer)=>(timer.into_state(),false),
}
}
2025-01-07 21:46:30 -08:00
pub fn paused(time:Time<T::In>,new_time:Time<T::Out>)->Self{
2024-07-31 12:10:35 -07:00
Self::Paused(TimerFixed::new(time,new_time))
}
2025-01-07 21:46:30 -08:00
pub fn unpaused(time:Time<T::In>,new_time:Time<T::Out>)->Self{
2024-07-31 12:10:35 -07:00
Self::Unpaused(TimerFixed::new(time,new_time))
}
2025-01-07 21:46:30 -08:00
pub fn time(&self,time:Time<T::In>)->Time<T::Out>{
2024-07-31 12:10:35 -07:00
match self{
Self::Paused(timer)=>timer.time(time),
Self::Unpaused(timer)=>timer.time(time),
}
}
2025-01-07 21:46:30 -08:00
pub fn set_time(&mut self,time:Time<T::In>,new_time:Time<T::Out>){
2024-07-31 12:10:35 -07:00
match self{
Self::Paused(timer)=>timer.set_time(time,new_time),
Self::Unpaused(timer)=>timer.set_time(time,new_time),
}
}
2025-01-07 21:46:30 -08:00
pub fn pause(&mut self,time:Time<T::In>)->Result<(),Error>{
2024-07-31 12:10:35 -07:00
*self=match *self{
Self::Paused(_)=>return Err(Error::AlreadyPaused),
Self::Unpaused(timer)=>Self::Paused(timer.into_paused(time)),
};
Ok(())
}
2025-01-07 21:46:30 -08:00
pub fn unpause(&mut self,time:Time<T::In>)->Result<(),Error>{
2024-07-31 12:10:35 -07:00
*self=match *self{
Self::Paused(timer)=>Self::Unpaused(timer.into_unpaused(time)),
Self::Unpaused(_)=>return Err(Error::AlreadyUnpaused),
};
Ok(())
}
2024-08-02 10:35:29 -07:00
pub fn is_paused(&self)->bool{
match self{
Self::Paused(_)=>true,
Self::Unpaused(_)=>false,
}
}
2025-01-07 21:46:30 -08:00
pub fn set_paused(&mut self,time:Time<T::In>,paused:bool)->Result<(),Error>{
2024-08-02 10:35:29 -07:00
match paused{
true=>self.pause(time),
false=>self.unpause(time),
}
}
}
//scaled timer methods are generic across PauseState
2025-01-07 21:46:30 -08:00
impl<In,Out> Timer<Scaled<In,Out>>
where Time<In>:Copy,
{
2024-08-02 10:35:29 -07:00
pub const fn get_scale(&self)->Ratio64{
match self{
Self::Paused(timer)=>timer.get_scale(),
Self::Unpaused(timer)=>timer.get_scale(),
}
}
2025-01-07 21:46:30 -08:00
pub fn set_scale(&mut self,time:Time<In>,new_scale:Ratio64){
2024-08-02 10:35:29 -07:00
match self{
Self::Paused(timer)=>timer.set_scale(time,new_scale),
Self::Unpaused(timer)=>timer.set_scale(time,new_scale),
}
}
2024-07-31 12:10:35 -07:00
}
#[cfg(test)]
mod test{
2024-08-01 21:55:53 -07:00
use super::*;
2024-07-31 12:10:35 -07:00
macro_rules! sec {
($s: expr) => {
Time::from_secs($s)
};
}
2025-01-07 21:46:30 -08:00
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
enum Parent{}
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
enum Calculated{}
2024-07-31 12:10:35 -07:00
#[test]
fn test_timerfixed_scaled(){
//create a paused timer that reads 0s
2025-01-07 21:46:30 -08:00
let timer=TimerFixed::<Scaled<Parent,Calculated>,Paused>::from_state(Scaled::new(0.5f32.try_into().unwrap(),sec!(0)));
2024-07-31 12:10:35 -07:00
//the paused timer at 1 second should read 0s
assert_eq!(timer.time(sec!(1)),sec!(0));
//unpause it after one second
let timer=timer.into_unpaused(sec!(1));
2024-08-27 13:33:50 -07:00
//the timer at 6 seconds should read 2.5s
assert_eq!(timer.time(sec!(6)),Time::from_millis(2500));
2024-07-31 12:10:35 -07:00
//pause the timer after 11 seconds
let timer=timer.into_paused(sec!(11));
2024-08-27 13:33:50 -07:00
//the paused timer at 20 seconds should read 5s
assert_eq!(timer.time(sec!(20)),sec!(5));
2024-07-31 12:10:35 -07:00
}
#[test]
fn test_timer()->Result<(),Error>{
//create a paused timer that reads 0s
2025-01-07 21:46:30 -08:00
let mut timer=Timer::<Realtime<Parent,Calculated>>::paused(sec!(0),sec!(0));
2024-07-31 12:10:35 -07:00
//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(())
}
}