ic_dbms_api/dbms/sanitize/
round_to_scale.rs

1use crate::prelude::{IcDbmsResult, Sanitize, Value};
2
3/// Sanitizer that rounds [`rust_decimal::Decimal`] values to a specified scale.
4///
5/// # Example
6///
7/// ```rust
8/// use ic_dbms_api::prelude::{RoundToScaleSanitizer, Value, Sanitize as _};
9/// use rust_decimal::Decimal;
10///
11/// let value = Value::Decimal(Decimal::new(123456, 4).into()); // 12.3456
12/// let sanitizer = RoundToScaleSanitizer(2);
13/// let sanitized_value = sanitizer.sanitize(value).unwrap();
14/// assert_eq!(sanitized_value, Value::Decimal(Decimal::new(1235, 2).into())); // 12.35
15/// ```
16pub struct RoundToScaleSanitizer(pub u32);
17
18impl Sanitize for RoundToScaleSanitizer {
19    fn sanitize(&self, value: Value) -> IcDbmsResult<Value> {
20        match value {
21            Value::Decimal(num) => {
22                let rounded = num.0.round_dp(self.0);
23                Ok(Value::Decimal(rounded.into()))
24            }
25            other => Ok(other),
26        }
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use rust_decimal::Decimal;
33
34    use super::*;
35    use crate::prelude::Value;
36
37    #[test]
38    fn test_round_to_scale_sanitizer() {
39        let sanitizer = RoundToScaleSanitizer(2);
40        let value = Value::Decimal(Decimal::new(123456, 4).into()); // 12.3456
41        let sanitized_value = sanitizer.sanitize(value).unwrap();
42        assert_eq!(
43            sanitized_value,
44            Value::Decimal(Decimal::new(1235, 2).into())
45        ); // 12.35
46
47        // Test with non-decimal value
48        let non_decimal_value = Value::Int32(42.into());
49        let sanitized_value = sanitizer.sanitize(non_decimal_value.clone()).unwrap();
50        assert_eq!(sanitized_value, non_decimal_value);
51    }
52}