use std::fmt;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Fraction(pub(crate) Decimal);
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum FractionError {
#[error("fraction {0} out of range [0, 1]")]
OutOfRange(Decimal),
}
impl Fraction {
pub fn new(value: Decimal) -> Result<Self, FractionError> {
if value < Decimal::ZERO || value > Decimal::ONE {
return Err(FractionError::OutOfRange(value));
}
Ok(Self(value))
}
pub fn value(&self) -> Decimal {
self.0
}
pub fn zero() -> Self {
Self(Decimal::ZERO)
}
pub fn one() -> Self {
Self(Decimal::ONE)
}
}
impl fmt::Display for Fraction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.normalize())
}
}
#[cfg(test)]
#[path = "fraction_tests.rs"]
mod tests;