1use std::{
2 path::{Path, PathBuf},
3 str::FromStr,
4};
5
6use log::{trace, warn};
7
8use crate::{
9 library::*,
10 version::Version,
11 xmlparser::{Element, XmlParser},
12};
13
14const EMPTY_CTYPE: &str = "/*EMPTY*/";
15
16pub fn is_empty_c_type(c_type: &str) -> bool {
17 c_type == EMPTY_CTYPE
18}
19
20impl Library {
21 pub fn read_file<P: AsRef<Path>>(
22 &mut self,
23 dirs: &[P],
24 libs: &mut Vec<String>,
25 ) -> Result<(), String> {
26 for dir in dirs {
27 let dir: &Path = dir.as_ref();
28 let file_name = make_file_name(dir, &libs[libs.len() - 1]);
29 let Ok(mut parser) = XmlParser::from_path(&file_name) else {
30 continue;
31 };
32 return parser.document(|p, _| {
33 p.element_with_name("repository", |sub_parser, _elem| {
34 self.read_repository(dirs, sub_parser, libs)
35 })
36 });
37 }
38 Err(format!("Couldn't find `{}`...", &libs[libs.len() - 1]))
39 }
40
41 fn read_repository<P: AsRef<Path>>(
42 &mut self,
43 dirs: &[P],
44 parser: &mut XmlParser<'_>,
45 libs: &mut Vec<String>,
46 ) -> Result<(), String> {
47 let mut packages = Vec::new();
48 let mut includes = Vec::new();
49 parser.elements(|parser, elem| match elem.name() {
50 "include" => {
51 match (elem.attr("name"), elem.attr("version")) {
52 (Some(name), Some(ver)) => {
53 if self.find_namespace(name).is_none() {
54 let lib = format!("{name}-{ver}");
55 if libs.iter().any(|x| *x == lib) {
56 return Err(format!(
57 "`{}` includes itself (full path:`{}`)!",
58 lib,
59 libs.join("::")
60 ));
61 }
62 libs.push(lib);
63 self.read_file(dirs, libs)?;
64 libs.pop();
65 }
66 }
67 (Some(name), None) => includes.push(name.to_owned()),
68 _ => {}
69 }
70 Ok(())
71 }
72 "package" => {
73 let name = elem.attr_required("name")?;
74 packages.push(name.to_owned());
75 Ok(())
76 }
77 "namespace" => self.read_namespace(
78 parser,
79 elem,
80 std::mem::take(&mut packages),
81 std::mem::take(&mut includes),
82 ),
83 "format" => parser.ignore_element(),
84 "attribute" => parser.ignore_element(),
85 _ => Err(parser.unexpected_element(elem)),
86 })?;
87 Ok(())
88 }
89
90 fn read_namespace(
91 &mut self,
92 parser: &mut XmlParser<'_>,
93 elem: &Element,
94 packages: Vec<String>,
95 c_includes: Vec<String>,
96 ) -> Result<(), String> {
97 let ns_name = elem.attr_required("name")?;
98 let ns_id = self.add_namespace(ns_name);
99
100 {
101 let ns = self.namespace_mut(ns_id);
102 ns.package_names = packages;
103 ns.c_includes = c_includes;
104 if let Some(s) = elem.attr("shared-library") {
105 ns.shared_library = s
106 .split(',')
107 .filter_map(|x| {
108 if !x.is_empty() {
109 Some(String::from(x))
110 } else {
111 None
112 }
113 })
114 .collect();
115 }
116 if let Some(s) = elem.attr("identifier-prefixes") {
117 ns.identifier_prefixes = s.split(',').map(String::from).collect();
118 }
119 if let Some(s) = elem.attr("symbol-prefixes") {
120 ns.symbol_prefixes = s.split(',').map(String::from).collect();
121 }
122 }
123
124 trace!(
125 "Reading {}-{}",
126 ns_name,
127 elem.attr("version").unwrap_or("?")
128 );
129
130 parser.elements(|parser, elem| {
131 trace!("<{} name={:?}>", elem.name(), elem.attr("name"));
132 match elem.name() {
133 "class" => self.read_class(parser, ns_id, elem),
134 "record" => self.read_record_start(parser, ns_id, elem),
135 "union" => self.read_named_union(parser, ns_id, elem),
136 "interface" => self.read_interface(parser, ns_id, elem),
137 "callback" => self.read_named_callback(parser, ns_id, elem),
138 "bitfield" => self.read_bitfield(parser, ns_id, elem),
139 "enumeration" => self.read_enumeration(parser, ns_id, elem),
140 "function" => self.read_global_function(parser, ns_id, elem),
141 "constant" => self.read_constant(parser, ns_id, elem),
142 "alias" => self.read_alias(parser, ns_id, elem),
143 "boxed" | "function-macro" | "docsection" | "function-inline" => {
144 parser.ignore_element()
145 }
146 _ => {
147 warn!("<{} name={:?}>", elem.name(), elem.attr("name"));
148 parser.ignore_element()
149 }
150 }
151 })?;
152 Ok(())
153 }
154
155 fn read_class(
156 &mut self,
157 parser: &mut XmlParser<'_>,
158 ns_id: u16,
159 elem: &Element,
160 ) -> Result<(), String> {
161 let class_name = elem.attr_required("name")?;
162 let c_type = self.read_object_c_type(parser, elem)?;
163 let symbol_prefix = elem.attr_required("symbol-prefix").map(ToOwned::to_owned)?;
164 let type_struct = elem.attr("type-struct").map(ToOwned::to_owned);
165 let get_type = elem.attr_required("get-type")?;
166 let version = self.read_version(parser, ns_id, elem)?;
167 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
168 let is_fundamental = elem.attr("fundamental").is_some_and(|x| x == "1");
169 let (ref_fn, unref_fn) = if is_fundamental {
170 (
171 elem.attr("ref-func").map(ToOwned::to_owned),
172 elem.attr("unref-func").map(ToOwned::to_owned),
173 )
174 } else {
175 (None, None)
176 };
177
178 let is_abstract = elem.attr("abstract").is_some_and(|x| x == "1");
179 let final_type = elem.attr("final").is_some_and(|x| x == "1");
180
181 let mut fns = Vec::new();
182 let mut signals = Vec::new();
183 let mut properties = Vec::new();
184 let mut impls = Vec::new();
185 let mut fields = Vec::new();
186 let mut vfns = Vec::new();
187 let mut doc = None;
188 let mut doc_deprecated = None;
189 let mut union_count = 1;
190
191 parser.elements(|parser, elem| match elem.name() {
192 "constructor" | "function" | "method" => {
193 self.read_function_to_vec(parser, ns_id, elem, &mut fns)
194 }
195 "implements" => self.read_type(parser, ns_id, elem).map(|r| {
196 impls.push(r.0);
197 }),
198 "signal" => self
199 .read_signal(parser, ns_id, elem)
200 .map(|s| signals.push(s)),
201 "property" => self
202 .read_property(parser, ns_id, elem, &symbol_prefix)
203 .map(|p| {
204 if let Some(p) = p {
205 properties.push(p);
206 }
207 }),
208 "field" => self.read_field(parser, ns_id, elem).map(|f| {
209 fields.push(f);
210 }),
211 "virtual-method" => self
212 .read_virtual_method(parser, ns_id, elem)
213 .map(|v| vfns.push(v)),
214 "doc" => parser.text().map(|t| doc = Some(t)),
215 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
216 "source-position" => parser.ignore_element(),
217 "union" => self
218 .read_union(parser, ns_id, elem, Some(class_name), Some(c_type))
219 .map(|mut u| {
220 let field_name = if let Some(field_name) = elem.attr("name") {
221 field_name.into()
222 } else {
223 format!("u{union_count}")
224 };
225
226 u = Union {
227 name: format!("{class_name}_{field_name}"),
228 c_type: Some(format!("{c_type}_{field_name}")),
229 ..u
230 };
231
232 let u_doc = u.doc.clone();
233 let ctype = u.c_type.clone();
234
235 fields.push(Field {
236 name: field_name,
237 typ: Type::union(self, u, ns_id),
238 doc: u_doc,
239 c_type: ctype,
240 ..Field::default()
241 });
242 union_count += 1;
243 }),
244 "attribute" => parser.ignore_element(),
245 _ => Err(parser.unexpected_element(elem)),
246 })?;
247
248 let parent = elem
249 .attr("parent")
250 .map(|s| self.find_or_stub_type(ns_id, s));
251 let typ = Type::Class(Class {
252 name: class_name.into(),
253 c_type: c_type.into(),
254 type_struct,
255 c_class_type: None, glib_get_type: get_type.into(),
257 fields,
258 functions: fns,
259 virtual_methods: vfns,
260 signals,
261 properties,
262 parent,
263 implements: impls,
264 final_type,
265 doc,
266 doc_deprecated,
267 version,
268 deprecated_version,
269 symbol_prefix,
270 is_abstract,
271 is_fundamental,
272 ref_fn,
273 unref_fn,
274 });
275 self.add_type(ns_id, class_name, typ);
276 Ok(())
277 }
278
279 fn read_record_start(
280 &mut self,
281 parser: &mut XmlParser<'_>,
282 ns_id: u16,
283 elem: &Element,
284 ) -> Result<(), String> {
285 if let Some(typ) = self.read_record(parser, ns_id, elem, None, None)? {
286 let name = typ.get_name();
287 self.add_type(ns_id, &name, typ);
288 }
289 Ok(())
290 }
291
292 fn read_record(
293 &mut self,
294 parser: &mut XmlParser<'_>,
295 ns_id: u16,
296 elem: &Element,
297 parent_name_prefix: Option<&str>,
298 parent_ctype_prefix: Option<&str>,
299 ) -> Result<Option<Type>, String> {
300 let record_name = elem.attr("name").unwrap_or_default();
301 if record_name.starts_with('_') {
303 parser.ignore_element()?;
304 return Ok(None);
305 }
306 let is_class_record = record_name.ends_with("Class");
307
308 let c_type = elem.attr("type").unwrap_or_default();
309 let symbol_prefix = elem.attr("symbol-prefix").map(ToOwned::to_owned);
310 let get_type = elem.attr("get-type").map(ToOwned::to_owned);
311 let gtype_struct_for = elem.attr("is-gtype-struct-for");
312 let version = self.read_version(parser, ns_id, elem)?;
313 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
314 let pointer = elem.attr_bool("pointer", false);
315 let disguised = elem.attr_bool("disguised", false);
316
317 let mut fields = Vec::new();
318 let mut fns = Vec::new();
319 let mut doc = None;
320 let mut doc_deprecated = None;
321 let mut union_count = 1;
322
323 parser.elements(|parser, elem| match elem.name() {
324 "constructor" | "function" | "method" => {
325 self.read_function_to_vec(parser, ns_id, elem, &mut fns)
326 }
327 "union" => self
328 .read_union(parser, ns_id, elem, Some(record_name), Some(c_type))
329 .map(|mut u| {
330 let field_name = if let Some(field_name) = elem.attr("name") {
331 field_name.into()
332 } else {
333 format!("u{union_count}")
334 };
335
336 u = Union {
337 name: format!(
338 "{}{}_{}",
339 parent_name_prefix.map_or_else(String::new, |s| { format!("{s}_") }),
340 record_name,
341 field_name
342 ),
343 c_type: Some(format!(
344 "{}{}_{}",
345 parent_ctype_prefix.map_or_else(String::new, |s| { format!("{s}_") }),
346 c_type,
347 field_name
348 )),
349 ..u
350 };
351
352 let u_doc = u.doc.clone();
353 let ctype = u.c_type.clone();
354
355 fields.push(Field {
356 name: field_name,
357 typ: Type::union(self, u, ns_id),
358 doc: u_doc,
359 c_type: ctype,
360 ..Field::default()
361 });
362 union_count += 1;
363 }),
364 "field" => {
365 self.read_field(parser, ns_id, elem).map(|mut f| {
366 if c_type == "GDate" {
368 if f.name == "julian_days" {
369 fields.push(f);
370 } else if f.name == "julian" {
371 f.name = "flags_dmy".into();
372 f.typ = TypeId::tid_uint32();
373 f.c_type = Some("guint".into());
374 f.bits = None;
375 fields.push(f);
376 } else {
377 }
379 return;
380 }
381 if c_type == "GValue" && f.name == "data" {
383 f.c_type = Some("GValue_data".into());
384 }
385 fields.push(f);
386 })
387 }
388 "doc" => parser.text().map(|t| doc = Some(t)),
389 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
390 "source-position" => parser.ignore_element(),
391 "attribute" => parser.ignore_element(),
392 "method-inline" => parser.ignore_element(),
393 _ => Err(parser.unexpected_element(elem)),
394 })?;
395
396 let typ = Type::Record(Record {
397 name: record_name.into(),
398 c_type: c_type.into(),
399 glib_get_type: get_type,
400 functions: if is_class_record && gtype_struct_for.is_some() {
401 fns.into_iter()
402 .map(|mut f| {
403 f.kind = FunctionKind::ClassMethod;
404 f
405 })
406 .collect::<Vec<_>>()
407 } else {
408 fns
409 },
410 gtype_struct_for: gtype_struct_for.map(|s| s.into()),
411 fields,
412 version,
413 deprecated_version,
414 doc,
415 doc_deprecated,
416 disguised,
417 pointer,
418 symbol_prefix,
419 });
420
421 Ok(Some(typ))
422 }
423
424 fn read_named_union(
425 &mut self,
426 parser: &mut XmlParser<'_>,
427 ns_id: u16,
428 elem: &Element,
429 ) -> Result<(), String> {
430 elem.attr_required("name")?;
432
433 self.read_union(parser, ns_id, elem, None, None)
434 .and_then(|mut u| {
435 assert_ne!(u.name, "");
436 if u.name == "_Value__data__union" {
438 u.c_type = Some("GValue_data".into());
439 } else if u.c_type.is_none() {
440 return Err(parser.fail("Missing union c:type"));
441 }
442 let union_name = u.name.clone();
443 self.add_type(ns_id, &union_name, Type::Union(u));
444 Ok(())
445 })
446 }
447
448 fn read_union(
449 &mut self,
450 parser: &mut XmlParser<'_>,
451 ns_id: u16,
452 elem: &Element,
453 parent_name_prefix: Option<&str>,
454 parent_ctype_prefix: Option<&str>,
455 ) -> Result<Union, String> {
456 let union_name = elem.attr("name").unwrap_or("");
457 let c_type = self.read_object_c_type(parser, elem).unwrap_or("");
458 let get_type = elem.attr("get-type").map(|s| s.into());
459 let symbol_prefix = elem.attr("symbol-prefix").map(ToOwned::to_owned);
460
461 let mut fields = Vec::new();
462 let mut fns = Vec::new();
463 let mut doc = None;
464 let mut struct_count = 1;
465
466 parser.elements(|parser, elem| match elem.name() {
467 "source-position" => parser.ignore_element(),
468 "field" => self.read_field(parser, ns_id, elem).map(|f| {
469 fields.push(f);
470 }),
471 "constructor" | "function" | "method" => {
472 self.read_function_to_vec(parser, ns_id, elem, &mut fns)
473 }
474 "record" => {
475 let mut r = match self.read_record(
476 parser,
477 ns_id,
478 elem,
479 parent_name_prefix,
480 parent_ctype_prefix,
481 )? {
482 Some(Type::Record(r)) => r,
483 _ => return Ok(()),
484 };
485
486 let field_name = if let Some(field_name) = elem.attr("name") {
487 field_name.into()
488 } else {
489 format!("s{struct_count}")
490 };
491
492 r = Record {
493 name: format!(
494 "{}{}_{}",
495 parent_name_prefix.map_or_else(String::new, |s| { format!("{s}_") }),
496 union_name,
497 field_name
498 ),
499 c_type: format!(
500 "{}{}_{}",
501 parent_ctype_prefix.map_or_else(String::new, |s| { format!("{s}_") }),
502 c_type,
503 field_name
504 ),
505 ..r
506 };
507
508 let r_doc = r.doc.clone();
509 let ctype = r.c_type.clone();
510
511 fields.push(Field {
512 name: field_name,
513 typ: Type::record(self, r, ns_id),
514 doc: r_doc,
515 c_type: Some(ctype),
516 ..Field::default()
517 });
518
519 struct_count += 1;
520
521 Ok(())
522 }
523 "doc" => parser.text().map(|t| doc = Some(t)),
524 "attribute" => parser.ignore_element(),
525 _ => Err(parser.unexpected_element(elem)),
526 })?;
527
528 Ok(Union {
529 name: union_name.into(),
530 c_type: Some(c_type.into()),
531 glib_get_type: get_type,
532 fields,
533 functions: fns,
534 doc,
535 symbol_prefix,
536 })
537 }
538
539 fn read_virtual_method(
540 &mut self,
541 parser: &mut XmlParser,
542 ns_id: u16,
543 elem: &Element,
544 ) -> Result<Function, String> {
545 let method_name = elem.attr_required("name")?;
546 let version = self.read_version(parser, ns_id, elem)?;
547 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
548 let c_identifier = elem.attr("identifier").or_else(|| elem.attr("name"));
549 let mut params = Vec::new();
550 let mut ret = None;
551 let mut doc = None;
552 let mut doc_deprecated = None;
553
554 parser.elements(|parser, elem| match elem.name() {
555 "parameters" => self
556 .read_parameters(parser, ns_id, true, true)
557 .map(|mut ps| params.append(&mut ps)),
558 "return-value" => {
559 if ret.is_some() {
560 return Err(parser.fail("Too many <return-value> elements"));
561 }
562 self.read_parameter(parser, ns_id, elem, true, false)
563 .map(|p| ret = Some(p))
564 }
565 "source-position" => parser.ignore_element(),
566 "doc" => parser.text().map(|t| doc = Some(t)),
567 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
568 "attribute" => parser.ignore_element(),
569 _ => Err(parser.unexpected_element(elem)),
570 })?;
571
572 let throws = elem.attr_bool("throws", false);
573 if throws {
574 params.push(Parameter {
575 name: "error".into(),
576 typ: self.find_or_stub_type(ns_id, "GLib.Error"),
577 c_type: "GError**".into(),
578 instance_parameter: false,
579 direction: ParameterDirection::Out,
580 transfer: Transfer::Full,
581 caller_allocates: false,
582 nullable: Nullable(true),
583 array_length: None,
584 is_error: true,
585 doc: None,
586 scope: ParameterScope::None,
587 closure: None,
588 destroy: None,
589 });
590 }
591
592 if let Some(ret) = ret {
593 Ok(Function {
594 name: method_name.into(),
595 c_identifier: c_identifier.map(|s| s.into()),
596 kind: FunctionKind::VirtualMethod,
597 parameters: params,
598 ret,
599 throws,
600 version,
601 deprecated_version,
602 doc,
603 doc_deprecated,
604 get_property: None,
605 set_property: None,
606 finish_func: None,
607 async_func: None,
608 sync_func: None,
609 })
610 } else {
611 Err(parser.fail("Missing <return-value> element"))
612 }
613 }
614
615 fn read_field(
616 &mut self,
617 parser: &mut XmlParser<'_>,
618 ns_id: u16,
619 elem: &Element,
620 ) -> Result<Field, String> {
621 let field_name = elem.attr_required("name")?;
622 let private = elem.attr_bool("private", false);
623 let bits = elem.attr("bits").and_then(|s| s.parse().ok());
624
625 let mut typ = None;
626 let mut doc = None;
627
628 parser.elements(|parser, elem| match elem.name() {
629 "type" | "array" => {
630 if typ.is_some() {
631 return Err(parser.fail("Too many <type> elements"));
632 }
633 self.read_type(parser, ns_id, elem).map(|t| {
634 typ = Some(t);
635 })
636 }
637 "callback" => {
638 if typ.is_some() {
639 return Err(parser.fail("Too many <type> elements"));
640 }
641 self.read_function(parser, ns_id, elem.name(), elem, true)
642 .map(|f| {
643 typ = Some((Type::function(self, f), None, None));
644 })
645 }
646 "doc" => parser.text().map(|t| doc = Some(t)),
647 "attribute" => parser.ignore_element(),
648 _ => Err(parser.unexpected_element(elem)),
649 })?;
650
651 if let Some((tid, c_type, array_length)) = typ {
652 Ok(Field {
653 name: field_name.into(),
654 typ: tid,
655 c_type,
656 private,
657 bits,
658 array_length,
659 doc,
660 })
661 } else {
662 Err(parser.fail("Missing <type> element"))
663 }
664 }
665
666 fn read_named_callback(
667 &mut self,
668 parser: &mut XmlParser<'_>,
669 ns_id: u16,
670 elem: &Element,
671 ) -> Result<(), String> {
672 self.read_function_if_not_moved(parser, ns_id, elem.name(), elem, true)?
673 .map(|func| {
674 let name = func.name.clone();
675 self.add_type(ns_id, &name, Type::Function(func))
676 });
677
678 Ok(())
679 }
680
681 fn read_interface(
682 &mut self,
683 parser: &mut XmlParser<'_>,
684 ns_id: u16,
685 elem: &Element,
686 ) -> Result<(), String> {
687 let interface_name = elem.attr_required("name")?;
688 let c_type = self.read_object_c_type(parser, elem)?;
689 let symbol_prefix = elem.attr_required("symbol-prefix").map(ToOwned::to_owned)?;
690 let type_struct = elem.attr("type-struct").map(ToOwned::to_owned);
691 let get_type = elem.attr_required("get-type")?;
692 let version = self.read_version(parser, ns_id, elem)?;
693 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
694
695 let mut fns = Vec::new();
696 let mut vfns = Vec::new();
697 let mut signals = Vec::new();
698 let mut properties = Vec::new();
699 let mut prereqs = Vec::new();
700 let mut doc = None;
701 let mut doc_deprecated = None;
702
703 parser.elements(|parser, elem| match elem.name() {
704 "constructor" | "function" | "method" => {
705 self.read_function_to_vec(parser, ns_id, elem, &mut fns)
706 }
707 "prerequisite" => self.read_type(parser, ns_id, elem).map(|r| {
708 prereqs.push(r.0);
709 }),
710 "signal" => self
711 .read_signal(parser, ns_id, elem)
712 .map(|s| signals.push(s)),
713 "property" => self
714 .read_property(parser, ns_id, elem, &symbol_prefix)
715 .map(|p| {
716 if let Some(p) = p {
717 properties.push(p);
718 }
719 }),
720 "doc" => parser.text().map(|t| doc = Some(t)),
721 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
722 "virtual-method" => self
723 .read_virtual_method(parser, ns_id, elem)
724 .map(|v| vfns.push(v)),
725 "source-position" => parser.ignore_element(),
726 "attribute" => parser.ignore_element(),
727 _ => Err(parser.unexpected_element(elem)),
728 })?;
729
730 let typ = Type::Interface(Interface {
731 name: interface_name.into(),
732 c_type: c_type.into(),
733 type_struct,
734 c_class_type: None, glib_get_type: get_type.into(),
736 functions: fns,
737 virtual_methods: vfns,
738 signals,
739 properties,
740 prerequisites: prereqs,
741 doc,
742 doc_deprecated,
743 version,
744 deprecated_version,
745 symbol_prefix,
746 });
747 self.add_type(ns_id, interface_name, typ);
748 Ok(())
749 }
750
751 fn read_bitfield(
752 &mut self,
753 parser: &mut XmlParser<'_>,
754 ns_id: u16,
755 elem: &Element,
756 ) -> Result<(), String> {
757 let bitfield_name = elem.attr_required("name")?;
758 let c_type = self.read_object_c_type(parser, elem)?;
759 let symbol_prefix = elem.attr("symbol-prefix").map(ToOwned::to_owned);
760 let get_type = elem.attr("get-type").map(|s| s.into());
761 let version = self.read_version(parser, ns_id, elem)?;
762 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
763
764 let mut members = Vec::new();
765 let mut fns = Vec::new();
766 let mut doc = None;
767 let mut doc_deprecated = None;
768
769 parser.elements(|parser, elem| match elem.name() {
770 "member" => self
771 .read_member(parser, ns_id, elem)
772 .map(|m| members.push(m)),
773 "constructor" | "function" | "method" => {
774 self.read_function_to_vec(parser, ns_id, elem, &mut fns)
775 }
776 "doc" => parser.text().map(|t| doc = Some(t)),
777 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
778 "source-position" => parser.ignore_element(),
779 "attribute" => parser.ignore_element(),
780 _ => Err(parser.unexpected_element(elem)),
781 })?;
782
783 let typ = Type::Bitfield(Bitfield {
784 name: bitfield_name.into(),
785 c_type: c_type.into(),
786 members,
787 functions: fns,
788 version,
789 deprecated_version,
790 doc,
791 doc_deprecated,
792 glib_get_type: get_type,
793 symbol_prefix,
794 });
795 self.add_type(ns_id, bitfield_name, typ);
796 Ok(())
797 }
798
799 fn read_enumeration(
800 &mut self,
801 parser: &mut XmlParser<'_>,
802 ns_id: u16,
803 elem: &Element,
804 ) -> Result<(), String> {
805 let enum_name = elem.attr_required("name")?;
806 let c_type = self.read_object_c_type(parser, elem)?;
807 let symbol_prefix = elem.attr("symbol-prefix").map(ToOwned::to_owned);
808 let get_type = elem.attr("get-type").map(|s| s.into());
809 let version = self.read_version(parser, ns_id, elem)?;
810 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
811 let error_domain = elem
812 .attr("error-domain")
813 .map(|s| ErrorDomain::Quark(String::from(s)));
814
815 let mut members = Vec::new();
816 let mut fns = Vec::new();
817 let mut doc = None;
818 let mut doc_deprecated = None;
819
820 parser.elements(|parser, elem| match elem.name() {
821 "member" => self
822 .read_member(parser, ns_id, elem)
823 .map(|m| members.push(m)),
824 "constructor" | "function" | "method" => {
825 self.read_function_to_vec(parser, ns_id, elem, &mut fns)
826 }
827 "doc" => parser.text().map(|t| doc = Some(t)),
828 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
829 "source-position" => parser.ignore_element(),
830 "attribute" => parser.ignore_element(),
831 _ => Err(parser.unexpected_element(elem)),
832 })?;
833
834 let typ = Type::Enumeration(Enumeration {
835 name: enum_name.into(),
836 c_type: c_type.into(),
837 members,
838 functions: fns,
839 version,
840 deprecated_version,
841 doc,
842 doc_deprecated,
843 error_domain,
844 glib_get_type: get_type,
845 symbol_prefix,
846 });
847 self.add_type(ns_id, enum_name, typ);
848 Ok(())
849 }
850
851 fn read_global_function(
852 &mut self,
853 parser: &mut XmlParser<'_>,
854 ns_id: u16,
855 elem: &Element,
856 ) -> Result<(), String> {
857 self.read_function_if_not_moved(parser, ns_id, "global", elem, false)
858 .map(|func| {
859 if let Some(func) = func {
860 self.add_function(ns_id, func);
861 }
862 })
863 }
864
865 fn read_constant(
866 &mut self,
867 parser: &mut XmlParser<'_>,
868 ns_id: u16,
869 elem: &Element,
870 ) -> Result<(), String> {
871 let const_name = elem.attr_required("name")?;
872 let c_identifier = elem.attr_required("type")?;
873 let value = elem.attr_required("value")?;
874 let version = self.read_version(parser, ns_id, elem)?;
875 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
876
877 let mut inner = None;
878 let mut doc = None;
879 let mut doc_deprecated = None;
880
881 parser.elements(|parser, elem| match elem.name() {
882 "type" | "array" => {
883 if inner.is_some() {
884 return Err(parser.fail_with_position(
885 "Too many <type> inner elements in <constant> element",
886 elem.position(),
887 ));
888 }
889 let (typ, c_type, array_length) = self.read_type(parser, ns_id, elem)?;
890 if let Some(c_type) = c_type {
891 inner = Some((typ, c_type, array_length));
892 } else {
893 return Err(parser.fail_with_position(
894 "Missing <constant> element's c:type",
895 elem.position(),
896 ));
897 }
898 Ok(())
899 }
900 "doc" => parser.text().map(|t| doc = Some(t)),
901 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
902 "source-position" => parser.ignore_element(),
903 "attribute" => parser.ignore_element(),
904 _ => Err(parser.unexpected_element(elem)),
905 })?;
906
907 if let Some((typ, c_type, _array_length)) = inner {
908 self.add_constant(
909 ns_id,
910 Constant {
911 name: const_name.into(),
912 c_identifier: c_identifier.into(),
913 typ,
914 c_type,
915 value: value.into(),
916 version,
917 deprecated_version,
918 doc,
919 doc_deprecated,
920 },
921 );
922 Ok(())
923 } else {
924 Err(parser.fail_with_position(
925 "Missing <type> element inside <constant> element",
926 elem.position(),
927 ))
928 }
929 }
930
931 fn read_alias(
932 &mut self,
933 parser: &mut XmlParser<'_>,
934 ns_id: u16,
935 elem: &Element,
936 ) -> Result<(), String> {
937 let alias_name = elem.attr_required("name")?;
938 let c_identifier = elem.attr_required("type")?;
939
940 let mut inner = None;
941 let mut doc = None;
942 let mut doc_deprecated = None;
943
944 parser.elements(|parser, elem| match elem.name() {
945 "source-position" => parser.ignore_element(),
946 "type" | "array" => {
947 if inner.is_some() {
948 return Err(parser.fail_with_position(
949 "Too many <type> inner elements in <alias> element",
950 elem.position(),
951 ));
952 }
953 let (typ, c_type, array_length) = self.read_type(parser, ns_id, elem)?;
954 if let Some(c_type) = c_type {
955 inner = Some((typ, c_type, array_length));
956 } else {
957 return Err(parser.fail("Missing <alias> target's c:type"));
958 }
959 Ok(())
960 }
961 "doc" => parser.text().map(|t| doc = Some(t)),
962 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
963 "attribute" => parser.ignore_element(),
964 _ => Err(parser.unexpected_element(elem)),
965 })?;
966
967 if let Some((typ, c_type, _array_length)) = inner {
968 let typ = Type::Alias(Alias {
969 name: alias_name.into(),
970 c_identifier: c_identifier.into(),
971 typ,
972 target_c_type: c_type,
973 doc,
974 doc_deprecated,
975 });
976 self.add_type(ns_id, alias_name, typ);
977 Ok(())
978 } else {
979 Err(parser.fail_with_position(
980 "Missing <type> element inside <alias> element",
981 elem.position(),
982 ))
983 }
984 }
985
986 fn read_member(
987 &mut self,
988 parser: &mut XmlParser<'_>,
989 ns_id: u16,
990 elem: &Element,
991 ) -> Result<Member, String> {
992 let member_name = elem.attr_required("name")?;
993 let value = elem.attr_required("value")?;
994 let c_identifier = elem.attr("identifier").map(|x| x.into());
995 let version = self.read_version(parser, ns_id, elem)?;
996 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
997
998 let mut doc = None;
999 let mut doc_deprecated = None;
1000
1001 parser.elements(|parser, elem| match elem.name() {
1002 "doc" => parser.text().map(|t| doc = Some(t)),
1003 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
1004 "attribute" => parser.ignore_element(),
1005 _ => Err(parser.unexpected_element(elem)),
1006 })?;
1007
1008 Ok(Member {
1009 name: member_name.into(),
1010 value: value.into(),
1011 doc,
1012 doc_deprecated,
1013 c_identifier: c_identifier.unwrap_or_else(|| member_name.into()),
1014 status: crate::config::gobjects::GStatus::Generate,
1015 version,
1016 deprecated_version,
1017 })
1018 }
1019
1020 fn read_function(
1021 &mut self,
1022 parser: &mut XmlParser<'_>,
1023 ns_id: u16,
1024 kind_str: &str,
1025 elem: &Element,
1026 is_callback: bool,
1027 ) -> Result<Function, String> {
1028 let fn_name = elem.attr_required("name")?;
1029 let c_identifier = elem.attr("identifier").or_else(|| elem.attr("type"));
1030 let kind = FunctionKind::from_str(kind_str).map_err(|why| parser.fail(&why))?;
1031 let is_method = kind == FunctionKind::Method;
1032 let version = self.read_version(parser, ns_id, elem)?;
1033 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
1034 let mut gtk_get_property = None;
1035 let mut gtk_set_property = None;
1036 let finish_func = c_identifier.and_then(|c_identifier| {
1037 elem.attr("finish-func").map(|finish_func_name| {
1038 format!(
1039 "{}{finish_func_name}",
1040 c_identifier.strip_suffix(&fn_name).unwrap()
1041 )
1042 })
1043 });
1044 let async_func = elem.attr("async-func").map(ToString::to_string);
1045 let sync_func = elem.attr("sync-func").map(ToString::to_string);
1046
1047 let mut params = Vec::new();
1048 let mut ret = None;
1049 let mut doc = None;
1050 let mut doc_deprecated = None;
1051
1052 parser.elements(|parser, elem| match elem.name() {
1053 "parameters" => self
1054 .read_parameters(parser, ns_id, false, is_method)
1055 .map(|mut ps| params.append(&mut ps)),
1056 "return-value" => {
1057 if ret.is_some() {
1058 return Err(parser.fail_with_position(
1059 "Too many <return-value> elements inside <function> element",
1060 elem.position(),
1061 ));
1062 }
1063 ret = Some(self.read_parameter(parser, ns_id, elem, false, is_method)?);
1064 Ok(())
1065 }
1066 "doc" => parser.text().map(|t| doc = Some(t)),
1067 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
1068 "doc-version" => parser.ignore_element(),
1069 "source-position" => parser.ignore_element(),
1070 "attribute" => {
1071 if let (Some(name), Some(value)) = (elem.attr("name"), elem.attr("value")) {
1072 match name {
1073 "org.gtk.Method.get_property" => {
1074 gtk_get_property = Some(value.to_string());
1075 Ok(())
1076 }
1077 "org.gtk.Method.set_property" => {
1078 gtk_set_property = Some(value.to_string());
1079 Ok(())
1080 }
1081 _ => parser.ignore_element(),
1082 }
1083 } else {
1084 parser.ignore_element()
1085 }
1086 }
1087 _ => Err(parser.unexpected_element(elem)),
1088 })?;
1089
1090 let get_property = gtk_get_property.or(elem.attr("get-property").map(ToString::to_string));
1091 let set_property = gtk_set_property.or(elem.attr("set-property").map(ToString::to_string));
1092 if is_callback && params.last().map(|x| x.closure.is_none()).unwrap_or(false) {
1095 params.last_mut().unwrap().closure = Some(2000);
1096 }
1097
1098 let throws = elem.attr_bool("throws", false);
1099 if throws {
1100 params.push(Parameter {
1101 name: "error".into(),
1102 typ: self.find_or_stub_type(ns_id, "GLib.Error"),
1103 c_type: "GError**".into(),
1104 instance_parameter: false,
1105 direction: ParameterDirection::Out,
1106 transfer: Transfer::Full,
1107 caller_allocates: false,
1108 nullable: Nullable(true),
1109 array_length: None,
1110 is_error: true,
1111 doc: None,
1112 scope: ParameterScope::None,
1113 closure: None,
1114 destroy: None,
1115 });
1116 }
1117 if let Some(ret) = ret {
1118 Ok(Function {
1119 name: fn_name.into(),
1120 c_identifier: c_identifier.map(|s| s.into()),
1121 kind,
1122 parameters: params,
1123 ret,
1124 throws,
1125 version,
1126 deprecated_version,
1127 doc,
1128 doc_deprecated,
1129 get_property,
1130 set_property,
1131 finish_func,
1132 async_func,
1133 sync_func,
1134 })
1135 } else {
1136 Err(parser.fail_with_position(
1137 "Missing <return-value> element in <function> element",
1138 elem.position(),
1139 ))
1140 }
1141 }
1142
1143 fn read_function_to_vec(
1144 &mut self,
1145 parser: &mut XmlParser<'_>,
1146 ns_id: u16,
1147 elem: &Element,
1148 fns: &mut Vec<Function>,
1149 ) -> Result<(), String> {
1150 if let Some(f) = self.read_function_if_not_moved(parser, ns_id, elem.name(), elem, false)? {
1151 fns.push(f);
1152 }
1153 Ok(())
1154 }
1155
1156 fn read_function_if_not_moved(
1157 &mut self,
1158 parser: &mut XmlParser<'_>,
1159 ns_id: u16,
1160 kind_str: &str,
1161 elem: &Element,
1162 is_callback: bool,
1163 ) -> Result<Option<Function>, String> {
1164 if elem.attr("moved-to").is_some() {
1165 return parser.ignore_element().map(|_| None);
1166 }
1167 self.read_function(parser, ns_id, kind_str, elem, is_callback)
1168 .and_then(|f| {
1169 if f.c_identifier.is_none() {
1170 return Err(parser.fail_with_position(
1171 &format!(
1172 "Missing c:identifier attribute in <{}> element",
1173 elem.name()
1174 ),
1175 elem.position(),
1176 ));
1177 }
1178 Ok(Some(f))
1179 })
1180 }
1181
1182 fn read_signal(
1183 &mut self,
1184 parser: &mut XmlParser<'_>,
1185 ns_id: u16,
1186 elem: &Element,
1187 ) -> Result<Signal, String> {
1188 let signal_name = elem.attr_required("name")?;
1189 let is_action = elem.attr_bool("action", false);
1190 let is_detailed = elem.attr_bool("detailed", false);
1191 let version = self.read_version(parser, ns_id, elem)?;
1192 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
1193
1194 let mut params = Vec::new();
1195 let mut ret = None;
1196 let mut doc = None;
1197 let mut doc_deprecated = None;
1198
1199 parser.elements(|parser, elem| match elem.name() {
1200 "parameters" => self
1201 .read_parameters(parser, ns_id, true, false)
1202 .map(|mut ps| params.append(&mut ps)),
1203 "return-value" => {
1204 if ret.is_some() {
1205 return Err(parser.fail_with_position(
1206 "Too many <return-value> elements in <signal> element",
1207 elem.position(),
1208 ));
1209 }
1210 self.read_parameter(parser, ns_id, elem, true, false)
1211 .map(|p| ret = Some(p))
1212 }
1213 "doc" => parser.text().map(|t| doc = Some(t)),
1214 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
1215 "attribute" => parser.ignore_element(),
1216 _ => Err(parser.unexpected_element(elem)),
1217 })?;
1218 if let Some(ret) = ret {
1219 Ok(Signal {
1220 name: signal_name.into(),
1221 parameters: params,
1222 ret,
1223 is_action,
1224 is_detailed,
1225 version,
1226 deprecated_version,
1227 doc,
1228 doc_deprecated,
1229 })
1230 } else {
1231 Err(parser.fail_with_position(
1232 "Missing <return-value> element in <signal> element",
1233 elem.position(),
1234 ))
1235 }
1236 }
1237
1238 fn read_parameters(
1239 &mut self,
1240 parser: &mut XmlParser<'_>,
1241 ns_id: u16,
1242 allow_no_ctype: bool,
1243 for_method: bool,
1244 ) -> Result<Vec<Parameter>, String> {
1245 parser.elements(|parser, elem| match elem.name() {
1246 "parameter" | "instance-parameter" => {
1247 self.read_parameter(parser, ns_id, elem, allow_no_ctype, for_method)
1248 }
1249 _ => Err(parser.unexpected_element(elem)),
1250 })
1251 }
1252
1253 fn read_parameter(
1254 &mut self,
1255 parser: &mut XmlParser<'_>,
1256 ns_id: u16,
1257 elem: &Element,
1258 allow_no_ctype: bool,
1259 for_method: bool,
1260 ) -> Result<Parameter, String> {
1261 let param_name = elem.attr("name").unwrap_or("");
1262 let instance_parameter = elem.name() == "instance-parameter";
1263 let transfer = elem
1264 .attr_from_str("transfer-ownership")?
1265 .unwrap_or(Transfer::None);
1266 let nullable = elem.attr_bool("nullable", false);
1267 let scope = elem.attr_from_str("scope")?.unwrap_or(ParameterScope::None);
1268 let closure = elem.attr_from_str("closure")?;
1269 let destroy = elem.attr_from_str("destroy")?;
1270 let caller_allocates = elem.attr_bool("caller-allocates", false);
1271 let direction = if elem.name() == "return-value" {
1272 Ok(ParameterDirection::Return)
1273 } else {
1274 ParameterDirection::from_str(elem.attr("direction").unwrap_or("in"))
1275 .map_err(|why| parser.fail_with_position(&why, elem.position()))
1276 }?;
1277
1278 let mut typ = None;
1279 let mut varargs = false;
1280 let mut doc = None;
1281
1282 parser.elements(|parser, elem| match elem.name() {
1283 "type" | "array" => {
1284 if typ.is_some() {
1285 return Err(parser.fail_with_position(
1286 &format!("Too many <type> elements in <{}> element", elem.name()),
1287 elem.position(),
1288 ));
1289 }
1290 typ = Some(self.read_type(parser, ns_id, elem)?);
1291 if let Some((tid, None, _)) = typ {
1292 if allow_no_ctype {
1293 typ = Some((tid, Some(EMPTY_CTYPE.to_owned()), None));
1294 } else {
1295 return Err(parser.fail_with_position(
1296 &format!("Missing c:type attribute in <{}> element", elem.name()),
1297 elem.position(),
1298 ));
1299 }
1300 }
1301 Ok(())
1302 }
1303 "varargs" => {
1304 varargs = true;
1305 parser.ignore_element()
1306 }
1307 "doc" => parser.text().map(|t| doc = Some(t)),
1308 "attribute" => parser.ignore_element(),
1309 _ => Err(parser.unexpected_element(elem)),
1310 })?;
1311
1312 if let Some((tid, c_type, mut array_length)) = typ {
1313 if for_method {
1314 array_length = array_length.map(|l| l + 1);
1315 }
1316 Ok(Parameter {
1317 name: param_name.into(),
1318 typ: tid,
1319 c_type: c_type.unwrap(),
1320 instance_parameter,
1321 direction,
1322 transfer,
1323 caller_allocates,
1324 nullable: Nullable(nullable),
1325 array_length,
1326 is_error: false,
1327 doc,
1328 scope,
1329 closure,
1330 destroy,
1331 })
1332 } else if varargs {
1333 Ok(Parameter {
1334 name: String::new(),
1335 typ: self.find_type(INTERNAL_NAMESPACE, "varargs").unwrap(),
1336 c_type: String::new(),
1337 instance_parameter,
1338 direction: Default::default(),
1339 transfer: Transfer::None,
1340 caller_allocates: false,
1341 nullable: Nullable(false),
1342 array_length: None,
1343 is_error: false,
1344 doc,
1345 scope,
1346 closure,
1347 destroy,
1348 })
1349 } else {
1350 Err(parser.fail_with_position(
1351 &format!("Missing <type> element in <{}> element", elem.name()),
1352 elem.position(),
1353 ))
1354 }
1355 }
1356
1357 fn read_property(
1358 &mut self,
1359 parser: &mut XmlParser<'_>,
1360 ns_id: u16,
1361 elem: &Element,
1362 symbol_prefix: &str,
1363 ) -> Result<Option<Property>, String> {
1364 let prop_name = elem.attr_required("name")?;
1365 let readable = elem.attr_bool("readable", true);
1366 let writable = elem.attr_bool("writable", false);
1367 let construct = elem.attr_bool("construct", false);
1368 let construct_only = elem.attr_bool("construct-only", false);
1369 let transfer = Transfer::from_str(elem.attr("transfer-ownership").unwrap_or("none"))
1370 .map_err(|why| parser.fail_with_position(&why, elem.position()))?;
1371
1372 let version = self.read_version(parser, ns_id, elem)?;
1373 let deprecated_version = self.read_deprecated_version(parser, ns_id, elem)?;
1374 let mut has_empty_type_tag = false;
1375 let mut typ = None;
1376 let mut doc = None;
1377 let mut doc_deprecated = None;
1378 let mut gtk_getter = None;
1379 let mut gtk_setter = None;
1380
1381 parser.elements(|parser, elem| match elem.name() {
1382 "type" | "array" => {
1383 if typ.is_some() {
1384 return Err(parser.fail_with_position(
1385 "Too many <type> elements in <property> element",
1386 elem.position(),
1387 ));
1388 }
1389 if !elem.has_attrs() && elem.name() == "type" {
1390 has_empty_type_tag = true;
1392 return parser.ignore_element();
1393 }
1394 typ = Some(self.read_type(parser, ns_id, elem)?);
1395 if let Some((tid, None, _)) = typ {
1396 typ = Some((tid, Some(EMPTY_CTYPE.to_owned()), None));
1397 }
1398 Ok(())
1399 }
1400 "doc" => parser.text().map(|t| doc = Some(t)),
1401 "doc-deprecated" => parser.text().map(|t| doc_deprecated = Some(t)),
1402 "attribute" => {
1403 if let (Some(name), Some(value)) = (elem.attr("name"), elem.attr("value")) {
1404 match name {
1405 "org.gtk.Property.get" => {
1406 gtk_getter = value
1407 .split(symbol_prefix)
1408 .last()
1409 .and_then(|p| p.strip_prefix('_'))
1410 .map(|p| p.to_string());
1411 Ok(())
1412 }
1413 "org.gtk.Property.set" => {
1414 gtk_setter = value
1415 .split(symbol_prefix)
1416 .last()
1417 .and_then(|p| p.strip_prefix('_'))
1418 .map(|p| p.to_string());
1419 Ok(())
1420 }
1421 _ => parser.ignore_element(),
1422 }
1423 } else {
1424 parser.ignore_element()
1425 }
1426 }
1427 _ => Err(parser.unexpected_element(elem)),
1428 })?;
1429
1430 let getter = gtk_getter.or(elem.attr("getter").map(ToString::to_string));
1431 let setter = gtk_setter.or(elem.attr("setter").map(ToString::to_string));
1432 if has_empty_type_tag {
1433 return Ok(None);
1434 }
1435
1436 if let Some((tid, c_type, _array_length)) = typ {
1437 Ok(Some(Property {
1438 name: prop_name.into(),
1439 readable,
1440 writable,
1441 construct,
1442 construct_only,
1443 transfer,
1444 typ: tid,
1445 c_type,
1446 version,
1447 deprecated_version,
1448 doc,
1449 doc_deprecated,
1450 getter,
1451 setter,
1452 }))
1453 } else {
1454 Err(parser.fail_with_position(
1455 "Missing <type> element in <property> element",
1456 elem.position(),
1457 ))
1458 }
1459 }
1460
1461 fn read_type(
1462 &mut self,
1463 parser: &mut XmlParser<'_>,
1464 ns_id: u16,
1465 elem: &Element,
1466 ) -> Result<(TypeId, Option<String>, Option<u32>), String> {
1467 let type_name = elem
1468 .attr("name")
1469 .or_else(|| {
1470 if elem.name() == "array" {
1471 Some("array")
1472 } else {
1473 None
1474 }
1475 })
1476 .ok_or_else(|| {
1477 parser.fail_with_position(
1478 "<type> element is missing a name attribute",
1479 elem.position(),
1480 )
1481 })?;
1482 let c_type = elem.attr("type").map(|s| s.into());
1483 let array_length = elem.attr("length").and_then(|s| s.parse().ok());
1484
1485 let inner = parser.elements(|parser, elem| match elem.name() {
1486 "type" | "array" => self.read_type(parser, ns_id, elem),
1487 _ => Err(parser.unexpected_element(elem)),
1488 })?;
1489
1490 if inner.is_empty() || type_name == "GLib.ByteArray" {
1491 if type_name == "array" {
1492 Err(parser.fail_with_position(
1493 "<type> element is missing an inner element type",
1494 elem.position(),
1495 ))
1496 } else if type_name == "gboolean" && c_type.as_deref() == Some("_Bool") {
1497 Ok((self.find_or_stub_type(ns_id, "bool"), c_type, array_length))
1498 } else {
1499 Ok((
1500 self.find_or_stub_type(ns_id, type_name),
1501 c_type,
1502 array_length,
1503 ))
1504 }
1505 } else {
1506 let tid = if type_name == "array" {
1507 let inner_type = &inner[0];
1508 Type::c_array(
1509 self,
1510 inner_type.0,
1511 elem.attr("fixed-size").and_then(|n| n.parse().ok()),
1512 inner_type.1.clone(),
1513 )
1514 } else {
1515 let inner = inner.iter().map(|r| r.0).collect();
1516 Type::container(self, type_name, inner).ok_or_else(|| {
1517 parser.fail_with_position("Unknown container type", elem.position())
1518 })?
1519 };
1520 Ok((tid, c_type, array_length))
1521 }
1522 }
1523
1524 fn read_version(
1525 &mut self,
1526 parser: &XmlParser<'_>,
1527 ns_id: u16,
1528 elem: &Element,
1529 ) -> Result<Option<Version>, String> {
1530 self.read_version_attribute(parser, ns_id, elem, "version")
1531 }
1532
1533 fn read_deprecated_version(
1534 &mut self,
1535 parser: &XmlParser<'_>,
1536 ns_id: u16,
1537 elem: &Element,
1538 ) -> Result<Option<Version>, String> {
1539 self.read_version_attribute(parser, ns_id, elem, "deprecated-version")
1540 }
1541
1542 fn read_version_attribute(
1543 &mut self,
1544 parser: &XmlParser<'_>,
1545 ns_id: u16,
1546 elem: &Element,
1547 attr: &str,
1548 ) -> Result<Option<Version>, String> {
1549 if let Some(v) = elem.attr(attr) {
1550 match v.parse() {
1551 Ok(v) => {
1552 self.register_version(ns_id, v);
1553 Ok(Some(v))
1554 }
1555 Err(e) => Err(parser.fail(&format!("Invalid `{attr}` attribute: {e}"))),
1556 }
1557 } else {
1558 Ok(None)
1559 }
1560 }
1561
1562 fn read_object_c_type<'a>(
1563 &mut self,
1564 parser: &XmlParser<'_>,
1565 elem: &'a Element,
1566 ) -> Result<&'a str, String> {
1567 elem.attr("type")
1568 .or_else(|| elem.attr("type-name"))
1569 .ok_or_else(|| {
1570 parser.fail(&format!(
1571 "Missing `c:type`/`glib:type-name` attributes on element <{}>",
1572 elem.name()
1573 ))
1574 })
1575 }
1576}
1577
1578fn make_file_name(dir: &Path, name: &str) -> PathBuf {
1579 let mut path = dir.to_path_buf();
1580 let name = format!("{name}.gir");
1581 path.push(name);
1582 path
1583}