libgir/config/
properties.rs
1use log::error;
2use toml::Value;
3
4use super::{
5 error::TomlHelper, gobjects::GStatus, ident::Ident, parsable::Parse,
6 property_generate_flags::PropertyGenerateFlags,
7};
8use crate::version::Version;
9
10#[derive(Clone, Debug)]
11pub struct Property {
12 pub ident: Ident,
13 pub status: GStatus,
14 pub version: Option<Version>,
15 pub generate: Option<PropertyGenerateFlags>,
16 pub bypass_auto_rename: bool,
17 pub doc_trait_name: Option<String>,
18 pub generate_doc: bool,
19}
20
21impl Parse for Property {
22 fn parse(toml: &Value, object_name: &str) -> Option<Self> {
23 let Some(ident) = Ident::parse(toml, object_name, "property") else {
24 error!(
25 "No 'name' or 'pattern' given for property for object {}",
26 object_name
27 );
28 return None;
29 };
30
31 toml.check_unwanted(
32 &[
33 "ignore",
34 "manual",
35 "version",
36 "name",
37 "pattern",
38 "generate",
39 "bypass_auto_rename",
40 "doc_trait_name",
41 "generate_doc",
42 ],
43 &format!("property {object_name}"),
44 );
45
46 let status = {
47 if toml
48 .lookup("ignore")
49 .and_then(Value::as_bool)
50 .unwrap_or(false)
51 {
52 GStatus::Ignore
53 } else if toml
54 .lookup("manual")
55 .and_then(Value::as_bool)
56 .unwrap_or(false)
57 {
58 GStatus::Manual
59 } else {
60 GStatus::Generate
61 }
62 };
63 let version = toml
64 .lookup("version")
65 .and_then(Value::as_str)
66 .and_then(|s| s.parse().ok());
67 let generate = toml.lookup("generate").and_then(|v| {
68 PropertyGenerateFlags::parse_flags(v, "generate")
69 .map_err(|e| error!("{} for object {}", e, object_name))
70 .ok()
71 });
72 let bypass_auto_rename = toml
73 .lookup("bypass_auto_rename")
74 .and_then(Value::as_bool)
75 .unwrap_or(false);
76 let doc_trait_name = toml
77 .lookup("doc_trait_name")
78 .and_then(Value::as_str)
79 .map(ToOwned::to_owned);
80 let generate_doc = toml
81 .lookup("generate_doc")
82 .and_then(Value::as_bool)
83 .unwrap_or(true);
84
85 Some(Self {
86 ident,
87 status,
88 version,
89 generate,
90 bypass_auto_rename,
91 doc_trait_name,
92 generate_doc,
93 })
94 }
95}
96
97impl AsRef<Ident> for Property {
98 fn as_ref(&self) -> &Ident {
99 &self.ident
100 }
101}
102
103pub type Properties = Vec<Property>;
104
105#[cfg(test)]
106mod tests {
107 use super::{
108 super::{
109 ident::Ident,
110 matchable::Matchable,
111 parsable::{Parsable, Parse},
112 },
113 *,
114 };
115 use crate::version::Version;
116
117 fn properties_toml(input: &str) -> ::toml::Value {
118 let mut value: ::toml::value::Table = ::toml::from_str(input).unwrap();
119 value.remove("f").unwrap()
120 }
121
122 fn toml(input: &str) -> ::toml::Value {
123 let value = input.parse();
124 assert!(value.is_ok());
125 value.unwrap()
126 }
127
128 #[test]
129 fn property_parse_ignore() {
130 let toml = toml(
131 r#"
132name = "prop1"
133ignore = true
134"#,
135 );
136 let p = Property::parse(&toml, "a").unwrap();
137 assert_eq!(p.ident, Ident::Name("prop1".into()));
138 assert!(p.status.ignored());
139 }
140
141 #[test]
142 fn property_parse_manual() {
143 let toml = toml(
144 r#"
145name = "prop1"
146manual = true
147"#,
148 );
149 let p = Property::parse(&toml, "a").unwrap();
150 assert_eq!(p.ident, Ident::Name("prop1".into()));
151 assert!(p.status.manual());
152 }
153
154 #[test]
155 fn property_bypass_auto_rename() {
156 let toml = toml(
157 r#"
158name = "prop1"
159bypass_auto_rename = true
160"#,
161 );
162 let f = Property::parse(&toml, "a").unwrap();
163 assert_eq!(f.ident, Ident::Name("prop1".into()));
164 assert!(f.bypass_auto_rename);
165 }
166
167 #[test]
168 fn property_parse_version_default() {
169 let toml = toml(
170 r#"
171name = "prop1"
172"#,
173 );
174 let p = Property::parse(&toml, "a").unwrap();
175 assert_eq!(p.version, None);
176 assert!(p.status.need_generate());
177 }
178
179 #[test]
180 fn property_parse_version() {
181 let toml = toml(
182 r#"
183name = "prop1"
184version = "3.20"
185"#,
186 );
187 let p = Property::parse(&toml, "a").unwrap();
188 assert_eq!(p.version, Some(Version::new(3, 20, 0)));
189 }
190
191 #[test]
192 fn property_generate_doc() {
193 let r = toml(
194 r#"
195name = "prop"
196generate_doc = false
197"#,
198 );
199 let p = Property::parse(&r, "a").unwrap();
200 assert!(!p.generate_doc);
201
202 let r = toml(
204 r#"
205name = "prop"
206"#,
207 );
208 let p = Property::parse(&r, "a").unwrap();
209 assert!(p.generate_doc);
210 }
211
212 #[test]
213 fn properties_parse_empty_for_none() {
214 let props = Properties::parse(None, "a");
215 assert!(props.is_empty());
216 }
217
218 #[test]
219 fn properties_parse_matches() {
220 let toml = properties_toml(
221 r#"
222[[f]]
223name = "prop1"
224[[f]]
225name = "p1.5"
226[[f]]
227name = "prop2"
228[[f]]
229pattern = 'prop\d+'
230"#,
231 );
232 let props = Properties::parse(Some(&toml), "a");
233 assert_eq!(props.len(), 3);
234
235 assert_eq!(props.matched("prop1").len(), 2);
236 assert_eq!(props.matched("prop2").len(), 2);
237 assert_eq!(props.matched("prop3").len(), 1);
238 assert_eq!(props.matched("p1.5").len(), 0);
240 assert_eq!(props.matched("none").len(), 0);
241 }
242}