ai_agent/utils/
env_validation.rs1use serde::Serialize;
4
5#[derive(Debug, Clone, Serialize)]
7pub struct EnvVarValidationResult {
8 pub effective: i64,
10 pub status: ValidationStatus,
12 #[serde(skip_serializing_if = "Option::is_none")]
14 pub message: Option<String>,
15}
16
17#[derive(Debug, Clone, Serialize)]
19#[serde(rename_all = "snake_case")]
20pub enum ValidationStatus {
21 Valid,
22 Capped,
23 Invalid,
24}
25
26pub fn validate_bounded_int_env_var(
28 name: &str,
29 value: Option<&str>,
30 default_value: i64,
31 upper_limit: i64,
32) -> EnvVarValidationResult {
33 let Some(value) = value else {
34 return EnvVarValidationResult {
35 effective: default_value,
36 status: ValidationStatus::Valid,
37 message: None,
38 };
39 };
40
41 let parsed = value.parse::<i64>();
42 if let Ok(parsed) = parsed {
43 if parsed <= 0 {
44 let message =
45 format!("Invalid value \"{}\" (using default: {})", value, default_value);
46 eprintln!("{} {}", name, message);
47 return EnvVarValidationResult {
48 effective: default_value,
49 status: ValidationStatus::Invalid,
50 message: Some(message),
51 };
52 }
53
54 if parsed > upper_limit {
55 let message = format!("Capped from {} to {}", parsed, upper_limit);
56 eprintln!("{} {}", name, message);
57 return EnvVarValidationResult {
58 effective: upper_limit,
59 status: ValidationStatus::Capped,
60 message: Some(message),
61 };
62 }
63
64 return EnvVarValidationResult {
65 effective: parsed,
66 status: ValidationStatus::Valid,
67 message: None,
68 };
69 }
70
71 let message = format!("Invalid value \"{}\" (using default: {})", value, default_value);
72 eprintln!("{} {}", name, message);
73 EnvVarValidationResult {
74 effective: default_value,
75 status: ValidationStatus::Invalid,
76 message: Some(message),
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_default_when_none() {
86 let result = validate_bounded_int_env_var("TEST_VAR", None, 10, 100);
87 assert_eq!(result.effective, 10);
88 assert!(matches!(result.status, ValidationStatus::Valid));
89 }
90
91 #[test]
92 fn test_valid_value() {
93 let result = validate_bounded_int_env_var("TEST_VAR", Some("50"), 10, 100);
94 assert_eq!(result.effective, 50);
95 assert!(matches!(result.status, ValidationStatus::Valid));
96 }
97
98 #[test]
99 fn test_capped_value() {
100 let result = validate_bounded_int_env_var("TEST_VAR", Some("200"), 10, 100);
101 assert_eq!(result.effective, 100);
102 assert!(matches!(result.status, ValidationStatus::Capped));
103 }
104
105 #[test]
106 fn test_invalid_value() {
107 let result = validate_bounded_int_env_var("TEST_VAR", Some("abc"), 10, 100);
108 assert_eq!(result.effective, 10);
109 assert!(matches!(result.status, ValidationStatus::Invalid));
110 }
111
112 #[test]
113 fn test_negative_value() {
114 let result = validate_bounded_int_env_var("TEST_VAR", Some("-5"), 10, 100);
115 assert_eq!(result.effective, 10);
116 assert!(matches!(result.status, ValidationStatus::Invalid));
117 }
118}