lmn_core/request_template/validators/
object.rs1use std::collections::HashMap;
2
3use crate::request_template::definition::TemplateDef;
4use crate::request_template::error::TemplateError;
5use crate::request_template::validators::Validator;
6
7pub struct ObjectDef {
10 pub composition: HashMap<String, String>,
12}
13
14pub struct ObjectValidator {
17 pub composition: HashMap<String, String>,
18}
19
20impl Validator for ObjectValidator {
21 fn validate(self, _name: &str) -> Result<TemplateDef, TemplateError> {
22 let composition = self
23 .composition
24 .into_iter()
25 .map(|(field, placeholder)| {
26 extract_plain_name(&placeholder)
27 .map(|n| (field, n.to_string()))
28 .ok_or_else(|| {
29 TemplateError::InvalidConstraint(format!(
30 "object composition value '{placeholder}' is not a valid \
31 placeholder — expected '{{{{name}}}}'"
32 ))
33 })
34 })
35 .collect::<Result<HashMap<_, _>, _>>()?;
36
37 Ok(TemplateDef::Object(ObjectDef { composition }))
38 }
39}
40
41fn extract_plain_name(s: &str) -> Option<&str> {
42 let inner = s.trim().strip_prefix("{{")?.strip_suffix("}}")?;
43 Some(inner.trim_end_matches(":global"))
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use crate::request_template::validators::Validator;
50
51 #[test]
52 fn validates_valid_composition() {
53 let comp = [("amount".to_string(), "{{price}}".to_string())]
54 .into_iter()
55 .collect();
56 assert!(ObjectValidator { composition: comp }.validate("x").is_ok());
57 }
58
59 #[test]
60 fn rejects_non_placeholder_value() {
61 let comp = [("amount".to_string(), "price".to_string())]
62 .into_iter()
63 .collect();
64 assert!(ObjectValidator { composition: comp }.validate("x").is_err());
65 }
66
67 #[test]
68 fn extract_plain_name_strips_braces() {
69 assert_eq!(extract_plain_name("{{name}}"), Some("name"));
70 }
71
72 #[test]
73 fn extract_plain_name_strips_global_suffix() {
74 assert_eq!(extract_plain_name("{{name:global}}"), Some("name"));
75 }
76
77 #[test]
78 fn extract_plain_name_returns_none_for_plain_string() {
79 assert_eq!(extract_plain_name("plain"), None);
80 }
81}