Skip to main content

libgir/
library.rs

1use gir_parser::{DocFormat, TransferOwnership, prelude::*};
2use std::{
3    cmp::{Ord, Ordering, PartialOrd},
4    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
5    fmt,
6    iter::Iterator,
7    str::FromStr,
8};
9
10use crate::{
11    analysis::conversion_type::ConversionType, config::gobjects::GStatus, env::Env,
12    nameutil::split_namespace_name, traits::*, version::Version,
13};
14
15#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
16pub enum ParameterDirection {
17    None,
18    #[default]
19    In,
20    Out,
21    InOut,
22    Return,
23}
24
25impl From<gir_parser::Direction> for ParameterDirection {
26    fn from(value: gir_parser::Direction) -> Self {
27        match value {
28            gir_parser::Direction::In => Self::In,
29            gir_parser::Direction::Out => Self::Out,
30            gir_parser::Direction::InOut => Self::InOut,
31        }
32    }
33}
34
35impl ParameterDirection {
36    pub fn is_in(self) -> bool {
37        matches!(self, Self::In | Self::InOut)
38    }
39
40    pub fn is_out(self) -> bool {
41        matches!(self, Self::Out | Self::InOut)
42    }
43}
44
45#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46pub enum FunctionKind {
47    Constructor,
48    Function,
49    Method,
50    Global,
51    ClassMethod,
52    VirtualMethod,
53}
54
55#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
56pub enum Concurrency {
57    #[default]
58    None,
59    Send,
60    SendSync,
61}
62
63impl FromStr for Concurrency {
64    type Err = String;
65    fn from_str(name: &str) -> Result<Self, String> {
66        match name {
67            "none" => Ok(Self::None),
68            "send" => Ok(Self::Send),
69            "send+sync" => Ok(Self::SendSync),
70            _ => Err(format!("Unknown concurrency kind '{name}'")),
71        }
72    }
73}
74
75#[derive(Clone, Copy, Debug, PartialEq, Eq)]
76pub enum Basic {
77    None,
78    Boolean,
79    Int8,
80    UInt8,
81    Int16,
82    UInt16,
83    Int32,
84    UInt32,
85    Int64,
86    UInt64,
87    Char,
88    UChar,
89    Short,
90    UShort,
91    Int,
92    UInt,
93    Long,
94    ULong,
95    Size,
96    SSize,
97    Float,
98    Double,
99    Pointer,
100    VarArgs,
101    UniChar,
102    Utf8,
103    Filename,
104    Type,
105    IntPtr,
106    UIntPtr,
107    TimeT,
108    OffT,
109    DevT,
110    GidT,
111    PidT,
112    SockLenT,
113    UidT,
114    // Same encoding as Filename but can contains any string
115    // Not defined in GLib directly
116    OsString,
117    Bool,
118    Unsupported,
119}
120
121impl Basic {
122    pub fn requires_conversion(&self) -> bool {
123        !matches!(
124            self,
125            Self::Int8
126                | Self::UInt8
127                | Self::Int16
128                | Self::UInt16
129                | Self::Int32
130                | Self::UInt32
131                | Self::Int64
132                | Self::UInt64
133                | Self::Char
134                | Self::UChar
135                | Self::Short
136                | Self::UShort
137                | Self::Int
138                | Self::UInt
139                | Self::Long
140                | Self::ULong
141                | Self::Size
142                | Self::SSize
143                | Self::Float
144                | Self::Double
145                | Self::Bool
146        )
147    }
148}
149
150const BASIC: &[(&str, Basic)] = &[
151    ("none", Basic::None),
152    ("gboolean", Basic::Boolean),
153    ("gint8", Basic::Int8),
154    ("guint8", Basic::UInt8),
155    ("gint16", Basic::Int16),
156    ("guint16", Basic::UInt16),
157    ("gint32", Basic::Int32),
158    ("guint32", Basic::UInt32),
159    ("gint64", Basic::Int64),
160    ("guint64", Basic::UInt64),
161    ("gchar", Basic::Char),
162    ("guchar", Basic::UChar),
163    ("gshort", Basic::Short),
164    ("gushort", Basic::UShort),
165    ("gint", Basic::Int),
166    ("guint", Basic::UInt),
167    ("glong", Basic::Long),
168    ("gulong", Basic::ULong),
169    ("gsize", Basic::Size),
170    ("gssize", Basic::SSize),
171    ("gfloat", Basic::Float),
172    ("gdouble", Basic::Double),
173    ("long double", Basic::Unsupported),
174    ("gunichar", Basic::UniChar),
175    ("gconstpointer", Basic::Pointer),
176    ("gpointer", Basic::Pointer),
177    ("va_list", Basic::Unsupported),
178    ("varargs", Basic::VarArgs),
179    ("utf8", Basic::Utf8),
180    ("filename", Basic::Filename),
181    ("GType", Basic::Type),
182    ("gintptr", Basic::IntPtr),
183    ("guintptr", Basic::UIntPtr),
184    // TODO: this is temporary name, change it when type added to GLib
185    ("os_string", Basic::OsString),
186    ("bool", Basic::Bool),
187    ("time_t", Basic::TimeT),
188    ("off_t", Basic::OffT),
189    ("dev_t", Basic::DevT),
190    ("gid_t", Basic::GidT),
191    ("pid_t", Basic::PidT),
192    ("socklen_t", Basic::SockLenT),
193    ("uid_t", Basic::UidT),
194];
195
196#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
197pub struct TypeId {
198    pub ns_id: u16,
199    pub id: u32,
200}
201
202impl TypeId {
203    pub fn full_name(self, library: &Library) -> String {
204        let ns_name = &library.namespace(self.ns_id).name;
205        let type_ = &library.type_(self);
206        format!("{}.{}", ns_name, &type_.get_name())
207    }
208
209    pub fn tid_none() -> TypeId {
210        Default::default()
211    }
212
213    pub fn tid_bool() -> TypeId {
214        TypeId { ns_id: 0, id: 1 }
215    }
216
217    pub fn tid_uint32() -> TypeId {
218        TypeId { ns_id: 0, id: 7 }
219    }
220
221    pub fn tid_utf8() -> TypeId {
222        TypeId { ns_id: 0, id: 28 }
223    }
224
225    pub fn tid_filename() -> TypeId {
226        TypeId { ns_id: 0, id: 29 }
227    }
228
229    pub fn tid_os_string() -> TypeId {
230        TypeId { ns_id: 0, id: 33 }
231    }
232
233    pub fn tid_c_bool() -> TypeId {
234        TypeId { ns_id: 0, id: 34 }
235    }
236
237    pub fn is_basic_type(self, env: &Env) -> bool {
238        env.library.type_(self).is_basic_type(env)
239    }
240}
241
242#[derive(Debug)]
243pub struct Alias {
244    pub name: String,
245    pub c_identifier: String,
246    pub typ: TypeId,
247    pub target_c_type: String,
248    pub doc: Option<String>,
249    pub doc_deprecated: Option<String>,
250}
251
252#[derive(Debug)]
253pub struct Constant {
254    pub name: String,
255    pub c_identifier: String,
256    pub typ: TypeId,
257    pub c_type: String,
258    pub value: String,
259    pub version: Option<Version>,
260    pub deprecated_version: Option<Version>,
261    pub doc: Option<String>,
262    pub doc_deprecated: Option<String>,
263}
264
265#[derive(Debug)]
266pub struct Member {
267    pub name: String,
268    pub c_identifier: String,
269    pub value: String,
270    pub doc: Option<String>,
271    pub doc_deprecated: Option<String>,
272    pub status: GStatus,
273    pub version: Option<Version>,
274    pub deprecated_version: Option<Version>,
275}
276
277#[derive(Debug)]
278pub enum ErrorDomain {
279    Quark(String),
280    Function(String),
281}
282
283#[derive(Debug)]
284pub struct Enumeration {
285    pub name: String,
286    pub c_type: String,
287    pub members: Vec<Member>,
288    pub functions: Vec<Function>,
289    pub version: Option<Version>,
290    pub deprecated_version: Option<Version>,
291    pub doc: Option<String>,
292    pub doc_deprecated: Option<String>,
293    pub error_domain: Option<ErrorDomain>,
294    pub glib_get_type: Option<String>,
295}
296
297#[derive(Debug)]
298pub struct Bitfield {
299    pub name: String,
300    pub c_type: String,
301    pub members: Vec<Member>,
302    pub functions: Vec<Function>,
303    pub version: Option<Version>,
304    pub deprecated_version: Option<Version>,
305    pub doc: Option<String>,
306    pub doc_deprecated: Option<String>,
307    pub glib_get_type: Option<String>,
308}
309
310#[derive(Default, Debug)]
311pub struct Record {
312    pub name: String,
313    pub c_type: String,
314    pub symbol_prefix: Option<String>,
315    pub glib_get_type: Option<String>,
316    pub gtype_struct_for: Option<String>,
317    pub fields: Vec<Field>,
318    pub functions: Vec<Function>,
319    pub version: Option<Version>,
320    pub deprecated_version: Option<Version>,
321    pub doc: Option<String>,
322    pub doc_deprecated: Option<String>,
323    /// A 'pointer' record is one where the c:type is a typedef that
324    /// doesn't look like a pointer, but is internally: typedef struct _X *X;
325    pub pointer: bool,
326    /// A 'disguised' record is one where the c:type is a typedef to
327    /// a struct whose content and size are unknown, it is :typedef struct _X X;
328    pub disguised: bool,
329}
330
331impl Record {
332    pub fn has_free(&self) -> bool {
333        self.functions.iter().any(|f| f.name == "free") || (self.has_copy() && self.has_destroy())
334    }
335
336    pub fn has_copy(&self) -> bool {
337        self.functions
338            .iter()
339            .any(|f| f.name == "copy" || f.name == "copy_into")
340    }
341
342    pub fn has_destroy(&self) -> bool {
343        self.functions.iter().any(|f| f.name == "destroy")
344    }
345
346    pub fn has_unref(&self) -> bool {
347        self.functions.iter().any(|f| f.name == "unref")
348    }
349
350    pub fn has_ref(&self) -> bool {
351        self.functions.iter().any(|f| f.name == "ref")
352    }
353}
354
355#[derive(Default, Debug)]
356pub struct Field {
357    pub name: String,
358    pub typ: TypeId,
359    pub c_type: Option<String>,
360    pub private: bool,
361    pub bits: Option<u8>,
362    pub array_length: Option<u32>,
363    pub doc: Option<String>,
364}
365
366#[derive(Default, Debug)]
367pub struct Union {
368    pub name: String,
369    pub c_type: Option<String>,
370    pub symbol_prefix: Option<String>,
371    pub glib_get_type: Option<String>,
372    pub fields: Vec<Field>,
373    pub functions: Vec<Function>,
374    pub doc: Option<String>,
375}
376
377#[derive(Debug)]
378pub struct Property {
379    pub name: String,
380    pub readable: bool,
381    pub writable: bool,
382    pub construct: bool,
383    pub construct_only: bool,
384    pub typ: TypeId,
385    pub c_type: Option<String>,
386    pub transfer: TransferOwnership,
387    pub version: Option<Version>,
388    pub deprecated_version: Option<Version>,
389    pub doc: Option<String>,
390    pub doc_deprecated: Option<String>,
391    pub getter: Option<String>,
392    pub setter: Option<String>,
393}
394
395#[derive(Clone, Debug)]
396pub enum Parameter {
397    Instance {
398        param: gir_parser::InstanceParameter,
399        tid: TypeId,
400        nullable_override: Option<bool>,
401        name_override: Option<String>,
402        c_type_override: Option<String>,
403    },
404    Return {
405        param: gir_parser::ReturnValue,
406        tid: TypeId,
407        nullable_override: Option<bool>,
408        name_override: Option<String>,
409        c_type_override: Option<String>,
410        array_length_offset: u32,
411    },
412    Default {
413        param: gir_parser::Parameter,
414        tid: TypeId,
415        nullable_override: Option<bool>,
416        name_override: Option<String>,
417        c_type_override: Option<String>,
418        array_length_offset: u32,
419        closure_override: Option<usize>,
420    },
421    Error(TypeId),
422    VarArgs(TypeId),
423    None(TypeId),
424}
425
426impl Parameter {
427    pub fn set_nullable(&mut self, is_nullable: bool) {
428        match self {
429            Self::Default {
430                nullable_override, ..
431            } => {
432                nullable_override.replace(is_nullable);
433            }
434            Parameter::Instance {
435                nullable_override, ..
436            } => {
437                nullable_override.replace(is_nullable);
438            }
439            Parameter::Return {
440                nullable_override, ..
441            } => {
442                nullable_override.replace(is_nullable);
443            }
444            _ => (),
445        }
446    }
447    pub fn set_c_type(&mut self, c_type: &str) {
448        match self {
449            Self::Default {
450                c_type_override, ..
451            } => {
452                c_type_override.replace(c_type.to_owned());
453            }
454            Parameter::Instance {
455                c_type_override, ..
456            } => {
457                c_type_override.replace(c_type.to_owned());
458            }
459            Parameter::Return {
460                c_type_override, ..
461            } => {
462                c_type_override.replace(c_type.to_owned());
463            }
464            _ => (),
465        }
466    }
467
468    pub fn set_name(&mut self, name: &str) {
469        match self {
470            Self::Default { name_override, .. } => {
471                name_override.replace(name.to_owned());
472            }
473            Parameter::Instance { name_override, .. } => {
474                name_override.replace(name.to_owned());
475            }
476            Parameter::Return { name_override, .. } => {
477                name_override.replace(name.to_owned());
478            }
479            _ => (),
480        }
481    }
482
483    pub fn destroy(&self) -> Option<usize> {
484        match self {
485            Parameter::Return { param, .. } => param.destroy(),
486            Parameter::Default { param, .. } => param.destroy(),
487            _ => None,
488        }
489    }
490
491    pub fn closure(&self) -> Option<usize> {
492        match self {
493            Parameter::Return { param, .. } => param.closure(),
494            Parameter::Default {
495                param,
496                closure_override,
497                ..
498            } => closure_override.or_else(|| param.closure()),
499            _ => None,
500        }
501    }
502
503    pub fn c_type(&self) -> &str {
504        match self {
505            Parameter::Instance {
506                param,
507                c_type_override,
508                ..
509            } => c_type_override
510                .as_deref()
511                .or(param.ty().and_then(|t| t.c_type())),
512            Parameter::Return {
513                param,
514                c_type_override,
515                ..
516            } => c_type_override.as_deref().or_else(|| match param.ty() {
517                gir_parser::AnyType::Array(a) => a.c_type(),
518                gir_parser::AnyType::Type(t) => t.c_type(),
519            }),
520            Parameter::Default {
521                param,
522                c_type_override,
523                ..
524            } => c_type_override.as_deref().or_else(|| {
525                param.ty().and_then(|t| match t {
526                    gir_parser::ParameterType::VarArgs => None,
527                    gir_parser::ParameterType::Array(a) => a.c_type(),
528                    gir_parser::ParameterType::Type(t) => t.c_type(),
529                })
530            }),
531            Parameter::Error(_) => Some("GError**"),
532            Parameter::VarArgs(_) => None,
533            Parameter::None(_) => Some("none"),
534        }
535        .unwrap_or("")
536    }
537
538    pub fn scope(&self) -> Option<gir_parser::FunctionScope> {
539        match self {
540            Self::Instance { .. } => None,
541            Self::Return { param, .. } => param.scope(),
542            Self::Default { param, .. } => param.scope(),
543            Self::Error(_) => None,
544            Self::VarArgs(_) => None,
545            Self::None(_) => None,
546        }
547    }
548
549    pub fn array_length(&self) -> Option<u32> {
550        match self {
551            Self::Return {
552                param,
553                array_length_offset,
554                ..
555            } => match param.ty() {
556                gir_parser::AnyType::Array(array) => {
557                    array.length().map(|l| l + array_length_offset)
558                }
559                _ => None,
560            },
561            Self::Default {
562                param,
563                array_length_offset,
564                ..
565            } => {
566                if let Some(ty) = param.ty() {
567                    match ty {
568                        gir_parser::ParameterType::Array(array) => {
569                            array.length().map(|l| l + array_length_offset)
570                        }
571                        _ => None,
572                    }
573                } else {
574                    None
575                }
576            }
577            _ => None,
578        }
579    }
580
581    pub fn doc(&self) -> Option<&str> {
582        match self {
583            Self::Instance { param, .. } => param.doc().map(|d| d.text()),
584            Self::Return { param, .. } => param.doc().map(|d| d.text()),
585            Self::Default { param, .. } => param.doc().map(|d| d.text()),
586            _ => None,
587        }
588    }
589
590    pub fn none(tid: TypeId) -> Self {
591        Self::None(tid)
592    }
593
594    pub fn error(tid: TypeId) -> Self {
595        Self::Error(tid)
596    }
597
598    pub fn is_instance(&self) -> bool {
599        matches!(self, Self::Instance { .. })
600    }
601
602    pub fn is_return(&self) -> bool {
603        matches!(self, Self::Return { .. })
604    }
605
606    pub fn is_error(&self) -> bool {
607        matches!(self, Self::Error(_))
608    }
609
610    pub fn is_varargs(&self) -> bool {
611        matches!(self, Self::VarArgs(_))
612    }
613
614    pub fn name(&self) -> &str {
615        match self {
616            Self::Instance {
617                param,
618                name_override,
619                ..
620            } => name_override.as_deref().or(Some(param.name())),
621            Self::Default {
622                param,
623                name_override,
624                ..
625            } => name_override.as_deref().or(Some(param.name())),
626            Self::Return { name_override, .. } => name_override.as_deref(),
627            Self::Error(_) => Some("error"),
628            _ => None,
629        }
630        .unwrap_or("")
631    }
632
633    pub fn is_caller_allocates(&self) -> bool {
634        match self {
635            Self::Instance { param, .. } => param.is_caller_allocates(),
636            Self::Default { param, .. } => param.is_caller_allocates(),
637            _ => None,
638        }
639        .unwrap_or(false)
640    }
641
642    pub fn typ(&self) -> TypeId {
643        match self {
644            Self::Instance { tid, .. } => *tid,
645            Self::Return { tid, .. } => *tid,
646            Self::Default { tid, .. } => *tid,
647            Self::Error(tid) => *tid,
648            Self::VarArgs(tid) => *tid,
649            Self::None(tid) => *tid,
650        }
651    }
652
653    pub fn set_tid(&mut self, new_tid: TypeId) {
654        match self {
655            Self::Instance { tid, .. } | Self::Return { tid, .. } | Self::Default { tid, .. } => {
656                *tid = new_tid;
657            }
658            Self::Error(tid) | Self::VarArgs(tid) | Self::None(tid) => {
659                *tid = new_tid;
660            }
661        }
662    }
663
664    pub fn is_nullable(&self) -> bool {
665        match self {
666            Self::Instance {
667                nullable_override, ..
668            } => nullable_override.unwrap_or(false),
669            Self::Default {
670                param,
671                nullable_override,
672                ..
673            } => nullable_override.or(param.is_nullable()).unwrap_or(false),
674            Self::Return {
675                param,
676                nullable_override,
677                ..
678            } => nullable_override.or(param.is_nullable()).unwrap_or(false),
679            Self::Error(_) => true,
680            Self::VarArgs(_) => false,
681            Self::None(_) => false,
682        }
683    }
684
685    pub fn direction(&self) -> ParameterDirection {
686        match self {
687            Self::Instance { param, .. } => param
688                .direction()
689                .map(ParameterDirection::from)
690                .unwrap_or_default(),
691            Self::Default { param, .. } => param
692                .direction()
693                .map(ParameterDirection::from)
694                .unwrap_or_default(),
695            Self::Return { .. } => ParameterDirection::Return,
696            Self::Error(_) => ParameterDirection::Out,
697            Self::VarArgs(_) => ParameterDirection::default(),
698            Self::None(_) => ParameterDirection::default(),
699        }
700    }
701
702    pub fn transfer_ownership(&self) -> TransferOwnership {
703        match self {
704            Self::Instance { param, .. } => param.transfer_ownership(),
705            Self::Return { param, .. } => param.transfer_ownership(),
706            Self::Default { param, .. } => param.transfer_ownership(),
707            Self::Error(_) => Some(TransferOwnership::Full),
708            Self::VarArgs(_) | Self::None(_) => None,
709        }
710        .unwrap_or(TransferOwnership::None)
711    }
712}
713
714#[derive(Debug)]
715pub struct Function {
716    pub name: String,
717    pub c_identifier: String,
718    pub kind: FunctionKind,
719    pub parameters: Vec<Parameter>,
720    pub ret: Parameter,
721    pub throws: bool,
722    pub version: Option<Version>,
723    pub deprecated_version: Option<Version>,
724    pub doc: Option<String>,
725    pub doc_deprecated: Option<String>,
726    pub get_property: Option<String>,
727    pub set_property: Option<String>,
728    pub finish_func: Option<String>,
729    pub async_func: Option<String>,
730    pub sync_func: Option<String>,
731}
732
733#[derive(Debug)]
734pub struct Signal {
735    pub name: String,
736    pub parameters: Vec<Parameter>,
737    pub ret: Parameter,
738    pub is_action: bool,
739    pub is_detailed: bool,
740    pub version: Option<Version>,
741    pub deprecated_version: Option<Version>,
742    pub doc: Option<String>,
743    pub doc_deprecated: Option<String>,
744}
745
746#[derive(Default, Debug)]
747pub struct Interface {
748    pub name: String,
749    pub c_type: String,
750    pub symbol_prefix: String,
751    pub type_struct: Option<String>,
752    pub c_class_type: Option<String>,
753    pub glib_get_type: String,
754    pub functions: Vec<Function>,
755    pub virtual_methods: Vec<Function>,
756    pub signals: Vec<Signal>,
757    pub properties: Vec<Property>,
758    pub prerequisites: Vec<TypeId>,
759    pub version: Option<Version>,
760    pub deprecated_version: Option<Version>,
761    pub doc: Option<String>,
762    pub doc_deprecated: Option<String>,
763}
764
765#[derive(Default, Debug)]
766pub struct Class {
767    pub name: String,
768    pub c_type: String,
769    pub symbol_prefix: String,
770    pub type_struct: Option<String>,
771    pub c_class_type: Option<String>,
772    pub glib_get_type: String,
773    pub fields: Vec<Field>,
774    pub functions: Vec<Function>,
775    pub virtual_methods: Vec<Function>,
776    pub signals: Vec<Signal>,
777    pub properties: Vec<Property>,
778    pub parent: Option<TypeId>,
779    pub implements: Vec<TypeId>,
780    pub final_type: bool,
781    pub version: Option<Version>,
782    pub deprecated_version: Option<Version>,
783    pub doc: Option<String>,
784    pub doc_deprecated: Option<String>,
785    pub is_abstract: bool,
786    pub is_fundamental: bool,
787    /// Specific to fundamental types
788    pub ref_fn: Option<String>,
789    pub unref_fn: Option<String>,
790}
791
792#[derive(Debug)]
793pub struct Custom {
794    pub name: String,
795    pub conversion_type: ConversionType,
796}
797
798macro_rules! impl_lexical_ord {
799    () => ();
800    ($name:ident => $field:ident, $($more_name:ident => $more_field:ident,)*) => (
801        impl_lexical_ord!($($more_name => $more_field,)*);
802
803        impl PartialEq for $name {
804            fn eq(&self, other: &$name) -> bool {
805                self.$field.eq(&other.$field)
806            }
807        }
808
809        impl Eq for $name { }
810
811        impl PartialOrd for $name {
812            fn partial_cmp(&self, other: &$name) -> Option<Ordering> {
813                Some(self.cmp(other))
814            }
815        }
816
817        impl Ord for $name {
818            fn cmp(&self, other: &$name) -> Ordering {
819                self.$field.cmp(&other.$field)
820            }
821        }
822    );
823}
824
825impl_lexical_ord!(
826    Alias => c_identifier,
827    Bitfield => c_type,
828    Class => c_type,
829    Enumeration => c_type,
830    Function => c_identifier,
831    Interface => c_type,
832    Record => c_type,
833    Union => c_type,
834    Custom => name,
835);
836
837#[derive(Debug, Eq, PartialEq)]
838pub enum Type {
839    Basic(Basic),
840    Alias(Alias),
841    Enumeration(Enumeration),
842    Bitfield(Bitfield),
843    Record(Record),
844    Union(Union),
845    Function(Box<Function>),
846    Interface(Interface),
847    Class(Class),
848    Custom(Custom),
849    Array(TypeId),
850    CArray(TypeId),
851    FixedArray(TypeId, u16, Option<String>),
852    PtrArray(TypeId),
853    HashTable(TypeId, TypeId),
854    List(TypeId),
855    SList(TypeId),
856}
857
858impl fmt::Display for Type {
859    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
860        f.write_str(match self {
861            Self::Basic(_) => "Basic",
862            Self::Alias(_) => "Alias",
863            Self::Enumeration(_) => "Enumeration",
864            Self::Bitfield(_) => "Bitfield",
865            Self::Record(_) => "Record",
866            Self::Union(_) => "Union",
867            Self::Function(_) => "Function",
868            Self::Interface(_) => "Interface",
869            Self::Class(_) => "Class",
870            Self::Custom(_) => "Custom",
871            Self::Array(_) => "Array",
872            Self::CArray(_) => "CArray",
873            Self::FixedArray(_, _, _) => "FixedArray",
874            Self::PtrArray(_) => "PtrArray",
875            Self::HashTable(_, _) => "HashTable",
876            Self::List(_) => "List",
877            Self::SList(_) => "SList",
878        })
879    }
880}
881
882impl Type {
883    pub fn get_name(&self) -> String {
884        match self {
885            Self::Basic(basic) => format!("{basic:?}"),
886            Self::Alias(alias) => alias.name.clone(),
887            Self::Enumeration(enum_) => enum_.name.clone(),
888            Self::Bitfield(bit_field) => bit_field.name.clone(),
889            Self::Record(rec) => rec.name.clone(),
890            Self::Union(u) => u.name.clone(),
891            Self::Function(func) => func.name.clone(),
892            Self::Interface(interface) => interface.name.clone(),
893            Self::Array(type_id) => format!("Array {type_id:?}"),
894            Self::Class(class) => class.name.clone(),
895            Self::Custom(custom) => custom.name.clone(),
896            Self::CArray(type_id) => format!("CArray {type_id:?}"),
897            Self::FixedArray(type_id, size, _) => format!("FixedArray {type_id:?}; {size}"),
898            Self::PtrArray(type_id) => format!("PtrArray {type_id:?}"),
899            Self::HashTable(key_type_id, value_type_id) => {
900                format!("HashTable {key_type_id:?}/{value_type_id:?}")
901            }
902            Self::List(type_id) => format!("List {type_id:?}"),
903            Self::SList(type_id) => format!("SList {type_id:?}"),
904        }
905    }
906
907    pub fn get_deprecated_version(&self) -> Option<Version> {
908        match self {
909            Self::Basic(_) => None,
910            Self::Alias(_) => None,
911            Self::Enumeration(enum_) => enum_.deprecated_version,
912            Self::Bitfield(bit_field) => bit_field.deprecated_version,
913            Self::Record(rec) => rec.deprecated_version,
914            Self::Union(_) => None,
915            Self::Function(func) => func.deprecated_version,
916            Self::Interface(interface) => interface.deprecated_version,
917            Self::Array(_) => None,
918            Self::Class(class) => class.deprecated_version,
919            Self::Custom(_) => None,
920            Self::CArray(_) => None,
921            Self::FixedArray(..) => None,
922            Self::PtrArray(_) => None,
923            Self::HashTable(_, _) => None,
924            Self::List(_) => None,
925            Self::SList(_) => None,
926        }
927    }
928
929    pub fn get_glib_name(&self) -> Option<&str> {
930        match self {
931            Self::Alias(alias) => Some(&alias.c_identifier),
932            Self::Enumeration(enum_) => Some(&enum_.c_type),
933            Self::Bitfield(bit_field) => Some(&bit_field.c_type),
934            Self::Record(rec) => Some(&rec.c_type),
935            Self::Union(union) => union.c_type.as_deref(),
936            Self::Function(func) => Some(&func.c_identifier),
937            Self::Interface(interface) => Some(&interface.c_type),
938            Self::Class(class) => Some(&class.c_type),
939            _ => None,
940        }
941    }
942
943    pub fn c_array(
944        library: &mut Library,
945        inner: TypeId,
946        size: Option<u16>,
947        c_type: Option<String>,
948    ) -> TypeId {
949        let name = Self::c_array_internal_name(inner, size, &c_type);
950        if let Some(size) = size {
951            library.add_type(
952                INTERNAL_NAMESPACE,
953                &name,
954                Self::FixedArray(inner, size, c_type),
955            )
956        } else {
957            library.add_type(INTERNAL_NAMESPACE, &name, Self::CArray(inner))
958        }
959    }
960
961    pub fn find_c_array(library: &Library, inner: TypeId, size: Option<u16>) -> TypeId {
962        let name = Self::c_array_internal_name(inner, size, &None);
963        library
964            .find_type(INTERNAL_NAMESPACE, &name)
965            .unwrap_or_else(|| panic!("No type for '*.{name}'"))
966    }
967
968    fn c_array_internal_name(inner: TypeId, size: Option<u16>, c_type: &Option<String>) -> String {
969        if let Some(size) = size {
970            format!("[#{inner:?}; {size};{c_type:?}]")
971        } else {
972            format!("[#{inner:?}]")
973        }
974    }
975
976    pub fn container(library: &mut Library, name: &str, mut inner: Vec<TypeId>) -> Option<TypeId> {
977        match (name, inner.len()) {
978            ("GLib.Array", 1) => {
979                let tid = inner.remove(0);
980                Some((format!("Array(#{tid:?})"), Self::Array(tid)))
981            }
982            ("GLib.PtrArray", 1) => {
983                let tid = inner.remove(0);
984                Some((format!("PtrArray(#{tid:?})"), Self::PtrArray(tid)))
985            }
986            ("GLib.HashTable", 2) => {
987                let k_tid = inner.remove(0);
988                let v_tid = inner.remove(0);
989                Some((
990                    format!("HashTable(#{k_tid:?}, #{v_tid:?})"),
991                    Self::HashTable(k_tid, v_tid),
992                ))
993            }
994            ("GLib.List", 1) => {
995                let tid = inner.remove(0);
996                Some((format!("List(#{tid:?})"), Self::List(tid)))
997            }
998            ("GLib.SList", 1) => {
999                let tid = inner.remove(0);
1000                Some((format!("SList(#{tid:?})"), Self::SList(tid)))
1001            }
1002            _ => None,
1003        }
1004        .map(|(name, typ)| library.add_type(INTERNAL_NAMESPACE, &name, typ))
1005    }
1006
1007    pub fn function(library: &mut Library, func: Function) -> TypeId {
1008        let mut param_tids: Vec<TypeId> = func.parameters.iter().map(|p| p.typ()).collect();
1009        param_tids.push(func.ret.typ());
1010        let typ = Self::Function(Box::new(func));
1011        library.add_type(INTERNAL_NAMESPACE, &format!("fn<#{param_tids:?}>"), typ)
1012    }
1013
1014    pub fn union(library: &mut Library, u: Union, ns_id: u16) -> TypeId {
1015        let field_tids: Vec<TypeId> = u.fields.iter().map(|f| f.typ).collect();
1016        let typ = Self::Union(u);
1017        library.add_type(ns_id, &format!("#{field_tids:?}"), typ)
1018    }
1019
1020    pub fn record(library: &mut Library, r: Record, ns_id: u16) -> TypeId {
1021        let field_tids: Vec<TypeId> = r.fields.iter().map(|f| f.typ).collect();
1022        let typ = Self::Record(r);
1023        library.add_type(ns_id, &format!("#{field_tids:?}"), typ)
1024    }
1025
1026    pub fn functions(&self) -> &[Function] {
1027        match self {
1028            Self::Enumeration(e) => &e.functions,
1029            Self::Bitfield(b) => &b.functions,
1030            Self::Record(r) => &r.functions,
1031            Self::Union(u) => &u.functions,
1032            Self::Interface(i) => &i.functions,
1033            Self::Class(c) => &c.functions,
1034            _ => &[],
1035        }
1036    }
1037
1038    pub fn is_basic(&self) -> bool {
1039        matches!(*self, Self::Basic(_))
1040    }
1041
1042    /// If the type is an Alias containing a basic, it'll return true (whereas
1043    /// `is_basic` won't).
1044    pub fn is_basic_type(&self, env: &Env) -> bool {
1045        match self {
1046            Self::Alias(x) => env.library.type_(x.typ).is_basic_type(env),
1047            x => x.is_basic(),
1048        }
1049    }
1050
1051    pub fn get_inner_type<'a>(&'a self, env: &'a Env) -> Option<(&'a Type, u16)> {
1052        match *self {
1053            Self::Array(t)
1054            | Self::CArray(t)
1055            | Self::FixedArray(t, ..)
1056            | Self::PtrArray(t)
1057            | Self::List(t)
1058            | Self::SList(t) => {
1059                let ty = env.type_(t);
1060                ty.get_inner_type(env).or(Some((ty, t.ns_id)))
1061            }
1062            _ => None,
1063        }
1064    }
1065
1066    pub fn is_function(&self) -> bool {
1067        matches!(*self, Self::Function(_))
1068    }
1069
1070    pub fn is_class(&self) -> bool {
1071        matches!(*self, Self::Class(_))
1072    }
1073
1074    pub fn is_interface(&self) -> bool {
1075        matches!(*self, Self::Interface(_))
1076    }
1077
1078    pub fn is_final_type(&self) -> bool {
1079        match *self {
1080            Self::Class(Class { final_type, .. }) => final_type,
1081            Self::Interface(..) => false,
1082            _ => true,
1083        }
1084    }
1085
1086    pub fn is_fundamental(&self) -> bool {
1087        match *self {
1088            Self::Class(Class { is_fundamental, .. }) => is_fundamental,
1089            _ => false,
1090        }
1091    }
1092
1093    pub fn is_abstract(&self) -> bool {
1094        match *self {
1095            Self::Class(Class { is_abstract, .. }) => is_abstract,
1096            _ => false,
1097        }
1098    }
1099
1100    pub fn is_enumeration(&self) -> bool {
1101        matches!(*self, Self::Enumeration(_))
1102    }
1103
1104    pub fn is_bitfield(&self) -> bool {
1105        matches!(*self, Self::Bitfield(_))
1106    }
1107}
1108
1109macro_rules! impl_maybe_ref {
1110    () => ();
1111    ($name:ident, $($more:ident,)*) => (
1112        impl_maybe_ref!($($more,)*);
1113
1114        impl MaybeRef<$name> for Type {
1115            fn maybe_ref(&self) -> Option<&$name> {
1116                if let Self::$name(x) = self { Some(x) } else { None }
1117            }
1118
1119            fn to_ref(&self) -> &$name {
1120                self.maybe_ref().unwrap_or_else(|| {
1121                    panic!("{} is not a {}", self.get_name(), stringify!($name))
1122                })
1123            }
1124        }
1125    );
1126}
1127
1128impl_maybe_ref!(
1129    Alias,
1130    Bitfield,
1131    Class,
1132    Enumeration,
1133    Function,
1134    Basic,
1135    Interface,
1136    Record,
1137    Union,
1138);
1139
1140impl<U> MaybeRefAs for U {
1141    fn maybe_ref_as<T>(&self) -> Option<&T>
1142    where
1143        Self: MaybeRef<T>,
1144    {
1145        self.maybe_ref()
1146    }
1147
1148    fn to_ref_as<T>(&self) -> &T
1149    where
1150        Self: MaybeRef<T>,
1151    {
1152        self.to_ref()
1153    }
1154}
1155
1156#[derive(Debug, Default)]
1157pub struct Namespace {
1158    pub name: String,
1159    pub types: Vec<Option<Type>>,
1160    pub index: BTreeMap<String, u32>,
1161    pub glib_name_index: HashMap<String, u32>,
1162    pub constants: Vec<Constant>,
1163    pub functions: Vec<Function>,
1164    pub package_names: Vec<String>,
1165    pub versions: BTreeSet<Version>,
1166    pub doc: Option<String>,
1167    pub doc_deprecated: Option<String>,
1168    pub shared_library: Vec<String>,
1169    pub identifier_prefixes: Vec<String>,
1170    pub symbol_prefixes: Vec<String>,
1171    /// C headers, relative to include directories provided by pkg-config
1172    /// --cflags.
1173    pub c_includes: Vec<String>,
1174}
1175
1176impl Namespace {
1177    fn new(name: &str) -> Self {
1178        Self {
1179            name: name.into(),
1180            ..Self::default()
1181        }
1182    }
1183
1184    fn add_constant(&mut self, c: Constant) {
1185        self.constants.push(c);
1186    }
1187
1188    fn add_function(&mut self, f: Function) {
1189        self.functions.push(f);
1190    }
1191
1192    fn type_(&self, id: u32) -> &Type {
1193        self.types[id as usize].as_ref().unwrap()
1194    }
1195
1196    fn type_mut(&mut self, id: u32) -> &mut Type {
1197        self.types[id as usize].as_mut().unwrap()
1198    }
1199
1200    fn add_type(&mut self, name: &str, typ: Option<Type>) -> u32 {
1201        let glib_name = typ
1202            .as_ref()
1203            .and_then(Type::get_glib_name)
1204            .map(ToOwned::to_owned);
1205        let id = if let Some(id) = self.find_type(name) {
1206            self.types[id as usize] = typ;
1207            id
1208        } else {
1209            let id = self.types.len() as u32;
1210            self.types.push(typ);
1211            self.index.insert(name.into(), id);
1212            id
1213        };
1214        if let Some(s) = glib_name {
1215            self.glib_name_index.insert(s, id);
1216        }
1217        id
1218    }
1219
1220    fn find_type(&self, name: &str) -> Option<u32> {
1221        self.index.get(name).copied()
1222    }
1223}
1224
1225pub const INTERNAL_NAMESPACE_NAME: &str = "*";
1226pub const INTERNAL_NAMESPACE: u16 = 0;
1227pub const MAIN_NAMESPACE: u16 = 1;
1228
1229#[derive(Debug, Default)]
1230pub struct Library {
1231    pub namespaces: Vec<Namespace>,
1232    pub index: HashMap<String, (u16, bool)>,
1233    pub doc_format: DocFormat,
1234}
1235
1236impl Library {
1237    pub fn new(main_namespace_name: &str) -> Self {
1238        let mut library = Self::default();
1239        assert_eq!(
1240            INTERNAL_NAMESPACE,
1241            library.add_namespace(INTERNAL_NAMESPACE_NAME, true)
1242        );
1243        for &(name, t) in BASIC {
1244            library.add_type(INTERNAL_NAMESPACE, name, Type::Basic(t));
1245        }
1246        assert_eq!(
1247            MAIN_NAMESPACE,
1248            library.add_namespace(main_namespace_name, false)
1249        );
1250
1251        // For string_type override
1252        Type::c_array(&mut library, TypeId::tid_utf8(), None, None);
1253        Type::c_array(&mut library, TypeId::tid_filename(), None, None);
1254        Type::c_array(&mut library, TypeId::tid_os_string(), None, None);
1255
1256        library
1257    }
1258
1259    pub fn show_non_bound_types(&self, env: &Env) {
1260        let not_allowed_ending = [
1261            "Class",
1262            "Private",
1263            "Func",
1264            "Callback",
1265            "Accessible",
1266            "Iface",
1267            "Type",
1268            "Interface",
1269        ];
1270        let namespace_name = self.namespaces[MAIN_NAMESPACE as usize].name.clone();
1271        let mut parents = HashSet::new();
1272
1273        for x in self.namespace(MAIN_NAMESPACE).types.iter().flatten() {
1274            let name = x.get_name();
1275            let full_name = format!("{namespace_name}.{name}");
1276            let mut check_methods = true;
1277
1278            if !not_allowed_ending.iter().any(|s| name.ends_with(s))
1279                || x.is_enumeration()
1280                || x.is_bitfield()
1281            {
1282                let version = x.get_deprecated_version();
1283                let depr_version = version.unwrap_or(env.config.min_cfg_version);
1284                if !env.analysis.objects.contains_key(&full_name)
1285                    && !env.analysis.records.contains_key(&full_name)
1286                    && !env.config.objects.iter().any(|o| o.1.name == full_name)
1287                    && depr_version >= env.config.min_cfg_version
1288                {
1289                    check_methods = false;
1290                    if let Some(version) = version {
1291                        println!("[NOT GENERATED] {full_name} (deprecated in {version})");
1292                    } else {
1293                        println!("[NOT GENERATED] {full_name}");
1294                    }
1295                } else if let Type::Class(Class { properties, .. }) = x
1296                    && !env
1297                        .config
1298                        .objects
1299                        .get(&full_name)
1300                        .is_some_and(|obj| obj.generate_builder)
1301                    && properties
1302                        .iter()
1303                        .any(|prop| prop.construct_only || prop.construct || prop.writable)
1304                {
1305                    println!("[NOT GENERATED BUILDER] {full_name}Builder");
1306                }
1307            }
1308            if let (Some(tid), Some(gobject_id)) = (
1309                env.library.find_type(0, &full_name),
1310                env.library.find_type(0, "GObject.Object"),
1311            ) {
1312                for &super_tid in env.class_hierarchy.supertypes(tid) {
1313                    let ty = env.library.type_(super_tid);
1314                    let ns_id = super_tid.ns_id as usize;
1315                    let full_parent_name =
1316                        format!("{}.{}", self.namespaces[ns_id].name, ty.get_name());
1317                    if super_tid != gobject_id
1318                        && env
1319                            .type_status(&super_tid.full_name(&env.library))
1320                            .ignored()
1321                        && parents.insert(full_parent_name.clone())
1322                    {
1323                        if let Some(version) = ty.get_deprecated_version() {
1324                            println!(
1325                                "[NOT GENERATED PARENT] {full_parent_name} (deprecated in {version})"
1326                            );
1327                        } else {
1328                            println!("[NOT GENERATED PARENT] {full_parent_name}");
1329                        }
1330                    }
1331                }
1332                if check_methods {
1333                    self.not_bound_functions(
1334                        env,
1335                        &format!("{full_name}::"),
1336                        x.functions(),
1337                        "METHOD",
1338                    );
1339                }
1340            }
1341        }
1342        self.not_bound_functions(
1343            env,
1344            &format!("{namespace_name}."),
1345            &self.namespace(MAIN_NAMESPACE).functions,
1346            "FUNCTION",
1347        );
1348    }
1349
1350    fn not_bound_functions(&self, env: &Env, prefix: &str, functions: &[Function], kind: &str) {
1351        for func in functions {
1352            let version = func.deprecated_version;
1353            let depr_version = version.unwrap_or(env.config.min_cfg_version);
1354
1355            if depr_version < env.config.min_cfg_version {
1356                continue;
1357            }
1358
1359            let mut errors = func
1360                .parameters
1361                .iter()
1362                .filter_map(|p| {
1363                    let mut ty = env.library.type_(p.typ());
1364                    let mut ns_id = p.typ().ns_id as usize;
1365                    if let Some((t, n)) = ty.get_inner_type(env) {
1366                        ty = t;
1367                        ns_id = n as usize;
1368                    }
1369                    if ty.is_basic() {
1370                        return None;
1371                    }
1372                    let full_name = format!("{}.{}", self.namespaces[ns_id].name, ty.get_name());
1373                    if env.type_status(&p.typ().full_name(&env.library)).ignored()
1374                        && !env.analysis.objects.contains_key(&full_name)
1375                        && !env.analysis.records.contains_key(&full_name)
1376                        && !env.config.objects.iter().any(|o| o.1.name == full_name)
1377                    {
1378                        Some(full_name)
1379                    } else {
1380                        None
1381                    }
1382                })
1383                .collect::<Vec<_>>();
1384            {
1385                let mut ty = env.library.type_(func.ret.typ());
1386                let mut ns_id = func.ret.typ().ns_id as usize;
1387                if let Some((t, n)) = ty.get_inner_type(env) {
1388                    ty = t;
1389                    ns_id = n as usize;
1390                }
1391                if !ty.is_basic() {
1392                    let full_name = format!("{}.{}", self.namespaces[ns_id].name, ty.get_name());
1393                    if env
1394                        .type_status(&func.ret.typ().full_name(&env.library))
1395                        .ignored()
1396                        && !env.analysis.objects.contains_key(&full_name)
1397                        && !env.analysis.records.contains_key(&full_name)
1398                        && !env.config.objects.iter().any(|o| o.1.name == full_name)
1399                    {
1400                        errors.push(full_name);
1401                    }
1402                }
1403            }
1404            if !errors.is_empty() {
1405                let full_name = format!("{}{}", prefix, func.name);
1406                let deprecated_version = match version {
1407                    Some(dv) => format!(" (deprecated in {dv})"),
1408                    None => String::new(),
1409                };
1410                if errors.len() > 1 {
1411                    let end = errors.pop().unwrap();
1412                    let begin = errors.join(", ");
1413                    println!(
1414                        "[NOT GENERATED {kind}] {full_name}{deprecated_version} because of {begin} and {end}"
1415                    );
1416                } else {
1417                    println!(
1418                        "[NOT GENERATED {}] {}{} because of {}",
1419                        kind, full_name, deprecated_version, errors[0]
1420                    );
1421                }
1422            }
1423        }
1424    }
1425
1426    pub fn namespace(&self, ns_id: u16) -> &Namespace {
1427        &self.namespaces[ns_id as usize]
1428    }
1429
1430    pub fn namespace_mut(&mut self, ns_id: u16) -> &mut Namespace {
1431        &mut self.namespaces[ns_id as usize]
1432    }
1433
1434    pub fn find_namespace(&self, name: &str) -> Option<(u16, bool)> {
1435        self.index.get(name).copied()
1436    }
1437
1438    pub fn add_namespace(&mut self, name: &str, parsed: bool) -> u16 {
1439        if let Some(&(id, _)) = self.index.get(name) {
1440            id
1441        } else {
1442            let id = self.namespaces.len() as u16;
1443            self.namespaces.push(Namespace::new(name));
1444            self.index.insert(name.into(), (id, parsed));
1445            id
1446        }
1447    }
1448
1449    pub fn add_constant(&mut self, ns_id: u16, c: Constant) {
1450        self.namespace_mut(ns_id).add_constant(c);
1451    }
1452
1453    pub fn add_function(&mut self, ns_id: u16, f: Function) {
1454        self.namespace_mut(ns_id).add_function(f);
1455    }
1456
1457    pub fn add_type(&mut self, ns_id: u16, name: &str, typ: Type) -> TypeId {
1458        TypeId {
1459            ns_id,
1460            id: self.namespace_mut(ns_id).add_type(name, Some(typ)),
1461        }
1462    }
1463
1464    #[allow(clippy::manual_map)]
1465    pub fn find_type(&self, current_ns_id: u16, name: &str) -> Option<TypeId> {
1466        let (mut ns, name) = split_namespace_name(name);
1467        if name == "GType" {
1468            ns = None;
1469        }
1470
1471        if let Some(ns) = ns {
1472            self.find_namespace(ns).and_then(|(ns_id, _)| {
1473                self.namespace(ns_id)
1474                    .find_type(name)
1475                    .map(|id| TypeId { ns_id, id })
1476            })
1477        } else if let Some(id) = self.namespace(current_ns_id).find_type(name) {
1478            Some(TypeId {
1479                ns_id: current_ns_id,
1480                id,
1481            })
1482        } else if let Some(id) = self.namespace(INTERNAL_NAMESPACE).find_type(name) {
1483            Some(TypeId {
1484                ns_id: INTERNAL_NAMESPACE,
1485                id,
1486            })
1487        } else {
1488            None
1489        }
1490    }
1491
1492    pub fn find_or_stub_type(&mut self, current_ns_id: u16, name: &str) -> TypeId {
1493        if let Some(tid) = self.find_type(current_ns_id, name) {
1494            return tid;
1495        }
1496
1497        let (ns, name) = split_namespace_name(name);
1498
1499        if let Some(ns) = ns {
1500            let (ns_id, _) = self
1501                .find_namespace(ns)
1502                .unwrap_or_else(|| (self.add_namespace(ns, false), false));
1503            let ns = self.namespace_mut(ns_id);
1504            let id = ns
1505                .find_type(name)
1506                .unwrap_or_else(|| ns.add_type(name, None));
1507            return TypeId { ns_id, id };
1508        }
1509
1510        let id = self.namespace_mut(current_ns_id).add_type(name, None);
1511        TypeId {
1512            ns_id: current_ns_id,
1513            id,
1514        }
1515    }
1516
1517    pub fn type_(&self, tid: TypeId) -> &Type {
1518        self.namespace(tid.ns_id).type_(tid.id)
1519    }
1520
1521    pub fn type_mut(&mut self, tid: TypeId) -> &mut Type {
1522        self.namespace_mut(tid.ns_id).type_mut(tid.id)
1523    }
1524
1525    pub fn register_version(&mut self, ns_id: u16, version: Version) {
1526        self.namespace_mut(ns_id).versions.insert(version);
1527    }
1528
1529    pub fn types<'a>(&'a self) -> Box<dyn Iterator<Item = (TypeId, &'a Type)> + 'a> {
1530        Box::new(self.namespaces.iter().enumerate().flat_map(|(ns_id, ns)| {
1531            ns.types.iter().enumerate().filter_map(move |(id, type_)| {
1532                let tid = TypeId {
1533                    ns_id: ns_id as u16,
1534                    id: id as u32,
1535                };
1536                type_.as_ref().map(|t| (tid, t))
1537            })
1538        }))
1539    }
1540
1541    /// Types from a single namespace in alphabetical order.
1542    pub fn namespace_types<'a>(
1543        &'a self,
1544        ns_id: u16,
1545    ) -> Box<dyn Iterator<Item = (TypeId, &'a Type)> + 'a> {
1546        let ns = self.namespace(ns_id);
1547        Box::new(ns.index.values().map(move |&id| {
1548            (
1549                TypeId { ns_id, id },
1550                ns.types[id as usize].as_ref().unwrap(),
1551            )
1552        }))
1553    }
1554
1555    pub fn is_crate(&self, crate_name: &str) -> bool {
1556        self.namespace(MAIN_NAMESPACE).name == crate_name
1557    }
1558
1559    pub fn is_glib_crate(&self) -> bool {
1560        self.is_crate("GObject") || self.is_crate("GLib")
1561    }
1562}
1563
1564#[cfg(test)]
1565mod tests {
1566    use super::*;
1567
1568    #[test]
1569    fn basic_tids() {
1570        let lib = Library::new("Gtk");
1571
1572        assert_eq!(TypeId::tid_none().full_name(&lib), "*.None");
1573        assert_eq!(TypeId::tid_bool().full_name(&lib), "*.Boolean");
1574        assert_eq!(TypeId::tid_uint32().full_name(&lib), "*.UInt32");
1575        assert_eq!(TypeId::tid_c_bool().full_name(&lib), "*.Bool");
1576        assert_eq!(TypeId::tid_utf8().full_name(&lib), "*.Utf8");
1577        assert_eq!(TypeId::tid_filename().full_name(&lib), "*.Filename");
1578        assert_eq!(TypeId::tid_os_string().full_name(&lib), "*.OsString");
1579    }
1580}