penumbra_sdk_num/percentage/
mod.rs

1use crate::fixpoint::U128x128;
2
3/// Represents a percentage value.
4///
5/// Useful for more robust typesafety, versus just passing around a `u64` which
6/// is merely *understood* to only contain values in [0, 100].
7///
8/// Defaults to 0%.
9#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
10pub struct Percentage(u64);
11
12impl Percentage {
13    /// 0%
14    pub const fn zero() -> Self {
15        Self(0)
16    }
17
18    /// Convert this value into a `u64` in [0, 100];
19    pub const fn to_percent(self) -> u64 {
20        self.0
21    }
22
23    /// Given an arbitrary `u64`, produce a percentage, *saturating* at 100.
24    pub fn from_percent(p: u64) -> Self {
25        Self(u64::min(p.into(), 100))
26    }
27
28    /// Given p%, return (1 - p)%.
29    pub fn complement(self) -> Self {
30        Self(100 - self.0)
31    }
32}
33
34impl From<Percentage> for U128x128 {
35    fn from(value: Percentage) -> Self {
36        Self::ratio(value.to_percent(), 100).expect("dividing by 100 should succeed")
37    }
38}
39
40#[cfg(test)]
41mod test {
42    use super::*;
43
44    #[test]
45    fn test_percentage_operations() {
46        assert_eq!(Percentage::from_percent(101), Percentage::from_percent(100));
47        assert_eq!(Percentage::from_percent(48).to_percent(), 48);
48    }
49}