libgir/config/
child_properties.rs
1use log::error;
2use toml::Value;
3
4use super::{error::TomlHelper, parsable::Parse};
5
6#[derive(Clone, Debug)]
7pub struct ChildProperty {
8 pub name: String,
9 pub rename_getter: Option<String>,
10 pub type_name: String,
11 pub doc_hidden: bool,
12 pub generate_doc: bool,
13}
14
15impl Parse for ChildProperty {
16 fn parse(toml: &Value, object_name: &str) -> Option<Self> {
17 let name = toml
18 .lookup("name")
19 .and_then(Value::as_str)
20 .map(ToOwned::to_owned);
21 let name = if let Some(name) = name {
22 name
23 } else {
24 error!("No child property name for `{}`", object_name);
25 return None;
26 };
27
28 toml.check_unwanted(
29 &["name", "type", "doc_hidden", "rename_getter"],
30 &format!("child property {object_name}"),
31 );
32
33 let type_name = toml
34 .lookup("type")
35 .and_then(Value::as_str)
36 .map(ToOwned::to_owned);
37 let type_name = if let Some(type_name) = type_name {
38 type_name
39 } else {
40 error!(
41 "No type for child property `{}` for `{}`",
42 name, object_name
43 );
44 return None;
45 };
46 let doc_hidden = toml
47 .lookup("doc_hidden")
48 .and_then(Value::as_bool)
49 .unwrap_or(false);
50 let rename_getter = toml
51 .lookup("rename_getter")
52 .and_then(Value::as_str)
53 .map(ToOwned::to_owned);
54 let generate_doc = toml
55 .lookup("generate_doc")
56 .and_then(Value::as_bool)
57 .unwrap_or(true);
58
59 Some(Self {
60 name,
61 rename_getter,
62 type_name,
63 doc_hidden,
64 generate_doc,
65 })
66 }
67}
68
69#[derive(Clone, Debug)]
70pub struct ChildProperties {
71 pub child_name: Option<String>,
72 pub child_type: Option<String>,
73 pub properties: Vec<ChildProperty>,
74}
75
76impl Parse for ChildProperties {
77 fn parse(toml_object: &Value, object_name: &str) -> Option<Self> {
78 let child_name = toml_object
79 .lookup("child_name")
80 .and_then(Value::as_str)
81 .map(ToOwned::to_owned);
82 let child_type = toml_object
83 .lookup("child_type")
84 .and_then(Value::as_str)
85 .map(ToOwned::to_owned);
86 let mut properties: Vec<ChildProperty> = Vec::new();
87 if let Some(configs) = toml_object.lookup("child_prop").and_then(Value::as_array) {
88 for config in configs {
89 if let Some(item) = ChildProperty::parse(config, object_name) {
90 properties.push(item);
91 }
92 }
93 }
94
95 if !properties.is_empty() {
96 Some(Self {
97 child_name,
98 child_type,
99 properties,
100 })
101 } else {
102 if child_name.is_some() {
103 error!("`{}` has child_name but no child_prop's", object_name);
104 }
105 if child_type.is_some() {
106 error!("`{}` has child_type but no child_prop's", object_name);
107 }
108 None
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::{super::parsable::Parse, *};
116
117 fn toml(input: &str) -> ::toml::Value {
118 let value = ::toml::from_str(input);
119 assert!(value.is_ok());
120 value.unwrap()
121 }
122
123 #[test]
124 fn child_property_parse() {
125 let toml = toml(
126 r#"
127name = "prop"
128type = "prop_type"
129"#,
130 );
131 let child = ChildProperty::parse(&toml, "a").unwrap();
132 assert_eq!("prop", child.name);
133 assert_eq!("prop_type", child.type_name);
134 }
135
136 #[test]
137 fn child_property_parse_generate_doc() {
138 let r = toml(
139 r#"
140name = "prop"
141type = "prop_type"
142generate_doc = false
143"#,
144 );
145 let child = ChildProperty::parse(&r, "a").unwrap();
146 assert!(!child.generate_doc);
147
148 let r = toml(
150 r#"
151name = "prop"
152type = "prop_type"
153"#,
154 );
155 let child = ChildProperty::parse(&r, "a").unwrap();
156 assert!(child.generate_doc);
157 }
158
159 #[test]
160 fn child_property_parse_not_all() {
161 let tml = toml(
162 r#"
163name = "prop"
164"#,
165 );
166 assert!(ChildProperty::parse(&tml, "a").is_none());
167
168 let tml = toml(
169 r#"
170type_name = "prop_type"
171"#,
172 );
173 assert!(ChildProperty::parse(&tml, "a").is_none());
174 }
175
176 #[test]
177 fn child_properties_parse() {
178 let toml = toml(
179 r#"
180child_name = "child_name"
181child_type = "child_type"
182[[child_prop]]
183name = "prop"
184type = "prop_type"
185[[child_prop]]
186name = "prop2"
187type = "prop_type2"
188"#,
189 );
190 let props = ChildProperties::parse(&toml, "a").unwrap();
191 assert_eq!(Some("child_name".into()), props.child_name);
192 assert_eq!(Some("child_type".into()), props.child_type);
193 assert_eq!(2, props.properties.len());
194 assert_eq!("prop", props.properties[0].name);
195 assert_eq!("prop_type", props.properties[0].type_name);
196 assert_eq!("prop2", props.properties[1].name);
197 assert_eq!("prop_type2", props.properties[1].type_name);
198 }
199
200 #[test]
201 fn child_property_no_parse_without_children() {
202 let toml = toml(
203 r#"
204child_name = "child_name"
205child_type = "child_type"
206"#,
207 );
208 let props = ChildProperties::parse(&toml, "a");
209 assert!(props.is_none());
210 }
211
212 #[test]
213 fn child_properties_parse_without_child_type_name() {
214 let toml = toml(
215 r#"
216[[child_prop]]
217name = "prop"
218type = "prop_type"
219"#,
220 );
221 let props = ChildProperties::parse(&toml, "a").unwrap();
222 assert_eq!(None, props.child_name);
223 assert_eq!(None, props.child_type);
224 assert_eq!(1, props.properties.len());
225 }
226
227 #[test]
228 fn child_properties_parse_without_child_type() {
229 let toml = toml(
230 r#"
231child_name = "child_name"
232[[child_prop]]
233name = "prop"
234type = "prop_type"
235"#,
236 );
237 let props = ChildProperties::parse(&toml, "a").unwrap();
238 assert_eq!(Some("child_name".into()), props.child_name);
239 assert_eq!(None, props.child_type);
240 assert_eq!(1, props.properties.len());
241 }
242
243 #[test]
244 fn child_properties_parse_without_child_name() {
245 let toml = toml(
246 r#"
247child_type = "child_type"
248[[child_prop]]
249name = "prop"
250type = "prop_type"
251"#,
252 );
253 let props = ChildProperties::parse(&toml, "a").unwrap();
254 assert_eq!(None, props.child_name);
255 assert_eq!(Some("child_type".into()), props.child_type);
256 assert_eq!(1, props.properties.len());
257 }
258}