use core::{
fmt,
ops::{Div, Mul},
};
use crate::{AmountT, Quantity, Unit, AMNT_ONE};
#[derive(Copy, Clone, Debug)]
pub struct Rate<TQ: Quantity, PQ: Quantity> {
term_amount: AmountT,
term_unit: TQ::UnitType,
per_unit_multiple: AmountT,
per_unit: PQ::UnitType,
}
impl<TQ: Quantity, PQ: Quantity> Rate<TQ, PQ> {
#[inline(always)]
pub const fn new(
term_amount: AmountT,
term_unit: TQ::UnitType,
per_unit_multiple: AmountT,
per_unit: PQ::UnitType,
) -> Self {
Self {
term_amount,
term_unit,
per_unit_multiple,
per_unit,
}
}
#[inline(always)]
pub fn from_qty_vals(term: TQ, per: PQ) -> Self {
Self {
term_amount: term.amount(),
term_unit: term.unit(),
per_unit_multiple: per.amount(),
per_unit: per.unit(),
}
}
#[inline(always)]
pub const fn term_amount(&self) -> AmountT {
self.term_amount
}
#[inline(always)]
pub const fn term_unit(&self) -> TQ::UnitType {
self.term_unit
}
#[inline(always)]
pub const fn per_unit_multiple(&self) -> AmountT {
self.per_unit_multiple
}
#[inline(always)]
pub const fn per_unit(&self) -> PQ::UnitType {
self.per_unit
}
pub const fn reciprocal(&self) -> Rate<PQ, TQ> {
Rate::<PQ, TQ>::new(
self.per_unit_multiple(),
self.per_unit(),
self.term_amount(),
self.term_unit(),
)
}
}
impl<TQ: Quantity, PQ: Quantity> fmt::Display for Rate<TQ, PQ> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.term_unit().symbol() == "" {
write!(f, "{} / ", self.term_amount())?;
} else {
write!(
f,
"{} {} / ",
self.term_amount(),
self.term_unit().symbol()
)?;
};
if self.per_unit().symbol() == "" {
write!(f, "{}", self.per_unit_multiple())
} else if self.per_unit_multiple() == AMNT_ONE {
write!(f, "{}", self.per_unit().symbol())
} else {
write!(
f,
"{} {}",
self.per_unit_multiple(),
self.per_unit().symbol()
)
}
}
}
impl<TQ: Quantity, PQ: Quantity> Mul<PQ> for Rate<TQ, PQ>
where
PQ: Div<PQ, Output = AmountT>,
{
type Output = TQ;
fn mul(self, rhs: PQ) -> Self::Output {
let amnt: AmountT =
(rhs / self.per_unit().as_qty()) / self.per_unit_multiple();
Self::Output::new(amnt * self.term_amount(), self.term_unit())
}
}