gir_parser/
parameter.rs

1use xmlserde::xml_serde_enum;
2use xmlserde_derives::XmlDeserialize;
3
4use crate::{
5    array::Array,
6    attribute::Attribute,
7    documentation::{DocDeprecated, DocStability, DocVersion, Documentation, SourcePosition},
8    prelude::*,
9    r#type::Type,
10    FunctionScope, TransferOwnership,
11};
12
13xml_serde_enum! {
14    #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
15    Direction {
16        In => "in",
17        Out => "out",
18        InOut => "inout",
19    }
20}
21
22#[derive(Clone, Debug, PartialEq, Eq, XmlDeserialize)]
23pub enum ParameterType {
24    #[xmlserde(name = b"type")]
25    Type(Type),
26    #[xmlserde(name = b"array")]
27    Array(Array),
28    #[xmlserde(name = b"varargs")]
29    VarArgs,
30}
31
32impl From<crate::r#type::Type> for ParameterType {
33    fn from(value: crate::r#type::Type) -> Self {
34        Self::Type(value)
35    }
36}
37
38impl From<crate::r#type::AnyType> for ParameterType {
39    fn from(value: crate::r#type::AnyType) -> Self {
40        match value {
41            crate::r#type::AnyType::Array(arr) => Self::Array(arr),
42            crate::r#type::AnyType::Type(ty) => Self::Type(ty),
43        }
44    }
45}
46
47/// Represents either an instance parameter or a regular parameter
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum AnyParameter<'a> {
50    Instance(&'a InstanceParameter),
51    Regular(&'a Parameter),
52}
53
54impl<'a> AnyParameter<'a> {
55    pub fn name(&self) -> &str {
56        match self {
57            Self::Instance(p) => p.name(),
58            Self::Regular(p) => p.name(),
59        }
60    }
61
62    pub fn is_instance(&self) -> bool {
63        matches!(self, Self::Instance(_))
64    }
65
66    pub fn is_regular(&self) -> bool {
67        matches!(self, Self::Regular(_))
68    }
69
70    pub fn as_instance(&self) -> &'a InstanceParameter {
71        match self {
72            Self::Instance(p) => p,
73            _ => unreachable!(),
74        }
75    }
76
77    pub fn as_regular(&self) -> &'a Parameter {
78        match self {
79            Self::Regular(p) => p,
80            _ => unreachable!(),
81        }
82    }
83
84    pub fn is_nullable(&self) -> Option<bool> {
85        match self {
86            Self::Instance(p) => p.is_nullable(),
87            Self::Regular(p) => p.is_nullable(),
88        }
89    }
90
91    pub fn is_allow_none(&self) -> Option<bool> {
92        match self {
93            Self::Instance(p) => p.is_allow_none(),
94            Self::Regular(p) => p.is_allow_none(),
95        }
96    }
97
98    pub fn direction(&self) -> Option<Direction> {
99        match self {
100            Self::Instance(p) => p.direction(),
101            Self::Regular(p) => p.direction(),
102        }
103    }
104
105    pub fn is_caller_allocates(&self) -> Option<bool> {
106        match self {
107            Self::Instance(p) => p.is_caller_allocates(),
108            Self::Regular(p) => p.is_caller_allocates(),
109        }
110    }
111
112    pub fn transfer_ownership(&self) -> Option<TransferOwnership> {
113        match self {
114            Self::Instance(p) => p.transfer_ownership(),
115            Self::Regular(p) => p.transfer_ownership(),
116        }
117    }
118}
119
120#[derive(Clone, Debug, Default, PartialEq, Eq, XmlDeserialize)]
121#[xmlserde(root = b"parameters")]
122#[xmlserde(deny_unknown_fields)]
123pub struct Parameters {
124    #[xmlserde(name = b"instance-parameter", ty = "child")]
125    instance_parameter: Option<InstanceParameter>,
126    #[xmlserde(name = b"parameter", ty = "child")]
127    parameter: Vec<Parameter>,
128}
129
130impl Parameters {
131    pub fn is_empty(&self) -> bool {
132        self.instance_parameter.is_none() && self.parameter.is_empty()
133    }
134
135    pub fn instance(&self) -> Option<&InstanceParameter> {
136        self.instance_parameter.as_ref()
137    }
138
139    pub fn inner(&self) -> &[Parameter] {
140        &self.parameter
141    }
142
143    /// Returns an iterator over all parameters
144    pub fn all(&self) -> impl Iterator<Item = AnyParameter<'_>> {
145        self.instance_parameter
146            .iter()
147            .map(AnyParameter::Instance)
148            .chain(self.parameter.iter().map(AnyParameter::Regular))
149    }
150}
151
152impl IntoIterator for Parameters {
153    type Item = Parameter;
154    type IntoIter = std::vec::IntoIter<Self::Item>;
155
156    fn into_iter(self) -> Self::IntoIter {
157        self.parameter.into_iter()
158    }
159}
160
161impl<'a> IntoIterator for &'a Parameters {
162    type Item = &'a Parameter;
163    type IntoIter = std::slice::Iter<'a, Parameter>;
164
165    fn into_iter(self) -> Self::IntoIter {
166        self.parameter.iter()
167    }
168}
169
170impl AsRef<[Parameter]> for Parameters {
171    fn as_ref(&self) -> &[Parameter] {
172        &self.parameter
173    }
174}
175
176impl std::ops::Deref for Parameters {
177    type Target = [Parameter];
178
179    fn deref(&self) -> &Self::Target {
180        &self.parameter
181    }
182}
183
184impl std::ops::Index<usize> for Parameters {
185    type Output = Parameter;
186
187    fn index(&self, index: usize) -> &Self::Output {
188        &self.parameter[index]
189    }
190}
191
192#[derive(Clone, Debug, PartialEq, Eq, XmlDeserialize)]
193#[xmlserde(root = b"parameter")]
194#[xmlserde(deny_unknown_fields)]
195pub struct Parameter {
196    #[xmlserde(name = b"name", ty = "attr")]
197    name: String,
198    #[xmlserde(name = b"transfer-ownership", ty = "attr")]
199    transfer: Option<TransferOwnership>,
200    #[xmlserde(name = b"nullable", ty = "attr")]
201    nullable: Option<bool>,
202    #[xmlserde(name = b"allow-none", ty = "attr")]
203    allow_none: Option<bool>,
204    #[xmlserde(name = b"introspectable", ty = "attr")]
205    introspectable: Option<bool>,
206    #[xmlserde(name = b"scope", ty = "attr")]
207    scope: Option<FunctionScope>,
208    #[xmlserde(name = b"closure", ty = "attr")]
209    closure: Option<usize>,
210    #[xmlserde(name = b"destroy", ty = "attr")]
211    destroy: Option<usize>,
212    #[xmlserde(name = b"direction", ty = "attr")]
213    direction: Option<Direction>,
214    #[xmlserde(name = b"caller-allocates", ty = "attr")]
215    caller_allocates: Option<bool>,
216    #[xmlserde(name = b"optional", ty = "attr")]
217    optional: Option<bool>,
218    #[xmlserde(name = b"skip", ty = "attr")]
219    skip: Option<bool>,
220    // Documentation
221    #[xmlserde(name = b"doc", ty = "child")]
222    doc: Option<Documentation>,
223    #[xmlserde(name = b"doc-deprecated", ty = "child")]
224    doc_deprecated: Option<DocDeprecated>,
225    #[xmlserde(name = b"doc-stability", ty = "child")]
226    doc_stability: Option<DocStability>,
227    #[xmlserde(name = b"doc-version", ty = "child")]
228    doc_version: Option<DocVersion>,
229    #[xmlserde(name = b"source-position", ty = "child")]
230    source_position: Option<SourcePosition>,
231    // Attributes: 0 or more
232    #[xmlserde(name = b"attribute", ty = "child")]
233    attributes: Vec<Attribute>,
234    #[xmlserde(ty = "untag")]
235    type_: Option<ParameterType>,
236}
237
238impl Parameter {
239    pub fn name(&self) -> &str {
240        &self.name
241    }
242
243    pub fn is_nullable(&self) -> Option<bool> {
244        self.nullable
245    }
246
247    pub fn is_allow_none(&self) -> Option<bool> {
248        self.allow_none
249    }
250
251    pub fn is_introspectable(&self) -> bool {
252        self.introspectable.unwrap_or(true)
253    }
254
255    pub fn scope(&self) -> Option<FunctionScope> {
256        self.scope
257    }
258
259    pub fn closure(&self) -> Option<usize> {
260        self.closure
261    }
262
263    pub fn destroy(&self) -> Option<usize> {
264        self.destroy
265    }
266
267    pub fn direction(&self) -> Option<Direction> {
268        self.direction
269    }
270
271    pub fn is_caller_allocates(&self) -> Option<bool> {
272        self.caller_allocates
273    }
274
275    pub fn is_optional(&self) -> Option<bool> {
276        self.optional
277    }
278
279    pub fn is_skip(&self) -> Option<bool> {
280        self.skip
281    }
282
283    pub fn transfer_ownership(&self) -> Option<TransferOwnership> {
284        self.transfer
285    }
286
287    pub fn ty(&self) -> Option<&ParameterType> {
288        self.type_.as_ref()
289    }
290}
291
292impl_attributable!(Parameter);
293impl_documentable!(Parameter);
294
295#[derive(Clone, Debug, PartialEq, Eq, XmlDeserialize)]
296#[xmlserde(root = b"instance-parameter")]
297#[xmlserde(deny_unknown_fields)]
298pub struct InstanceParameter {
299    #[xmlserde(name = b"name", ty = "attr")]
300    name: String,
301    #[xmlserde(name = b"transfer-ownership", ty = "attr")]
302    transfer: Option<TransferOwnership>,
303    #[xmlserde(name = b"nullable", ty = "attr")]
304    nullable: Option<bool>,
305    #[xmlserde(name = b"allow-none", ty = "attr")]
306    allow_none: Option<bool>,
307    #[xmlserde(name = b"direction", ty = "attr")]
308    direction: Option<Direction>,
309    #[xmlserde(name = b"caller-allocates", ty = "attr")]
310    caller_allocates: Option<bool>,
311    // Documentation
312    #[xmlserde(name = b"doc", ty = "child")]
313    doc: Option<Documentation>,
314    #[xmlserde(name = b"doc-deprecated", ty = "child")]
315    doc_deprecated: Option<DocDeprecated>,
316    #[xmlserde(name = b"doc-stability", ty = "child")]
317    doc_stability: Option<DocStability>,
318    #[xmlserde(name = b"doc-version", ty = "child")]
319    doc_version: Option<DocVersion>,
320    #[xmlserde(name = b"source-position", ty = "child")]
321    source_position: Option<SourcePosition>,
322    #[xmlserde(name = b"type", ty = "child")]
323    type_: Option<Type>,
324}
325
326impl InstanceParameter {
327    pub fn name(&self) -> &str {
328        &self.name
329    }
330
331    pub fn is_nullable(&self) -> Option<bool> {
332        self.nullable
333    }
334
335    pub fn is_allow_none(&self) -> Option<bool> {
336        self.allow_none
337    }
338
339    pub fn direction(&self) -> Option<Direction> {
340        self.direction
341    }
342
343    pub fn is_caller_allocates(&self) -> Option<bool> {
344        self.caller_allocates
345    }
346
347    pub fn transfer_ownership(&self) -> Option<TransferOwnership> {
348        self.transfer
349    }
350
351    pub fn ty(&self) -> Option<&Type> {
352        self.type_.as_ref()
353    }
354}
355
356impl_documentable!(InstanceParameter);