use crate::prelude::{DbmsResult, Sanitize, Value};
pub struct ClampSanitizer {
pub min: i64,
pub max: i64,
}
impl Sanitize for ClampSanitizer {
fn sanitize(&self, value: Value) -> DbmsResult<Value> {
match value {
Value::Int32(num) => {
let clamped = (num.0 as i64).clamp(self.min, self.max);
let clamped: Result<i32, _> = clamped.try_into();
match clamped {
Ok(clamped_i32) => Ok(Value::Int32(clamped_i32.into())),
Err(_) => Err(crate::prelude::DbmsError::Sanitize(
"Clamped value out of Int32 range".into(),
)),
}
}
Value::Int64(num) => {
let clamped = num.0.clamp(self.min, self.max);
Ok(Value::Int64(clamped.into()))
}
other => Ok(other),
}
}
}
pub struct ClampUnsignedSanitizer {
pub min: u64,
pub max: u64,
}
impl Sanitize for ClampUnsignedSanitizer {
fn sanitize(&self, value: Value) -> DbmsResult<Value> {
match value {
Value::Uint32(num) => {
let clamped = (num.0 as u64).clamp(self.min, self.max);
let clamped: Result<u32, _> = clamped.try_into();
match clamped {
Ok(clamped_u32) => Ok(Value::Uint32(clamped_u32.into())),
Err(_) => Err(crate::prelude::DbmsError::Sanitize(
"Clamped value out of Uint32 range".into(),
)),
}
}
Value::Uint64(num) => {
let clamped = num.0.clamp(self.min, self.max);
Ok(Value::Uint64(clamped.into()))
}
other => Ok(other),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clamp_sanitizer_i32() {
let sanitizer = ClampSanitizer { min: 0, max: 100 };
let value_in_range = Value::Int32(50.into());
let value_below_range = Value::Int32((-10i32).into());
let value_above_range = Value::Int32(150.into());
let non_integer_value = Value::Text("Not an integer".into());
let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
assert_eq!(sanitized_in_range, Value::Int32(50.into()));
assert_eq!(sanitized_below_range, Value::Int32(0.into()));
assert_eq!(sanitized_above_range, Value::Int32(100.into()));
assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
}
#[test]
fn test_clamp_sanitizer_i64() {
let sanitizer = ClampSanitizer { min: 0, max: 100 };
let value_in_range = Value::Int64(50.into());
let value_below_range = Value::Int64((-10i64).into());
let value_above_range = Value::Int64(150.into());
let non_integer_value = Value::Text("Not an integer".into());
let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
assert_eq!(sanitized_in_range, Value::Int64(50.into()));
assert_eq!(sanitized_below_range, Value::Int64(0.into()));
assert_eq!(sanitized_above_range, Value::Int64(100.into()));
assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
}
#[test]
fn test_clamp_unsigned_sanitizer_u32() {
let sanitizer = ClampUnsignedSanitizer { min: 0, max: 100 };
let value_in_range = Value::Uint32(50.into());
let value_below_range = Value::Uint32(0.into()); let value_above_range = Value::Uint32(150.into());
let non_integer_value = Value::Text("Not an integer".into());
let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
assert_eq!(sanitized_in_range, Value::Uint32(50.into()));
assert_eq!(sanitized_below_range, Value::Uint32(0.into()));
assert_eq!(sanitized_above_range, Value::Uint32(100.into()));
assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
}
#[test]
fn test_clamp_unsigned_sanitizer_u64() {
let sanitizer = ClampUnsignedSanitizer { min: 0, max: 100 };
let value_in_range = Value::Uint64(50.into());
let value_below_range = Value::Uint64(0.into()); let value_above_range = Value::Uint64(150.into());
let non_integer_value = Value::Text("Not an integer".into());
let sanitized_in_range = sanitizer.sanitize(value_in_range).unwrap();
let sanitized_below_range = sanitizer.sanitize(value_below_range).unwrap();
let sanitized_above_range = sanitizer.sanitize(value_above_range).unwrap();
let sanitized_non_integer = sanitizer.sanitize(non_integer_value).unwrap();
assert_eq!(sanitized_in_range, Value::Uint64(50.into()));
assert_eq!(sanitized_below_range, Value::Uint64(0.into()));
assert_eq!(sanitized_above_range, Value::Uint64(100.into()));
assert_eq!(sanitized_non_integer, Value::Text("Not an integer".into()));
}
}