use toml::Value;
pub fn allowed_values(input: &str, allowed_values: &Value) -> Result<(), String> {
if let Some(values) = allowed_values.as_array() {
let input_matches = values.iter().any(|value| {
if let Some(val_str) = value.as_str() {
val_str == input
} else if let Some(val_int) = value.as_integer() {
input.parse::<i64>().map(|i| i == val_int).unwrap_or(false)
} else if let Some(val_bool) = value.as_bool() {
input
.parse::<bool>()
.map(|b| b == val_bool)
.unwrap_or(false)
} else {
false
}
});
if input_matches {
Ok(())
} else {
let values_str = values
.iter()
.map(|v| match v {
Value::String(s) => format!("\"{}\"", s),
_ => v.to_string(),
})
.collect::<Vec<String>>()
.join(", ");
Err(format!("Input must be one of: {}", values_str))
}
} else {
Err("Invalid allowed_values format. Expected array.".to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
use toml::Value;
#[test]
fn test_allowed_values_valid() {
let allowed = Value::Array(vec![
Value::String("admin".to_string()),
Value::String("user".to_string()),
Value::String("guest".to_string()),
]);
assert!(allowed_values("admin", &allowed).is_ok());
assert!(allowed_values("user", &allowed).is_ok());
assert!(allowed_values("guest", &allowed).is_ok());
}
#[test]
fn test_allowed_values_invalid() {
let allowed = Value::Array(vec![
Value::String("admin".to_string()),
Value::String("user".to_string()),
Value::String("guest".to_string()),
]);
let result = allowed_values("moderator", &allowed);
assert!(result.is_err());
assert!(result
.clone()
.unwrap_err()
.contains("Input must be one of:"));
assert!(result.unwrap_err().contains("admin"));
}
#[test]
fn test_allowed_values_numbers() {
let allowed = Value::Array(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
assert!(allowed_values("1", &allowed).is_ok());
assert!(allowed_values("2", &allowed).is_ok());
let result = allowed_values("4", &allowed);
assert!(result.is_err());
}
}