ic_dbms_api/dbms/sanitize/
clamp.rs1use crate::prelude::{IcDbmsResult, Sanitize, Value};
2
3pub struct ClampSanitizer {
16 pub min: i64,
17 pub max: i64,
18}
19
20impl Sanitize for ClampSanitizer {
21 fn sanitize(&self, value: Value) -> IcDbmsResult<Value> {
22 match value {
23 Value::Int32(num) => {
24 let clamped = (num.0 as i64).clamp(self.min, self.max);
25 let clamped: Result<i32, _> = clamped.try_into();
26 match clamped {
27 Ok(clamped_i32) => Ok(Value::Int32(clamped_i32.into())),
28 Err(_) => Err(crate::prelude::IcDbmsError::Sanitize(
29 "Clamped value out of Int32 range".into(),
30 )),
31 }
32 }
33 Value::Int64(num) => {
34 let clamped = num.0.clamp(self.min, self.max);
35 Ok(Value::Int64(clamped.into()))
36 }
37 other => Ok(other),
38 }
39 }
40}
41
42pub struct ClampUnsignedSanitizer {
55 pub min: u64,
56 pub max: u64,
57}
58
59impl Sanitize for ClampUnsignedSanitizer {
60 fn sanitize(&self, value: Value) -> IcDbmsResult<Value> {
61 match value {
62 Value::Uint32(num) => {
63 let clamped = (num.0 as u64).clamp(self.min, self.max);
64 let clamped: Result<u32, _> = clamped.try_into();
65 match clamped {
66 Ok(clamped_u32) => Ok(Value::Uint32(clamped_u32.into())),
67 Err(_) => Err(crate::prelude::IcDbmsError::Sanitize(
68 "Clamped value out of Uint32 range".into(),
69 )),
70 }
71 }
72 Value::Uint64(num) => {
73 let clamped = num.0.clamp(self.min, self.max);
74 Ok(Value::Uint64(clamped.into()))
75 }
76 other => Ok(other),
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_clamp_sanitizer_i32() {
87 let sanitizer = ClampSanitizer { min: 0, max: 100 };
88 let value_in_range = Value::Int32(50.into());
89 let value_below_range = Value::Int32((-10i32).into());
90 let value_above_range = Value::Int32(150.into());
91 let non_integer_value = Value::Text("Not an integer".into());
92
93 let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
94 let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
95 let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
96 let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
97
98 assert_eq!(sanitized_in_range, Value::Int32(50.into()));
99 assert_eq!(sanitized_below_range, Value::Int32(0.into()));
100 assert_eq!(sanitized_above_range, Value::Int32(100.into()));
101 assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
102 }
103
104 #[test]
105 fn test_clamp_sanitizer_i64() {
106 let sanitizer = ClampSanitizer { min: 0, max: 100 };
107 let value_in_range = Value::Int64(50.into());
108 let value_below_range = Value::Int64((-10i64).into());
109 let value_above_range = Value::Int64(150.into());
110 let non_integer_value = Value::Text("Not an integer".into());
111
112 let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
113 let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
114 let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
115 let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
116
117 assert_eq!(sanitized_in_range, Value::Int64(50.into()));
118 assert_eq!(sanitized_below_range, Value::Int64(0.into()));
119 assert_eq!(sanitized_above_range, Value::Int64(100.into()));
120 assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
121 }
122
123 #[test]
124 fn test_clamp_unsigned_sanitizer_u32() {
125 let sanitizer = ClampUnsignedSanitizer { min: 0, max: 100 };
126 let value_in_range = Value::Uint32(50.into());
127 let value_below_range = Value::Uint32(0.into()); let value_above_range = Value::Uint32(150.into());
129 let non_integer_value = Value::Text("Not an integer".into());
130
131 let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
132 let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
133 let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
134 let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
135
136 assert_eq!(sanitized_in_range, Value::Uint32(50.into()));
137 assert_eq!(sanitized_below_range, Value::Uint32(0.into()));
138 assert_eq!(sanitized_above_range, Value::Uint32(100.into()));
139 assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
140 }
141
142 #[test]
143 fn test_clamp_unsigned_sanitizer_u64() {
144 let sanitizer = ClampUnsignedSanitizer { min: 0, max: 100 };
145 let value_in_range = Value::Uint64(50.into());
146 let value_below_range = Value::Uint64(0.into()); let value_above_range = Value::Uint64(150.into());
148 let non_integer_value = Value::Text("Not an integer".into());
149
150 let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
151 let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
152 let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
153 let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
154
155 assert_eq!(sanitized_in_range, Value::Uint64(50.into()));
156 assert_eq!(sanitized_below_range, Value::Uint64(0.into()));
157 assert_eq!(sanitized_above_range, Value::Uint64(100.into()));
158 assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
159 }
160}