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