1use core::{
11 fmt,
12 ops::{Div, Mul},
13};
14
15use crate::{AmountT, Quantity, Unit, AMNT_ONE};
16
17#[derive(Copy, Clone, Debug)]
19pub struct Rate<TQ: Quantity, PQ: Quantity> {
20 term_amount: AmountT,
21 term_unit: TQ::UnitType,
22 per_unit_multiple: AmountT,
23 per_unit: PQ::UnitType,
24}
25
26impl<TQ: Quantity, PQ: Quantity> Rate<TQ, PQ> {
27 #[inline(always)]
29 pub const fn new(
30 term_amount: AmountT,
31 term_unit: TQ::UnitType,
32 per_unit_multiple: AmountT,
33 per_unit: PQ::UnitType,
34 ) -> Self {
35 Self {
36 term_amount,
37 term_unit,
38 per_unit_multiple,
39 per_unit,
40 }
41 }
42
43 #[inline(always)]
46 pub fn from_qty_vals(term: TQ, per: PQ) -> Self {
47 Self {
48 term_amount: term.amount(),
49 term_unit: term.unit(),
50 per_unit_multiple: per.amount(),
51 per_unit: per.unit(),
52 }
53 }
54
55 #[inline(always)]
57 pub const fn term_amount(&self) -> AmountT {
58 self.term_amount
59 }
60
61 #[inline(always)]
63 pub const fn term_unit(&self) -> TQ::UnitType {
64 self.term_unit
65 }
66
67 #[inline(always)]
69 pub const fn per_unit_multiple(&self) -> AmountT {
70 self.per_unit_multiple
71 }
72
73 #[inline(always)]
75 pub const fn per_unit(&self) -> PQ::UnitType {
76 self.per_unit
77 }
78
79 pub const fn reciprocal(&self) -> Rate<PQ, TQ> {
81 Rate::<PQ, TQ>::new(
82 self.per_unit_multiple(),
83 self.per_unit(),
84 self.term_amount(),
85 self.term_unit(),
86 )
87 }
88}
89
90impl<TQ: Quantity, PQ: Quantity> fmt::Display for Rate<TQ, PQ> {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 if self.term_unit().symbol() == "" {
93 write!(f, "{} / ", self.term_amount())?;
94 } else {
95 write!(
96 f,
97 "{} {} / ",
98 self.term_amount(),
99 self.term_unit().symbol()
100 )?;
101 };
102 if self.per_unit().symbol() == "" {
103 write!(f, "{}", self.per_unit_multiple())
104 } else if self.per_unit_multiple() == AMNT_ONE {
105 write!(f, "{}", self.per_unit().symbol())
106 } else {
107 write!(
108 f,
109 "{} {}",
110 self.per_unit_multiple(),
111 self.per_unit().symbol()
112 )
113 }
114 }
115}
116
117impl<TQ: Quantity, PQ: Quantity> Mul<PQ> for Rate<TQ, PQ>
118where
119 PQ: Div<PQ, Output = AmountT>,
120{
121 type Output = TQ;
122
123 fn mul(self, rhs: PQ) -> Self::Output {
124 let amnt: AmountT =
125 (rhs / self.per_unit().as_qty()) / self.per_unit_multiple();
126 Self::Output::new(amnt * self.term_amount(), self.term_unit())
127 }
128}