use atomic_arena::{error::ArenaFull, Arena};
use crate::{manager::backend::resources::clocks::Clocks, StartTime};
use super::{ClockId, ClockTime};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ClockInfo {
pub ticking: bool,
pub ticks: u64,
pub fractional_position: f64,
}
pub struct ClockInfoProvider<'a> {
kind: ClockInfoProviderKind<'a>,
}
impl<'a> ClockInfoProvider<'a> {
pub(crate) fn new(clocks: &'a Clocks) -> Self {
Self {
kind: ClockInfoProviderKind::Normal { clocks },
}
}
pub fn get(&self, id: ClockId) -> Option<ClockInfo> {
match &self.kind {
ClockInfoProviderKind::Normal { clocks } => clocks.get(id).map(|clock| ClockInfo {
ticking: clock.shared.ticking(),
ticks: clock.shared.ticks(),
fractional_position: clock.shared.fractional_position(),
}),
ClockInfoProviderKind::Mock { clock_info } => clock_info.get(id.0).copied(),
}
}
pub fn when_to_start(&self, start_time: StartTime) -> WhenToStart {
if let StartTime::ClockTime(ClockTime { clock, ticks }) = start_time {
if let Some(clock_info) = self.get(clock) {
if clock_info.ticking && clock_info.ticks >= ticks {
WhenToStart::Now
} else {
WhenToStart::Later
}
} else {
WhenToStart::Never
}
} else {
WhenToStart::Now
}
}
}
enum ClockInfoProviderKind<'a> {
Normal { clocks: &'a Clocks },
Mock { clock_info: Arena<ClockInfo> },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum WhenToStart {
Now,
Later,
Never,
}
pub struct MockClockInfoProviderBuilder {
clock_info: Arena<ClockInfo>,
}
impl MockClockInfoProviderBuilder {
pub fn new(capacity: usize) -> Self {
Self {
clock_info: Arena::new(capacity),
}
}
pub fn add(&mut self, info: ClockInfo) -> Result<ClockId, ArenaFull> {
Ok(ClockId(self.clock_info.insert(info)?))
}
pub fn build(self) -> ClockInfoProvider<'static> {
ClockInfoProvider {
kind: ClockInfoProviderKind::Mock {
clock_info: self.clock_info,
},
}
}
}