ic_dbms_api/validate/
case.rs1use ic_dbms_api::prelude::Value;
2
3use crate::prelude::Validate;
4
5pub struct SnakeCaseValidator;
33
34impl Validate for SnakeCaseValidator {
35 fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
36 let Value::Text(text) = value else {
37 return Err(ic_dbms_api::prelude::IcDbmsError::Validation(
38 "RGB color validation requires a text value".to_string(),
39 ));
40 };
41
42 let s = &text.0;
43
44 let first_char = s.chars().next().ok_or_else(|| {
46 crate::prelude::IcDbmsError::Validation(
47 "Empty string is not valid snake_case".to_string(),
48 )
49 })?;
50 if !first_char.is_lowercase() && first_char != '_' {
51 return Err(crate::prelude::IcDbmsError::Validation(format!(
52 "Value '{s}' is not in snake_case format",
53 )));
54 }
55
56 if s.chars()
57 .all(|c| c.is_lowercase() || c.is_ascii_digit() || c == '_')
58 {
59 Ok(())
60 } else {
61 Err(crate::prelude::IcDbmsError::Validation(format!(
62 "Value '{s}' is not in snake_case format",
63 )))
64 }
65 }
66}
67
68pub struct KebabCaseValidator;
94
95impl Validate for KebabCaseValidator {
96 fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
97 let Value::Text(text) = value else {
98 return Err(ic_dbms_api::prelude::IcDbmsError::Validation(
99 "RGB color validation requires a text value".to_string(),
100 ));
101 };
102
103 let s = &text.0;
104
105 let first_char = s.chars().next().ok_or_else(|| {
107 crate::prelude::IcDbmsError::Validation(
108 "Empty string is not valid kebab-case".to_string(),
109 )
110 })?;
111 if !first_char.is_lowercase() {
112 return Err(crate::prelude::IcDbmsError::Validation(format!(
113 "Value '{s}' is not in kebab-case format",
114 )));
115 }
116
117 if s.chars()
118 .all(|c| c.is_lowercase() || c.is_ascii_digit() || c == '-')
119 {
120 Ok(())
121 } else {
122 Err(crate::prelude::IcDbmsError::Validation(format!(
123 "Value '{s}' is not in kebab-case format",
124 )))
125 }
126 }
127}
128
129pub struct CamelCaseValidator;
154
155impl Validate for CamelCaseValidator {
156 fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
157 let Value::Text(text) = value else {
158 return Err(ic_dbms_api::prelude::IcDbmsError::Validation(
159 "CamelCase validation requires a text value".to_string(),
160 ));
161 };
162
163 let s = &text.0;
164
165 let mut chars = s.chars();
166 let first_char = chars.next().ok_or_else(|| {
167 crate::prelude::IcDbmsError::Validation(
168 "Empty string is not valid CamelCase".to_string(),
169 )
170 })?;
171 if !first_char.is_uppercase() {
172 return Err(crate::prelude::IcDbmsError::Validation(format!(
173 "Value '{s}' is not in CamelCase format"
174 )));
175 }
176
177 if s.chars().all(|c| c.is_alphanumeric()) {
178 Ok(())
179 } else {
180 Err(crate::prelude::IcDbmsError::Validation(format!(
181 "Value '{}' is not in CamelCase format",
182 s
183 )))
184 }
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use ic_dbms_api::prelude::Value;
191
192 use super::*;
193
194 #[test]
195 fn test_snake_case_validator() {
196 let validator = SnakeCaseValidator;
197
198 let value = Value::Text(ic_dbms_api::prelude::Text("valid_snake_case".to_string()));
200 assert!(validator.validate(&value).is_ok());
201
202 let value = Value::Text(ic_dbms_api::prelude::Text("Invalid_Snake_Case".to_string()));
204 assert!(validator.validate(&value).is_err());
205
206 let value = Value::Text(ic_dbms_api::prelude::Text(
208 "invalid-snake-case!".to_string(),
209 ));
210 assert!(validator.validate(&value).is_err());
211
212 let value = Value::Text(ic_dbms_api::prelude::Text(
214 "1invalid_snake_case".to_string(),
215 ));
216 assert!(validator.validate(&value).is_err());
217
218 let value = Value::Text(ic_dbms_api::prelude::Text("_valid_snake_case".to_string()));
220 assert!(validator.validate(&value).is_ok());
221
222 let value = Value::Text(ic_dbms_api::prelude::Text("".to_string()));
224 assert!(validator.validate(&value).is_err());
225
226 let value = Value::Int32(123i32.into());
227 assert!(validator.validate(&value).is_err());
228 }
229
230 #[test]
231 fn test_kebab_case_validator() {
232 let validator = KebabCaseValidator;
233
234 let value = Value::Text(ic_dbms_api::prelude::Text("valid-kebab-case".to_string()));
236 assert!(validator.validate(&value).is_ok());
237
238 let value = Value::Text(ic_dbms_api::prelude::Text("Invalid-Kebab-Case".to_string()));
240 assert!(validator.validate(&value).is_err());
241
242 let value = Value::Text(ic_dbms_api::prelude::Text(
244 "invalid-kebab-case!".to_string(),
245 ));
246 assert!(validator.validate(&value).is_err());
247
248 let value = Value::Text(ic_dbms_api::prelude::Text("".to_string()));
250 assert!(validator.validate(&value).is_err());
251
252 let value = Value::Text(ic_dbms_api::prelude::Text(
254 "1invalid-kebab-case".to_string(),
255 ));
256 assert!(validator.validate(&value).is_err());
257
258 let value = Value::Int32(123i32.into());
259 assert!(validator.validate(&value).is_err());
260 }
261
262 #[test]
263 fn test_camel_case_validator() {
264 let validator = CamelCaseValidator;
265 let value = Value::Text(ic_dbms_api::prelude::Text("ValidCamelCase".to_string()));
267 assert!(validator.validate(&value).is_ok());
268 let value = Value::Text(ic_dbms_api::prelude::Text("invalidCamelCase".to_string()));
270 assert!(validator.validate(&value).is_err());
271 let value = Value::Text(ic_dbms_api::prelude::Text("Invalid-CamelCase!".to_string()));
273 assert!(validator.validate(&value).is_err());
274 let value = Value::Text(ic_dbms_api::prelude::Text("Invalid_CamelCase".to_string()));
276 assert!(validator.validate(&value).is_err());
277
278 let value = Value::Text(ic_dbms_api::prelude::Text("".to_string()));
280 assert!(validator.validate(&value).is_err());
281
282 let value = Value::Int32(123i32.into());
283 assert!(validator.validate(&value).is_err());
284 }
285}