dinero/api/
transform_scale.rs

1use crate::Dinero;
2
3/// Transform a Dinero to a new scale.
4///
5/// Transforming to a higher scale means that the internal amount value increases by orders of magnitude. Be careful not to exceed the minimum and maximum safe integers.
6pub fn transform_scale(item: &Dinero, new_scale: u32) -> Dinero {
7    let scale = item.scale;
8    let amount = item.amount;
9    let currency = item.currency;
10
11    let is_new_scale_larger = new_scale > scale;
12    let new_amount: i128;
13    let factor: i128;
14
15    if is_new_scale_larger {
16        factor = i128::from(currency.base.pow(new_scale - scale));
17        new_amount = amount * factor;
18    } else {
19        factor = i128::from(currency.base.pow(scale - new_scale));
20        new_amount = amount / factor;
21    }
22
23    Dinero {
24        amount: new_amount,
25        currency,
26        scale: new_scale,
27    }
28}
29
30#[cfg(test)]
31#[cfg(not(tarpaulin_include))]
32mod tests {
33
34    use super::*;
35    use crate::currencies::EUR;
36    use pretty_assertions::assert_eq;
37
38    #[test]
39    fn test_transform_scale() {
40        assert_eq!(
41            transform_scale(&Dinero::new(500, EUR, Some(2)), 4),
42            Dinero::new(50000, EUR, Some(4))
43        );
44
45        assert_eq!(
46            transform_scale(&Dinero::new(3000, EUR, Some(2)), 0),
47            Dinero::new(30, EUR, Some(0))
48        );
49    }
50}