yaml_schema/validation/
strings.rs1use log::debug;
2use regex::Regex;
3
4use crate::Context;
5use crate::Result;
6use crate::Validator;
7use crate::schemas::StringSchema;
8
9impl Validator for StringSchema {
10 fn validate(&self, context: &Context, value: &saphyr::MarkedYaml) -> Result<()> {
11 let errors = self.do_validate(value);
12 if !errors.is_empty() {
13 for error in errors {
14 context.add_error(value, error);
15 }
16 }
17 Ok(())
18 }
19}
20
21impl StringSchema {
22 fn do_validate(&self, value: &saphyr::MarkedYaml) -> Vec<String> {
23 debug!("do_validate: {:?}", value.data);
24 let mut errors = Vec::new();
25
26 if let saphyr::YamlData::Value(scalar) = &value.data
27 && let saphyr::Scalar::String(s) = scalar
28 {
29 let enum_strings = None;
31 debug!("enum_strings: {enum_strings:?}");
32 validate_string(
33 &mut errors,
34 self.min_length,
35 self.max_length,
36 self.pattern.as_ref(),
37 enum_strings.as_ref(),
38 s,
39 );
40 } else {
41 errors.push(format!("Expected a string, but got: {:?}", value.data));
42 }
43 errors
44 }
45}
46
47pub fn validate_string(
49 errors: &mut Vec<String>,
50 min_length: Option<usize>,
51 max_length: Option<usize>,
52 pattern: Option<&Regex>,
53 r#enum: Option<&Vec<String>>,
54 str_value: &str,
55) {
56 if let Some(min_length) = min_length
57 && str_value.len() < min_length
58 {
59 errors.push(format!("String is too short! (min length: {min_length})"));
60 }
61 if let Some(max_length) = max_length
62 && str_value.len() > max_length
63 {
64 errors.push(format!("String is too long! (max length: {max_length})"));
65 }
66 if let Some(regex) = pattern
67 && !regex.is_match(str_value)
68 {
69 errors.push(format!(
70 "String does not match regular expression {}!",
71 regex.as_str()
72 ));
73 }
74 if let Some(enum_values) = r#enum
75 && !enum_values.contains(&str_value.to_string())
76 {
77 errors.push(format!("String is not in enum: {enum_values:?}"));
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::Engine;
84 use crate::RootSchema;
85 use crate::YamlSchema;
86 use saphyr::LoadableYamlNode;
87
88 use super::*;
89
90 #[test]
91 fn test_engine_validate_string() {
92 let schema = StringSchema::default();
93 let root_schema = RootSchema::new(YamlSchema::typed_string(schema));
94 let context = Engine::evaluate(&root_schema, "some string", false).unwrap();
95 assert!(!context.has_errors());
96 }
97
98 #[test]
99 fn test_engine_validate_string_with_min_length() {
100 let schema = StringSchema {
101 min_length: Some(5),
102 ..Default::default()
103 };
104 let root_schema = RootSchema::new(YamlSchema::typed_string(schema));
105 let context = Engine::evaluate(&root_schema, "hello", false).unwrap();
106 assert!(!context.has_errors());
107 let context = Engine::evaluate(&root_schema, "hell", false).unwrap();
108 assert!(context.has_errors());
109 }
110
111 #[test]
112 fn test_validate_string() {
113 let mut errors = Vec::new();
114 validate_string(&mut errors, None, None, None, None, "hello");
115 assert!(errors.is_empty());
116 }
117
118 #[test]
119 fn test_validate_string_with_min_length() {
120 let mut errors = Vec::new();
121 validate_string(&mut errors, Some(5), None, None, None, "hello");
122 assert!(errors.is_empty());
123 validate_string(&mut errors, Some(5), None, None, None, "hell");
124 assert!(!errors.is_empty());
125 assert_eq!(
126 errors.first().unwrap(),
127 "String is too short! (min length: 5)"
128 );
129 }
130
131 #[test]
132 fn test_string_schema_validation() {
133 let schema = StringSchema::default();
134 let docs = saphyr::MarkedYaml::load_from_str("Washington").unwrap();
135 let value = docs.first().unwrap();
136 let context = Context::default();
137 let result = schema.validate(&context, value);
138 assert!(result.is_ok());
139 }
140
141 #[test]
142 fn test_string_schema_doesnt_validate_object() {
143 let yaml = "an: [arbitrarily, nested, data, structure]";
144 let doc = saphyr::MarkedYaml::load_from_str(yaml).unwrap();
145 let marked_yaml = doc.first().unwrap();
146 let string_schema: StringSchema = StringSchema::default();
147 let context = Context::default();
148 let result = string_schema.validate(&context, marked_yaml);
149 assert!(result.is_ok());
150 assert!(context.has_errors());
151 }
152}