Skip to main content

reinhardt_rest/metadata/
validators.rs

1//! Field validator specifications for metadata
2
3use serde::{Deserialize, Serialize};
4
5/// Field validator specification
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct FieldValidator {
8	/// Type of validator (e.g., "email", "url", "regex", "min_length", "max_length")
9	pub validator_type: String,
10	/// Optional validator configuration (e.g., regex pattern, min/max values)
11	#[serde(skip_serializing_if = "Option::is_none")]
12	pub options: Option<serde_json::Value>,
13	/// Optional error message for validation failures
14	#[serde(skip_serializing_if = "Option::is_none")]
15	pub message: Option<String>,
16}
17
18impl FieldValidator {
19	/// Extracts regex pattern from validator options for OpenAPI schema generation
20	///
21	/// # Returns
22	///
23	/// Returns `Some(String)` containing the regex pattern if this is a regex validator
24	/// with a valid pattern option, otherwise returns `None`.
25	///
26	/// # Examples
27	///
28	/// ```
29	/// use reinhardt_rest::metadata::FieldValidator;
30	/// use serde_json::json;
31	///
32	/// let validator = FieldValidator {
33	///     validator_type: "regex".to_string(),
34	///     options: Some(json!({"pattern": "^[a-zA-Z0-9_]+$"})),
35	///     message: None,
36	/// };
37	///
38	/// assert_eq!(validator.extract_pattern(), Some("^[a-zA-Z0-9_]+$".to_string()));
39	/// ```
40	pub fn extract_pattern(&self) -> Option<String> {
41		if self.validator_type == "regex" {
42			self.options
43				.as_ref()
44				.and_then(|opts| opts.get("pattern"))
45				.and_then(|p| p.as_str())
46				.map(|s| s.to_string())
47		} else {
48			None
49		}
50	}
51}
52
53#[cfg(test)]
54mod tests {
55	use super::*;
56
57	#[test]
58	fn test_validator_with_options() {
59		let validator = FieldValidator {
60			validator_type: "range".to_string(),
61			options: Some(serde_json::json!({"min": 1, "max": 100})),
62			message: Some("Value must be between 1 and 100".to_string()),
63		};
64
65		assert_eq!(validator.validator_type, "range");
66		assert!(validator.options.is_some());
67
68		let options = validator.options.as_ref().unwrap();
69		assert_eq!(options["min"], 1);
70		assert_eq!(options["max"], 100);
71	}
72
73	#[test]
74	fn test_validator_serialization() {
75		let validator = FieldValidator {
76			validator_type: "custom".to_string(),
77			options: Some(serde_json::json!({"key": "value"})),
78			message: Some("Custom validation failed".to_string()),
79		};
80
81		let json = serde_json::to_string(&validator).unwrap();
82		assert!(json.contains("custom"));
83		assert!(json.contains("Custom validation failed"));
84	}
85}