use core::fmt;
use crate::calendar::{DefaultPlan, Scheduler};
#[doc(inline)]
pub use odem_rs_meta::Config;
pub trait Config: 'static {
type Time: Time;
type Rank: Rank;
type Data: 'static;
type Plan: Scheduler<Config = Self>;
fn default_time(&self) -> Self::Time;
fn default_rank(&self) -> Self::Rank;
fn global_data(&self) -> &Self::Data;
}
pub trait Time: Unpin + PartialOrd + Copy + fmt::Debug + 'static {
fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self, f)
}
fn display(self) -> DisplayTime<Self> {
DisplayTime(self)
}
}
pub trait Rank: Default + Unpin + Ord + Copy + fmt::Debug + 'static {}
impl<R> Rank for R where R: Default + Unpin + Ord + Copy + fmt::Debug + 'static {}
#[derive(Default, Copy, Clone)]
pub struct DefaultConfig;
impl Config for DefaultConfig {
type Time = f64;
type Rank = ();
type Data = Self;
type Plan = DefaultPlan<Self>;
fn default_time(&self) -> Self::Time {
0.0
}
fn default_rank(&self) -> Self::Rank {}
fn global_data(&self) -> &Self::Data {
self
}
}
pub struct DisplayTime<T>(T);
impl<T> DisplayTime<T> {
pub fn get(&self) -> &T {
&self.0
}
pub fn into_inner(self) -> T {
self.0
}
}
impl<T: Time> fmt::Debug for DisplayTime<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.format(f)
}
}
impl<T: Time> fmt::Display for DisplayTime<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.format(f)
}
}
impl<T: Time, R: Rank, D: 'static> Config for (T, R, D) {
type Time = T;
type Rank = R;
type Data = D;
type Plan = DefaultPlan<Self>;
fn default_time(&self) -> Self::Time {
self.0
}
fn default_rank(&self) -> Self::Rank {
self.1
}
fn global_data(&self) -> &Self::Data {
&self.2
}
}
macro_rules! impl_primitive_time {
($($T:ty),* $(,)?) => {$(
impl Time for $T {
fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Display;
if f.alternate() {
use crate::erased::ClockTime;
Display::fmt(&ClockTime::seconds(*self as isize), f)
} else {
Display::fmt(self, f)
}
}
}
)*};
}
impl_primitive_time!(
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64
);
impl Time for () {}
#[cfg(feature = "uom")]
mod uom {
use super::Time;
use core::fmt;
use uom::{
Conversion,
fmt::DisplayStyle,
num_traits::{AsPrimitive, Num},
si::{Units, time},
};
impl<U, V> Time for time::Time<U, V>
where
U: Units<V> + ?Sized + 'static,
V: Conversion<V>
+ Num
+ PartialOrd
+ PartialEq
+ AsPrimitive<isize>
+ fmt::Debug
+ fmt::Display
+ Unpin
+ 'static,
time::second: Conversion<V, T = V::T>,
{
fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Display;
if f.alternate() {
use crate::erased::ClockTime;
ClockTime::seconds(self.get::<time::second>().as_()).fmt(f)
} else {
self.into_format_args(time::second, DisplayStyle::Abbreviation)
.fmt(f)
}
}
}
}