74 lines
1.8 KiB
Rust
74 lines
1.8 KiB
Rust
|
|
use std::fmt::Display;
|
||
|
|
|
||
|
|
use rust_decimal::Decimal;
|
||
|
|
|
||
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
|
||
|
|
pub struct InterestRate {
|
||
|
|
rate_as_fraction: Decimal,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl InterestRate {
|
||
|
|
pub const ZERO: Self = InterestRate {
|
||
|
|
rate_as_fraction: Decimal::ZERO,
|
||
|
|
};
|
||
|
|
|
||
|
|
pub fn from_percentage(rate_in_percent: Decimal) -> Self {
|
||
|
|
InterestRate {
|
||
|
|
rate_as_fraction: rate_in_percent / Decimal::ONE_HUNDRED,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub const fn from_fraction(rate_as_fraction: Decimal) -> Self {
|
||
|
|
InterestRate { rate_as_fraction }
|
||
|
|
}
|
||
|
|
|
||
|
|
pub const fn as_fraction(self) -> Decimal {
|
||
|
|
self.rate_as_fraction
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn as_percentage(self) -> Decimal {
|
||
|
|
(self.rate_as_fraction * Decimal::ONE_HUNDRED).normalize()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Display for InterestRate {
|
||
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
|
|
write!(f, "{} %", self.as_percentage())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn create_from_percentage_yields_correct_rate() {
|
||
|
|
assert_eq!(
|
||
|
|
InterestRate::from_percentage(Decimal::new(415, 2)).as_fraction(),
|
||
|
|
Decimal::new(415, 4)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn create_from_fraction_yields_correct_rate() {
|
||
|
|
assert_eq!(
|
||
|
|
InterestRate::from_fraction(Decimal::new(415, 4)).as_fraction(),
|
||
|
|
Decimal::new(415, 4)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn create_from_fraction_is_properly_output_as_percentage() {
|
||
|
|
assert_eq!(
|
||
|
|
InterestRate::from_fraction(Decimal::new(314, 4)).as_percentage(),
|
||
|
|
Decimal::new(314, 2)
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn display_works_as_expected_with_no_trailing_zeros() {
|
||
|
|
let interest_rate = InterestRate::from_fraction(Decimal::new(3145, 5));
|
||
|
|
assert_eq!(format!("{}", interest_rate), "3.145 %");
|
||
|
|
}
|
||
|
|
}
|