lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

percent.rs (2199B)


      1 use core::fmt;
      2 use core::str::FromStr;
      3 
      4 use crate::RadrootsCoreDecimal;
      5 use crate::money::RadrootsCoreMoney;
      6 
      7 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
      8 #[derive(Clone, Debug, PartialEq, Eq)]
      9 pub struct RadrootsCorePercent {
     10     #[cfg_attr(feature = "serde", serde(with = "crate::serde_ext::decimal_str"))]
     11     pub value: RadrootsCoreDecimal,
     12 }
     13 
     14 impl RadrootsCorePercent {
     15     #[inline]
     16     pub fn new(value: RadrootsCoreDecimal) -> Self {
     17         Self { value }
     18     }
     19 
     20     #[inline]
     21     pub fn from_ratio(ratio_0_to_1: RadrootsCoreDecimal) -> Self {
     22         Self {
     23             value: ratio_0_to_1 * RadrootsCoreDecimal::from(100u32),
     24         }
     25     }
     26 
     27     #[inline]
     28     pub fn to_ratio(&self) -> RadrootsCoreDecimal {
     29         self.value / RadrootsCoreDecimal::from(100u32)
     30     }
     31 
     32     #[inline]
     33     pub fn of_money(&self, base: &RadrootsCoreMoney) -> RadrootsCoreMoney {
     34         base.mul_decimal(self.to_ratio())
     35     }
     36 
     37     #[inline]
     38     pub fn of_money_quantized(&self, base: &RadrootsCoreMoney) -> RadrootsCoreMoney {
     39         base.mul_decimal(self.to_ratio()).quantize_to_currency()
     40     }
     41 }
     42 
     43 impl fmt::Display for RadrootsCorePercent {
     44     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     45         write!(f, "{}%", self.value.normalize())
     46     }
     47 }
     48 
     49 impl FromStr for RadrootsCorePercent {
     50     type Err = RadrootsCorePercentParseError;
     51 
     52     fn from_str(s: &str) -> Result<Self, Self::Err> {
     53         let trimmed = s.trim_end();
     54         let no_pct = trimmed.strip_suffix('%').unwrap_or(trimmed).trim();
     55         let dec = no_pct
     56             .parse::<RadrootsCoreDecimal>()
     57             .map_err(|_| RadrootsCorePercentParseError::InvalidNumber)?;
     58         Ok(RadrootsCorePercent::new(dec))
     59     }
     60 }
     61 
     62 #[non_exhaustive]
     63 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
     64 pub enum RadrootsCorePercentParseError {
     65     InvalidNumber,
     66 }
     67 
     68 impl fmt::Display for RadrootsCorePercentParseError {
     69     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     70         match self {
     71             RadrootsCorePercentParseError::InvalidNumber => write!(f, "invalid percent string"),
     72         }
     73     }
     74 }
     75 
     76 #[cfg(feature = "std")]
     77 impl std::error::Error for RadrootsCorePercentParseError {}