1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
use crate::{
    attribute::Attribute,
    documentation::{DocDeprecated, DocStability, DocVersion, Documentation, SourcePosition},
    version::Version,
    Parameters, ReturnValue, Stability,
};

pub trait Documentable {
    fn doc(&self) -> Option<&Documentation>;
    fn doc_deprecated(&self) -> Option<&DocDeprecated>;
    fn doc_stability(&self) -> Option<&DocStability>;
    fn doc_version(&self) -> Option<&DocVersion>;
    fn source_position(&self) -> Option<&SourcePosition>;
}

pub trait Attributable {
    fn attributes(&self) -> &[Attribute];

    fn element_type(&self) -> Option<&str> {
        self.attributes()
            .iter()
            .find(|a| a.name() == "element-type")
            .map(|a| a.value())
    }

    fn gtk_property_get(&self) -> Option<&str> {
        self.attributes()
            .iter()
            .find(|a| a.name() == "org.gtk.Property.get")
            .map(|a| a.value())
    }

    fn gtk_method_get_property(&self) -> Option<&str> {
        self.attributes()
            .iter()
            .find(|a| a.name() == "org.gtk.Method.get_property")
            .map(|a| a.value())
    }

    fn gtk_property_set(&self) -> Option<&str> {
        self.attributes()
            .iter()
            .find(|a| a.name() == "org.gtk.Property.set")
            .map(|a| a.value())
    }

    fn gtk_method_set_property(&self) -> Option<&str> {
        self.attributes()
            .iter()
            .find(|a| a.name() == "org.gtk.Method.set_property")
            .map(|a| a.value())
    }
}

pub trait Info: Documentable + Attributable {
    fn is_introspectable(&self) -> bool;
    fn is_deprecated(&self) -> bool;
    fn version(&self) -> Option<&Version>;
    fn deprecated_version(&self) -> Option<&Version>;
    fn stability(&self) -> Option<Stability>;
}

pub trait Callable: Info {
    fn name(&self) -> &str;
    fn c_identifier(&self) -> Option<&str>;
    fn shadows(&self) -> Option<&str>;
    fn shadowed_by(&self) -> Option<&str>;
    fn moved_to(&self) -> Option<&str>;
    fn async_func(&self) -> Option<&str>;
    fn finish_func(&self) -> Option<&str>;
    fn sync_func(&self) -> Option<&str>;
}

macro_rules! impl_documentable {
    ($rust_type:ident) => {
        impl Documentable for $rust_type {
            fn doc(&self) -> Option<&Documentation> {
                self.doc.as_ref()
            }
            fn doc_deprecated(&self) -> Option<&DocDeprecated> {
                self.doc_deprecated.as_ref()
            }
            fn doc_stability(&self) -> Option<&DocStability> {
                self.doc_stability.as_ref()
            }
            fn doc_version(&self) -> Option<&DocVersion> {
                self.doc_version.as_ref()
            }
            fn source_position(&self) -> Option<&SourcePosition> {
                self.source_position.as_ref()
            }
        }
    };
}

macro_rules! impl_attributable {
    ($rust_type:ident) => {
        impl Attributable for $rust_type {
            fn attributes(&self) -> &[Attribute] {
                &self.attributes
            }
        }
    };
}

macro_rules! impl_info {
    ($rust_type:ident) => {
        impl Info for $rust_type {
            fn is_introspectable(&self) -> bool {
                self.introspectable.unwrap_or(true)
            }

            fn is_deprecated(&self) -> bool {
                self.deprecated.unwrap_or(false)
            }

            fn version(&self) -> Option<&Version> {
                self.version.as_ref()
            }

            fn deprecated_version(&self) -> Option<&Version> {
                self.deprecated_version.as_ref()
            }

            fn stability(&self) -> Option<Stability> {
                self.stability
            }
        }
    };
}

macro_rules! impl_callable {
    ($rust_type:ident) => {
        impl Callable for $rust_type {
            fn name(&self) -> &str {
                &self.name
            }

            fn c_identifier(&self) -> Option<&str> {
                self.c_identifier.as_deref()
            }

            fn shadows(&self) -> Option<&str> {
                self.shadows.as_deref()
            }

            fn shadowed_by(&self) -> Option<&str> {
                self.shadowed_by.as_deref()
            }

            fn moved_to(&self) -> Option<&str> {
                self.moved_to.as_deref()
            }

            fn async_func(&self) -> Option<&str> {
                self.async_func.as_deref()
            }

            fn finish_func(&self) -> Option<&str> {
                self.finish_func.as_deref()
            }

            fn sync_func(&self) -> Option<&str> {
                self.sync_func.as_deref()
            }
        }
    };
}

pub trait FunctionLike: Attributable + Info + Documentable {
    fn throws(&self) -> bool;
    fn return_value(&self) -> &ReturnValue;
    fn parameters(&self) -> &Parameters;
}

macro_rules! impl_function_like {
    ($rust_type:ident) => {
        impl FunctionLike for $rust_type {
            fn throws(&self) -> bool {
                self.throws.unwrap_or(false)
            }

            fn return_value(&self) -> &ReturnValue {
                &self.return_value
            }

            fn parameters(&self) -> &Parameters {
                &self.parameters
            }
        }
    };
}