1use crate::calendar::{DefaultPlan, Scheduler};
52use core::{any::Any, fmt, marker::PhantomData};
53
54#[doc(inline)]
55pub use odem_rs_meta::Config;
56
57pub trait Config: 'static {
62 type Time: Time;
64 type Rank: Rank;
67 type Data: Any;
74 type Plan: Scheduler<Config = Self>;
82
83 fn default_time(&self) -> Self::Time;
85
86 fn default_rank(&self) -> Self::Rank;
88
89 fn global_data(&self) -> &Self::Data;
91}
92
93pub trait Time: Unpin + PartialOrd + Copy + fmt::Debug + 'static {
96 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 fmt::Debug::fmt(&self, f)
102 }
103
104 fn display(self) -> DisplayTime<Self> {
108 DisplayTime(self)
109 }
110}
111
112pub trait Rank: Unpin + Ord + Copy + fmt::Debug + 'static {}
115
116impl<R> Rank for R where R: Unpin + Ord + Copy + fmt::Debug + 'static {}
118
119impl Config for () {
122 type Time = f64;
123 type Rank = ();
124 type Data = ();
125 type Plan = DefaultPlan<()>;
126
127 fn default_time(&self) -> Self::Time {
128 0.0
129 }
130
131 fn default_rank(&self) -> Self::Rank {}
132
133 fn global_data(&self) -> &Self::Data {
134 self
135 }
136}
137
138pub struct DisplayTime<T>(pub T);
144
145impl<T: Time> fmt::Debug for DisplayTime<T> {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 self.0.format(f)
148 }
149}
150
151impl<T: Time> fmt::Display for DisplayTime<T> {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 self.0.format(f)
154 }
155}
156
157macro_rules! impl_signed_integral_time {
158 ($($T:ty),* $(,)?) => {$(
159 impl Time for $T {
160 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 use fmt::Display;
162 if f.alternate() {
163 Display::fmt(&ClockTime::seconds(*self as isize), f)
164 } else {
165 Display::fmt(self, f)
166 }
167 }
168 }
169 )*};
170}
171
172impl_signed_integral_time!(i8, i16, i32, i64, i128, isize);
173
174macro_rules! impl_unsigned_integral_time {
175 ($($T:ty),* $(,)?) => {$(
176 impl Time for $T {
177 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 use fmt::Display;
179 if f.alternate() {
180 Display::fmt(&Seconds(*self as usize), f)
181 } else {
182 Display::fmt(self, f)
183 }
184 }
185 }
186 )*};
187}
188
189impl_unsigned_integral_time!(u8, u16, u32, u64, u128, usize);
190
191macro_rules! impl_floating_time {
192 ($($T:ty),* $(,)?) => {$(
193 impl Time for $T {
194 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 use fmt::Display;
196 if f.alternate() {
197 match f.precision() {
198 None | Some(0) => Display::fmt(&ClockTime::seconds(*self as isize), f),
199 Some(1) => Display::fmt(&ClockTime::milliseconds((*self * 1e+3) as isize), f),
200 Some(2) => Display::fmt(&ClockTime::microseconds((*self * 1e+6) as isize), f),
201 _ => Display::fmt(&ClockTime::nanoseconds((*self * 1e+9) as isize), f),
202 }
203 } else {
204 Display::fmt(self, f)
205 }
206 }
207 }
208 )*};
209}
210
211impl_floating_time!(f32, f64);
212
213impl Time for () {}
214
215#[derive(Copy, Clone)]
219pub struct ClockTime<U> {
220 value: isize,
222 _unit: PhantomData<U>,
224}
225
226impl ClockTime<()> {
227 pub const fn nanoseconds(value: isize) -> impl fmt::Display {
229 ClockTime::<Nanoseconds> {
230 value,
231 _unit: PhantomData,
232 }
233 }
234
235 pub const fn microseconds(value: isize) -> impl fmt::Display {
237 ClockTime::<Microseconds> {
238 value,
239 _unit: PhantomData,
240 }
241 }
242
243 pub const fn milliseconds(value: isize) -> impl fmt::Display {
245 ClockTime::<Milliseconds> {
246 value,
247 _unit: PhantomData,
248 }
249 }
250
251 pub const fn seconds(value: isize) -> impl fmt::Display {
253 ClockTime::<Seconds> {
254 value,
255 _unit: PhantomData,
256 }
257 }
258
259 pub const fn minutes(value: isize) -> impl fmt::Display {
261 ClockTime::<Minutes> {
262 value,
263 _unit: PhantomData,
264 }
265 }
266
267 pub const fn hours(value: isize) -> impl fmt::Display {
269 ClockTime::<Hours> {
270 value,
271 _unit: PhantomData,
272 }
273 }
274
275 pub const fn days(value: isize) -> impl fmt::Display {
277 ClockTime::<Days> {
278 value,
279 _unit: PhantomData,
280 }
281 }
282
283 pub const fn years(value: isize) -> impl fmt::Display {
285 ClockTime::<Years> {
286 value,
287 _unit: PhantomData,
288 }
289 }
290}
291
292impl<U> ClockTime<U> {
293 fn write_sign(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 if self.value < 0 {
296 write!(f, "-")
297 } else if f.sign_plus() {
298 write!(f, "+")
299 } else {
300 Ok(())
301 }
302 }
303}
304
305impl fmt::Display for ClockTime<Years> {
306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307 self.write_sign(f)?;
308 Years(self.value.unsigned_abs()).fmt(f)
309 }
310}
311
312impl fmt::Display for ClockTime<Days> {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 self.write_sign(f)?;
315 Days(self.value.unsigned_abs()).fmt(f)
316 }
317}
318
319impl fmt::Display for ClockTime<Hours> {
320 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321 self.write_sign(f)?;
322 Hours(self.value.unsigned_abs()).fmt(f)
323 }
324}
325
326impl fmt::Display for ClockTime<Minutes> {
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 self.write_sign(f)?;
329 Minutes(self.value.unsigned_abs()).fmt(f)
330 }
331}
332
333impl fmt::Display for ClockTime<Seconds> {
334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335 self.write_sign(f)?;
336 Seconds(self.value.unsigned_abs()).fmt(f)
337 }
338}
339
340impl fmt::Display for ClockTime<Milliseconds> {
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 self.write_sign(f)?;
343 Milliseconds(self.value.unsigned_abs()).fmt(f)
344 }
345}
346
347impl fmt::Display for ClockTime<Microseconds> {
348 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349 self.write_sign(f)?;
350 Microseconds(self.value.unsigned_abs()).fmt(f)
351 }
352}
353
354impl fmt::Display for ClockTime<Nanoseconds> {
355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356 self.write_sign(f)?;
357 Nanoseconds(self.value.unsigned_abs()).fmt(f)
358 }
359}
360
361struct Nanoseconds(usize);
363struct Microseconds(usize);
365struct Milliseconds(usize);
367struct Seconds(usize);
369struct Minutes(usize);
371struct Hours(usize);
373struct Days(usize);
375struct Years(usize);
377
378impl fmt::Display for Years {
379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380 if self.0 != 0 || f.sign_aware_zero_pad() {
381 write!(f, "{}a", self.0)
382 } else {
383 f.write_str(" ")
384 }
385 }
386}
387
388impl fmt::Display for Days {
389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390 let mut quantity = self.0;
391 let mut p;
392
393 if {
394 p = quantity >= 365;
395 p
396 } || f.width().map(|w| w > 5).unwrap_or(false)
397 {
398 Years(quantity / 365).fmt(f)?;
399 f.write_str(" ")?;
400 }
401
402 if quantity >= 7 || f.width().map(|w| w > 4).unwrap_or(false) {
403 quantity %= 365;
404
405 p |= quantity >= 7;
406 if p || f.sign_aware_zero_pad() {
407 write!(f, "{:2}w ", quantity / 7)?;
408 } else {
409 f.write_str(" ")?;
410 }
411
412 quantity %= 7;
413 }
414
415 if p || quantity != 0 || f.sign_aware_zero_pad() {
416 write!(f, "{quantity}d")
417 } else {
418 f.write_str(" ")
419 }
420 }
421}
422
423impl fmt::Display for Hours {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 let mut quantity = self.0;
426 let p;
427
428 if {
429 p = quantity >= 24;
430 p
431 } || f.width().map(|w| w > 3).unwrap_or(false)
432 {
433 Days(quantity / 24).fmt(f)?;
434 quantity %= 24;
435 f.write_str(" ")?;
436 }
437
438 if p || quantity != 0 || f.sign_aware_zero_pad() {
439 write!(f, "{quantity:02}h")
440 } else {
441 f.write_str(" ")
442 }
443 }
444}
445
446impl fmt::Display for Minutes {
447 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448 let mut quantity = self.0;
449 let p;
450
451 if {
452 p = quantity >= 60;
453 p
454 } || f.width().map(|w| w > 2).unwrap_or(false)
455 {
456 Hours(quantity / 60).fmt(f)?;
457 quantity %= 60;
458 f.write_str(" ")?;
459 }
460
461 if p || quantity != 0 || f.sign_aware_zero_pad() {
462 write!(f, "{quantity:02}m")
463 } else {
464 f.write_str(" ")
465 }
466 }
467}
468
469impl fmt::Display for Seconds {
470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471 let mut quantity = self.0;
472 let p;
473
474 if {
475 p = quantity >= 60;
476 p
477 } || f.width().map(|w| w > 1).unwrap_or(false)
478 {
479 Minutes(quantity / 60).fmt(f)?;
480 quantity %= 60;
481 f.write_str(" ")?;
482 }
483
484 if p || quantity != 0 || f.sign_aware_zero_pad() {
485 write!(f, "{quantity:02}s")
486 } else {
487 f.write_str(" 0s")
488 }
489 }
490}
491
492impl fmt::Display for Milliseconds {
493 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494 let mut quantity = self.0;
495
496 Seconds(quantity / 1000).fmt(f)?;
497 quantity %= 1000;
498 write!(f, " {quantity:03}ms")
499 }
500}
501
502impl fmt::Display for Microseconds {
503 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504 let mut quantity = self.0;
505
506 Milliseconds(quantity / 1000).fmt(f)?;
507 quantity %= 1000;
508 write!(f, " {quantity:03}µs")
509 }
510}
511
512impl fmt::Display for Nanoseconds {
513 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
514 let mut quantity = self.0;
515
516 Microseconds(quantity / 1000).fmt(f)?;
517 quantity %= 1000;
518 write!(f, " {quantity:03}ns")
519 }
520}
521
522#[cfg(feature = "uom")]
526#[cfg_attr(docsrs, doc(cfg(feature = "uom")))]
527mod uom {
528 use super::{ClockTime, Time};
529 use core::fmt;
530 use uom::{
531 Conversion,
532 fmt::DisplayStyle,
533 num_traits::{AsPrimitive, Num},
534 si::{Units, time},
535 };
536
537 impl<U, V> Time for time::Time<U, V>
538 where
539 U: Units<V> + ?Sized + 'static,
540 V: Conversion<V>
541 + Num
542 + PartialOrd
543 + PartialEq
544 + AsPrimitive<isize>
545 + fmt::Debug
546 + fmt::Display
547 + Unpin
548 + 'static,
549 time::second: Conversion<V, T = V::T>,
550 time::millisecond: Conversion<V, T = V::T>,
551 time::microsecond: Conversion<V, T = V::T>,
552 time::nanosecond: Conversion<V, T = V::T>,
553 {
554 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
555 use fmt::Display;
556
557 if f.alternate() {
558 match f.precision() {
560 None | Some(0) => ClockTime::seconds(self.get::<time::second>().as_()).fmt(f),
561 Some(1) => {
562 ClockTime::milliseconds(self.get::<time::millisecond>().as_()).fmt(f)
563 }
564 Some(2) => {
565 ClockTime::microseconds(self.get::<time::microsecond>().as_()).fmt(f)
566 }
567 _ => ClockTime::nanoseconds(self.get::<time::nanosecond>().as_()).fmt(f),
568 }
569 } else {
570 self.into_format_args(time::second, DisplayStyle::Abbreviation)
572 .fmt(f)
573 }
574 }
575 }
576}