use crate::{CachifiedError, Result};
pub trait CheckValue<T> {
fn check(&self, value: &T) -> Result<()>;
}
pub struct FunctionValidator<F> {
func: F,
}
impl<F> FunctionValidator<F> {
pub fn new(func: F) -> Self {
Self { func }
}
}
impl<T, F> CheckValue<T> for FunctionValidator<F>
where
F: Fn(&T) -> Result<()>,
{
fn check(&self, value: &T) -> Result<()> {
(self.func)(value)
}
}
pub struct NoValidator;
impl<T> CheckValue<T> for NoValidator {
fn check(&self, _value: &T) -> Result<()> {
Ok(())
}
}
pub struct NonNullValidator;
impl<T> CheckValue<Option<T>> for NonNullValidator {
fn check(&self, value: &Option<T>) -> Result<()> {
match value {
Some(_) => Ok(()),
None => Err(CachifiedError::validation("Value is None")),
}
}
}
pub struct NonEmptyStringValidator;
impl CheckValue<String> for NonEmptyStringValidator {
fn check(&self, value: &String) -> Result<()> {
if value.is_empty() {
Err(CachifiedError::validation("String is empty"))
} else {
Ok(())
}
}
}
impl CheckValue<&str> for NonEmptyStringValidator {
fn check(&self, value: &&str) -> Result<()> {
if value.is_empty() {
Err(CachifiedError::validation("String is empty"))
} else {
Ok(())
}
}
}
pub fn validator<T, F>(func: F) -> FunctionValidator<F>
where
F: Fn(&T) -> Result<()>,
{
FunctionValidator::new(func)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_function_validator() {
let validator = validator(|x: &i32| {
if *x > 0 {
Ok(())
} else {
Err(CachifiedError::validation("Must be positive"))
}
});
assert!(validator.check(&5).is_ok());
assert!(validator.check(&-1).is_err());
}
#[test]
fn test_non_null_validator() {
let validator = NonNullValidator;
assert!(validator.check(&Some(42)).is_ok());
assert!(validator.check(&None::<i32>).is_err());
}
#[test]
fn test_non_empty_string_validator() {
let validator = NonEmptyStringValidator;
assert!(validator.check(&"hello".to_string()).is_ok());
assert!(validator.check(&"".to_string()).is_err());
assert!(validator.check(&"world").is_ok());
assert!(validator.check(&"").is_err());
}
#[test]
fn test_no_validator() {
let validator = NoValidator;
assert!(validator.check(&42).is_ok());
assert!(validator.check(&"anything").is_ok());
assert!(validator.check(&None::<String>).is_ok());
}
}