use crate::Decimal;
use crate::error::CoolError;
#[cfg(test)]
mod tests;
pub fn validate_length(
field: &'static str,
value: &str,
min: Option<usize>,
max: Option<usize>,
) -> Result<(), CoolError> {
let len = value.chars().count();
if let Some(min) = min
&& len < min
{
return Err(CoolError::Validation(format!(
"field '{field}' length {len} is below minimum {min}",
)));
}
if let Some(max) = max
&& len > max
{
return Err(CoolError::Validation(format!(
"field '{field}' length {len} exceeds maximum {max}",
)));
}
Ok(())
}
pub fn validate_range_i64(
field: &'static str,
value: i64,
min: Option<i64>,
max: Option<i64>,
) -> Result<(), CoolError> {
if let Some(min) = min
&& value < min
{
return Err(CoolError::Validation(format!(
"field '{field}' is below minimum {min}",
)));
}
if let Some(max) = max
&& value > max
{
return Err(CoolError::Validation(format!(
"field '{field}' exceeds maximum {max}",
)));
}
Ok(())
}
pub fn validate_range_decimal(
field: &'static str,
value: &Decimal,
min: Option<i64>,
max: Option<i64>,
) -> Result<(), CoolError> {
if let Some(min) = min {
let bound = Decimal::from(min);
if *value < bound {
return Err(CoolError::Validation(format!(
"field '{field}' is below minimum {min}",
)));
}
}
if let Some(max) = max {
let bound = Decimal::from(max);
if *value > bound {
return Err(CoolError::Validation(format!(
"field '{field}' exceeds maximum {max}",
)));
}
}
Ok(())
}
pub fn validate_email(field: &'static str, value: &str) -> Result<(), CoolError> {
let trimmed = value.trim();
if trimmed.is_empty()
|| trimmed.chars().any(char::is_whitespace)
|| trimmed.chars().filter(|c| *c == '@').count() != 1
{
return Err(CoolError::Validation(format!(
"field '{field}' is not a valid email address",
)));
}
let (local, domain) = trimmed.split_once('@').unwrap();
if local.is_empty() || domain.is_empty() || !domain.contains('.') {
return Err(CoolError::Validation(format!(
"field '{field}' is not a valid email address",
)));
}
Ok(())
}
pub fn validate_uri(field: &'static str, value: &str) -> Result<(), CoolError> {
if url::Url::parse(value).is_err() {
return Err(CoolError::Validation(format!(
"field '{field}' is not a valid URI",
)));
}
Ok(())
}
pub fn validate_iso4217(field: &'static str, value: &str) -> Result<(), CoolError> {
if value.len() != 3 || !value.chars().all(|c| c.is_ascii_uppercase()) {
return Err(CoolError::Validation(format!(
"field '{field}' must be a 3-letter uppercase ISO 4217 code",
)));
}
Ok(())
}