aviso_validators/string.rs
1// (C) Copyright 2024- ECMWF and individual contributors.
2//
3// This software is licensed under the terms of the Apache Licence Version 2.0
4// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5// In applying this licence, ECMWF does not waive the privileges and immunities
6// granted to it by virtue of its status as an intergovernmental organisation nor
7// does it submit to any jurisdiction.
8
9//! String validation and canonicalization
10//!
11//! Provides validation for string fields with configurable length constraints.
12//! Ensures strings are non-empty and within specified length limits.
13
14use anyhow::{Result, bail};
15
16/// String validation handler
17///
18/// Validates string fields according to the following rules:
19/// - Must not be empty (required for all string fields)
20/// - Must not exceed maximum length if specified
21/// - Returns the original string if valid (no canonicalization needed)
22pub struct StringHandler;
23
24impl StringHandler {
25 /// Validate and canonicalize a string value
26 ///
27 /// # Arguments
28 /// * `value` - The string value to validate
29 /// * `max_length` - Optional maximum length constraint
30 /// * `field_name` - Name of the field (for error messages)
31 ///
32 /// # Returns
33 /// * `Ok(String)` - The validated string (unchanged)
34 /// * `Err(anyhow::Error)` - Validation failed with detailed error
35 pub fn validate_and_canonicalize(
36 value: &str,
37 max_length: Option<usize>,
38 field_name: &str,
39 ) -> Result<String> {
40 // Check for empty strings (not allowed)
41 if value.is_empty() {
42 bail!("Field '{}' cannot be empty", field_name);
43 }
44
45 // Check maximum length constraint if specified
46 if let Some(max_len) = max_length
47 && value.len() > max_len
48 {
49 bail!(
50 "Field '{}' exceeds maximum length of {} characters, got: {}",
51 field_name,
52 max_len,
53 value.len()
54 );
55 }
56
57 // String is valid, return as-is (no canonicalization needed)
58 Ok(value.to_string())
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_valid_string() {
68 let result = StringHandler::validate_and_canonicalize("test", Some(10), "field");
69 assert!(result.is_ok());
70 assert_eq!(result.unwrap(), "test");
71 }
72
73 #[test]
74 fn test_empty_string_fails() {
75 let result = StringHandler::validate_and_canonicalize("", Some(10), "field");
76 assert!(result.is_err());
77 assert!(result.unwrap_err().to_string().contains("cannot be empty"));
78 }
79
80 #[test]
81 fn test_too_long_string_fails() {
82 let result = StringHandler::validate_and_canonicalize("toolong", Some(5), "field");
83 assert!(result.is_err());
84 assert!(
85 result
86 .unwrap_err()
87 .to_string()
88 .contains("exceeds maximum length")
89 );
90 }
91
92 #[test]
93 fn test_no_length_limit() {
94 let result = StringHandler::validate_and_canonicalize("very long string", None, "field");
95 assert!(result.is_ok());
96 }
97}