progress_monitor/work/
numeric.rs

1use std::{
2    fmt::Debug,
3    fmt::Display,
4    ops::{Add, Sub},
5};
6
7use num::{FromPrimitive, Num, ToPrimitive};
8
9use crate::work::{AddError, Work};
10
11pub trait NumReq: Num + ToPrimitive + FromPrimitive + PartialOrd + Debug + Display + Clone {}
12
13impl<T: Num + ToPrimitive + FromPrimitive + PartialOrd + Debug + Display + Clone> NumReq for T {}
14
15#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
16pub struct NumericWork<N: NumReq>(N);
17
18impl<N: NumReq> Work for NumericWork<N> {
19    type Type = N;
20
21    fn new<A: Into<Self::Type>>(value: A) -> Self {
22        Self(value.into())
23    }
24
25    fn zero() -> Self {
26        Self::new(N::zero())
27    }
28
29    fn min<'a>(a: &'a Self, b: &'a Self) -> &'a Self {
30        if a.0 < b.0 {
31            a
32        } else {
33            b
34        }
35    }
36
37    fn parent_work_done_when(
38        sub_work_done: Self,
39        of_total_sub_work: Self,
40        of_parent_work: Self,
41    ) -> Self {
42        let sub_work_done = sub_work_done.0.to_f64().expect("representable as f64");
43        let of_total_sub_work = of_total_sub_work.0.to_f64().expect("representable as f64");
44        let of_parent_work = of_parent_work.0.to_f64().expect("representable as f64");
45
46        let rel = sub_work_done / of_total_sub_work * of_parent_work;
47
48        Self::new(N::from_f64(rel).expect("cast from f64 to N"))
49    }
50}
51
52impl<N: NumReq> Display for NumericWork<N> {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        f.write_fmt(format_args!("{}", self.0))
55    }
56}
57
58impl<N: NumReq> Add for NumericWork<N> {
59    type Output = Result<Self, AddError>;
60
61    fn add(self, rhs: Self) -> Self::Output {
62        Ok(Self::new(self.0 + rhs.0))
63    }
64}
65
66impl<N: NumReq> Sub for NumericWork<N> {
67    type Output = Self;
68
69    fn sub(self, rhs: Self) -> Self::Output {
70        Self::new(self.0 - rhs.0)
71    }
72}
73
74impl<N: NumReq> From<N> for NumericWork<N> {
75    fn from(value: N) -> Self {
76        Self::new(value)
77    }
78}