aviso_validators/
enum_handler.rs1use anyhow::{Result, bail};
16
17pub struct EnumHandler;
18
19impl EnumHandler {
20 pub fn validate_and_canonicalize(
40 value: &str,
41 allowed_values: &[String],
42 field_name: &str,
43 ) -> Result<String> {
44 let lowercase_value = value.to_lowercase();
46
47 let is_valid = allowed_values
49 .iter()
50 .any(|allowed| allowed.to_lowercase() == lowercase_value);
51
52 if is_valid {
53 tracing::debug!(
54 field_name = field_name,
55 input_value = value,
56 canonical_value = %lowercase_value,
57 allowed_count = allowed_values.len(),
58 "Enum value successfully validated and canonicalized"
59 );
60
61 Ok(lowercase_value)
62 } else {
63 bail!(
64 "Field '{}' has invalid value '{}'. Allowed: [{}]",
65 field_name,
66 value,
67 allowed_values.join(", ")
68 );
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn test_valid_enum_value_exact_case() {
79 let allowed = vec![
80 "active".to_string(),
81 "inactive".to_string(),
82 "pending".to_string(),
83 ];
84 let result = EnumHandler::validate_and_canonicalize("active", &allowed, "status");
85 assert!(result.is_ok());
86 assert_eq!(result.unwrap(), "active");
87 }
88
89 #[test]
90 fn test_valid_enum_value_different_case() {
91 let allowed = vec!["active".to_string(), "inactive".to_string()];
92 let result = EnumHandler::validate_and_canonicalize("ACTIVE", &allowed, "status");
93 assert!(result.is_ok());
94 assert_eq!(result.unwrap(), "active");
95 }
96
97 #[test]
98 fn test_valid_enum_value_mixed_case() {
99 let allowed = vec!["Active".to_string(), "InActive".to_string()];
100 let result = EnumHandler::validate_and_canonicalize("active", &allowed, "status");
101 assert!(result.is_ok());
102 assert_eq!(result.unwrap(), "active");
103 }
104
105 #[test]
106 fn test_invalid_enum_value() {
107 let allowed = vec!["active".to_string(), "inactive".to_string()];
108 let result = EnumHandler::validate_and_canonicalize("unknown", &allowed, "status");
109 assert!(result.is_err());
110 }
111
112 #[test]
113 fn test_empty_allowed_values() {
114 let allowed = vec![];
115 let result = EnumHandler::validate_and_canonicalize("any", &allowed, "field");
116 assert!(result.is_err());
117 }
118
119 #[test]
120 fn test_large_allowed_values_list() {
121 let allowed: Vec<String> = (0..20).map(|i| format!("value{}", i)).collect();
122 let result = EnumHandler::validate_and_canonicalize("unknown", &allowed, "field");
123 assert!(result.is_err());
124 }
125}