1use xmlserde_derives::XmlDeserialize;
2
3use crate::{
4 alias::Alias,
5 attribute::Attribute,
6 bitfield::BitField,
7 boxed::Boxed,
8 callback::Callback,
9 class::Class,
10 constant::Constant,
11 enums::Enumeration,
12 function::{Function, FunctionInline},
13 function_macro::FunctionMacro,
14 interface::Interface,
15 prelude::*,
16 record::Record,
17 union::Union,
18 version::Version,
19};
20
21#[derive(Clone, Debug, XmlDeserialize)]
22#[cfg_attr(test, derive(Default))]
23#[xmlserde(root = b"namespace")]
24#[xmlserde(deny_unknown_fields)]
25pub struct Namespace {
26 #[xmlserde(name = b"name", ty = "attr")]
27 name: String,
28 #[xmlserde(name = b"version", ty = "attr")]
29 version: Version,
30 #[xmlserde(name = b"c:identifier-prefixes", ty = "attr")]
31 c_identifier_prefixes: Option<String>,
32 #[xmlserde(name = b"c:prefix", ty = "attr")]
34 c_prefix: Option<String>,
35 #[xmlserde(name = b"c:symbol-prefixes", ty = "attr")]
36 c_symbol_prefixes: Option<String>,
37 #[xmlserde(name = b"shared-library", ty = "attr")]
38 shared_library: Option<String>,
39
40 #[xmlserde(name = b"alias", ty = "child")]
41 aliases: Vec<Alias>,
42 #[xmlserde(name = b"class", ty = "child")]
43 classes: Vec<Class>,
44 #[xmlserde(name = b"interface", ty = "child")]
45 interfaces: Vec<Interface>,
46 #[xmlserde(name = b"record", ty = "child")]
47 records: Vec<Record>,
48 #[xmlserde(name = b"enumeration", ty = "child")]
49 enums: Vec<Enumeration>,
50 #[xmlserde(name = b"function", ty = "child")]
51 functions_global: Vec<Function>,
52 #[xmlserde(name = b"function-inline", ty = "child")]
53 inline_functions: Vec<FunctionInline>,
54 #[xmlserde(name = b"function-macro", ty = "child")]
55 functions_macro: Vec<FunctionMacro>,
56 #[xmlserde(name = b"union", ty = "child")]
57 unions: Vec<Union>,
58 #[xmlserde(name = b"bitfield", ty = "child")]
59 flags: Vec<BitField>,
60 #[xmlserde(name = b"callback", ty = "child")]
61 callbacks: Vec<Callback>,
62 #[xmlserde(name = b"constant", ty = "child")]
63 constants: Vec<Constant>,
64 #[xmlserde(name = b"attribute", ty = "child")]
66 attributes: Vec<Attribute>,
67 #[xmlserde(name = b"glib:boxed", ty = "child")]
68 boxed: Vec<Boxed>,
69}
70
71impl Namespace {
72 pub fn name(&self) -> &str {
73 &self.name
74 }
75
76 pub fn version(&self) -> &Version {
77 &self.version
78 }
79
80 pub fn c_identifier_prefixes(&self) -> &str {
81 self.c_identifier_prefixes
82 .as_ref()
83 .or(self.c_prefix.as_ref())
84 .unwrap()
85 }
86
87 pub fn c_symbol_prefixes(&self) -> Option<&str> {
88 self.c_symbol_prefixes.as_deref()
89 }
90
91 pub fn shared_library(&self) -> Option<&str> {
92 self.shared_library.as_deref()
93 }
94
95 pub fn aliases(&self) -> &[Alias] {
96 &self.aliases
97 }
98
99 pub fn constants(&self) -> &[Constant] {
100 &self.constants
101 }
102
103 pub fn functions(&self) -> &[Function] {
104 &self.functions_global
105 }
106
107 pub fn inlined_functions(&self) -> &[FunctionInline] {
108 &self.inline_functions
109 }
110
111 pub fn macros(&self) -> &[FunctionMacro] {
112 &self.functions_macro
113 }
114
115 pub fn enums(&self) -> &[Enumeration] {
116 &self.enums
117 }
118
119 pub fn flags(&self) -> &[BitField] {
120 &self.flags
121 }
122
123 pub fn unions(&self) -> &[Union] {
124 &self.unions
125 }
126
127 pub fn boxed(&self) -> &[Boxed] {
128 &self.boxed
129 }
130
131 pub fn records(&self) -> &[Record] {
132 &self.records
133 }
134
135 pub fn classes(&self) -> &[Class] {
136 &self.classes
137 }
138
139 pub fn callbacks(&self) -> &[Callback] {
140 &self.callbacks
141 }
142
143 pub fn interfaces(&self) -> &[Interface] {
144 &self.interfaces
145 }
146
147 pub fn link_name(&self) -> Option<&str> {
149 let mut s = self.shared_library.as_deref()?;
150
151 if s.starts_with("lib") {
152 s = &s[3..];
153 }
154
155 if let Some(offset) = s.rfind(".so") {
156 s = &s[..offset];
157 } else if let Some(offset) = s.rfind(".dll") {
158 s = &s[..offset];
159 if let Some(offset) = s.rfind('-') {
160 s = &s[..offset];
161 }
162 }
163
164 Some(s)
165 }
166}
167
168impl_attributable!(Namespace);
169
170#[cfg(test)]
171mod tests {
172 #[test]
173 fn shared_library_to_link_name() {
174 let mut namespace = super::Namespace::default();
175 let tests = [
176 ("libgtk-4-1.dll", "gtk-4"),
177 ("libatk-1.0.so.0", "atk-1.0"),
178 ("libgdk_pixbuf-2.0.so.0", "gdk_pixbuf-2.0"),
179 ];
180 for (shared_lib, expected_result) in tests {
181 namespace.shared_library = Some(shared_lib.to_owned());
182 assert_eq!(namespace.link_name(), Some(expected_result));
183 }
184 }
185}