ai_json_template/
ai_json_template_for_hashmap.rs1crate::ix!();
3
4impl<K, V> AiJsonTemplate for HashMap<K, V>
7where
8 K: Send + Sync + AiJsonTemplate + Eq + Hash + 'static,
9 V: Send + Sync + AiJsonTemplate + 'static,
10{
11 fn to_template() -> JsonValue {
12 trace!("AiJsonTemplate::to_template for HashMap<K, V>");
14
15 let mut obj = serde_json::Map::new();
16 obj.insert("type".to_string(), JsonValue::String("map_of".to_string()));
17
18 obj.insert("required".to_string(), JsonValue::Bool(true));
20
21 let key_schema = K::to_template();
25 let val_schema = V::to_template();
26 obj.insert("map_key_template".to_string(), key_schema);
27 obj.insert("map_value_template".to_string(), val_schema);
28
29 JsonValue::Object(obj)
30 }
31}
32
33impl<K, V> AiJsonTemplateWithJustification for HashMap<K, V>
36where
37 K: Send + Sync + AiJsonTemplate + Eq + Hash + 'static,
38 V: Send + Sync + AiJsonTemplate + 'static,
39{
40 fn to_template_with_justification() -> JsonValue {
41 trace!("AiJsonTemplateWithJustification::to_template_with_justification for HashMap<K, V>");
42
43 let mut obj = serde_json::Map::new();
45 obj.insert("type".to_string(), JsonValue::String("map_of".to_string()));
46 obj.insert("required".to_string(), JsonValue::Bool(true));
47 obj.insert("has_justification".to_string(), JsonValue::Bool(true));
48
49 let nested_key = K::to_template();
51 let nested_val = V::to_template();
52 obj.insert("map_key_template".to_string(), nested_key);
53 obj.insert("map_value_template".to_string(), nested_val);
54
55 JsonValue::Object(obj)
56 }
57}
58
59#[cfg(test)]
62mod test_hashmap_k_v {
63 use super::*;
64
65 #[derive(SaveLoad,Serialize,Deserialize,Debug, Clone)]
68 struct FakeLeaf {
69 label: String,
70 }
71
72 impl AiJsonTemplate for FakeLeaf {
73 fn to_template() -> JsonValue {
74 let mut obj = serde_json::Map::new();
75 obj.insert("type".to_string(), JsonValue::String("struct".to_string()));
76 obj.insert("struct_name".to_string(), JsonValue::String("FakeLeaf".into()));
77 let mut fields = serde_json::Map::new();
78 fields.insert("label".to_string(), {
79 let mut label_obj = serde_json::Map::new();
80 label_obj.insert("type".to_string(), JsonValue::String("string".into()));
81 label_obj.insert("required".to_string(), JsonValue::Bool(true));
82 label_obj.insert("generation_instructions".to_string(), JsonValue::String("A label string.".into()));
83 JsonValue::Object(label_obj)
84 });
85 obj.insert("fields".to_string(), JsonValue::Object(fields));
86 JsonValue::Object(obj)
87 }
88 }
89
90 impl AiJsonTemplateWithJustification for FakeLeaf {
91 fn to_template_with_justification() -> JsonValue {
92 let mut root = Self::to_template();
93 if let Some(obj) = root.as_object_mut() {
94 obj.insert("has_justification".to_string(), JsonValue::Bool(true));
95 }
96 root
97 }
98 }
99
100 #[traced_test]
101 fn test_hashmap_string_fakeleaf_schema() {
102 type MyHash = HashMap<String, FakeLeaf>;
103 let schema = <MyHash as AiJsonTemplate>::to_template();
104 assert!(schema.is_object(), "Should produce an object schema");
105
106 let schema_obj = schema.as_object().unwrap();
107 assert_eq!(schema_obj.get("type").unwrap(), "map_of");
108 assert!(schema_obj.contains_key("map_key_template"), "key template expected");
109 assert!(schema_obj.contains_key("map_value_template"), "value template expected");
110 }
111
112 #[traced_test]
113 fn test_hashmap_string_vec_fakeleaf_schema() {
114 type MyHash = HashMap<String, Vec<FakeLeaf>>;
116 let schema = <MyHash as AiJsonTemplate>::to_template();
117
118 assert!(schema.is_object(), "Should produce an object schema for map_of");
119 let so = schema.as_object().unwrap();
120 assert_eq!(so.get("type").unwrap(), "map_of");
121 let val_template = so.get("map_value_template").expect("no map_value_template?");
122 assert!(val_template.is_object(), "value template must be an object");
123 let val_obj = val_template.as_object().unwrap();
124 assert!(
126 val_obj.get("type").unwrap().as_str().unwrap().contains("array_of"),
127 "Expected an array_of type"
128 );
129 }
130
131 #[traced_test]
132 fn test_hashmap_justification() {
133 type MyHash = HashMap<String, FakeLeaf>;
134 let jschema = <MyHash as AiJsonTemplateWithJustification>::to_template_with_justification();
135 assert!(jschema.is_object());
136 let m = jschema.as_object().unwrap();
137 assert_eq!(m.get("type").unwrap(), "map_of");
138 assert_eq!(m.get("has_justification").unwrap(), &JsonValue::Bool(true));
139 let kv_template = m.get("map_key_template").unwrap();
140 let vv_template = m.get("map_value_template").unwrap();
141 assert!(kv_template.is_object(), "K justification must be object for the schema");
142 assert!(vv_template.is_object(), "V justification must be object for the schema");
143 }
144}