libgir/analysis/
types.rs
1use crate::library::*;
2
3const RUST_DERIVE_ARRAY_SIZE_LIMIT: u16 = 32;
5const RUST_DERIVE_PARAM_SIZE_LIMIT: usize = 12;
8
9pub trait IsPtr {
11 fn is_ptr(&self) -> bool;
12}
13
14impl IsPtr for Field {
15 fn is_ptr(&self) -> bool {
16 if let Some(ref c_type) = self.c_type {
17 c_type.contains('*')
18 } else {
19 false
23 }
24 }
25}
26
27impl IsPtr for Alias {
28 fn is_ptr(&self) -> bool {
29 self.target_c_type.contains('*')
30 }
31}
32
33pub trait IsVolatile {
35 fn is_volatile(&self) -> bool;
36}
37
38impl IsVolatile for Field {
39 fn is_volatile(&self) -> bool {
40 if let Some(ref c_type) = self.c_type {
41 c_type.starts_with("volatile")
42 } else {
43 false
44 }
45 }
46}
47
48pub trait IsIncomplete {
50 fn is_incomplete(&self, lib: &Library) -> bool;
51}
52
53impl IsIncomplete for Basic {
54 fn is_incomplete(&self, _lib: &Library) -> bool {
55 matches!(*self, Self::None | Self::Unsupported | Self::VarArgs)
56 }
57}
58
59impl IsIncomplete for Alias {
60 fn is_incomplete(&self, lib: &Library) -> bool {
61 if self.is_ptr() {
62 false
63 } else {
64 lib.type_(self.typ).is_incomplete(lib)
65 }
66 }
67}
68
69impl IsIncomplete for Field {
70 fn is_incomplete(&self, lib: &Library) -> bool {
71 if self.is_ptr() {
72 false
74 } else {
75 lib.type_(self.typ).is_incomplete(lib)
76 }
77 }
78}
79
80impl IsIncomplete for &[Field] {
81 fn is_incomplete(&self, lib: &Library) -> bool {
82 if self.is_empty() {
83 return true;
84 }
85
86 let mut is_bitfield = false;
87 for field in self.iter() {
88 if field.is_incomplete(lib) {
89 return true;
90 }
91 if is_bitfield && field.bits.is_some() {
94 return true;
95 }
96 is_bitfield = field.bits.is_some();
97 }
98
99 false
100 }
101}
102
103impl IsIncomplete for Class {
104 fn is_incomplete(&self, lib: &Library) -> bool {
105 self.fields.as_slice().is_incomplete(lib)
106 }
107}
108
109impl IsIncomplete for Record {
110 fn is_incomplete(&self, lib: &Library) -> bool {
111 if self.c_type == "GHookList" || self.disguised || self.pointer {
112 false
114 } else {
115 self.fields.as_slice().is_incomplete(lib)
116 }
117 }
118}
119
120impl IsIncomplete for Union {
121 fn is_incomplete(&self, lib: &Library) -> bool {
122 self.fields.as_slice().is_incomplete(lib)
123 }
124}
125
126impl IsIncomplete for Function {
127 fn is_incomplete(&self, lib: &Library) -> bool {
128 self.parameters.iter().any(|p| {
130 matches!(
131 lib.type_(p.typ),
132 Type::Basic(Basic::Unsupported | Basic::VarArgs)
133 )
134 })
135 }
136}
137
138impl IsIncomplete for TypeId {
139 fn is_incomplete(&self, lib: &Library) -> bool {
140 lib.type_(*self).is_incomplete(lib)
141 }
142}
143
144impl IsIncomplete for Type {
145 fn is_incomplete(&self, lib: &Library) -> bool {
146 match self {
147 Type::Basic(basic) => basic.is_incomplete(lib),
148 Type::Alias(alias) => alias.is_incomplete(lib),
149 Type::FixedArray(tid, ..) => tid.is_incomplete(lib),
150 Type::Class(klass) => klass.is_incomplete(lib),
151 Type::Record(record) => record.is_incomplete(lib),
152 Type::Union(union) => union.is_incomplete(lib),
153 Type::Function(function) => function.is_incomplete(lib),
154 Type::Interface(..) => true,
155 Type::Custom(..)
156 | Type::Enumeration(..)
157 | Type::Bitfield(..)
158 | Type::Array(..)
159 | Type::CArray(..)
160 | Type::PtrArray(..)
161 | Type::HashTable(..)
162 | Type::List(..)
163 | Type::SList(..) => false,
164 }
165 }
166}
167
168pub trait IsExternal {
170 fn is_external(&self, lib: &Library) -> bool;
171}
172
173impl IsExternal for Class {
174 fn is_external(&self, _lib: &Library) -> bool {
175 self.fields.is_empty()
176 }
177}
178
179impl IsExternal for Record {
180 fn is_external(&self, _lib: &Library) -> bool {
181 self.fields.is_empty()
182 }
183}
184
185impl IsExternal for Union {
186 fn is_external(&self, _lib: &Library) -> bool {
187 self.fields.is_empty()
188 }
189}
190
191impl IsExternal for Alias {
192 fn is_external(&self, lib: &Library) -> bool {
193 if self.is_ptr() {
194 false
195 } else {
196 lib.type_(self.typ).is_external(lib)
197 }
198 }
199}
200
201impl IsExternal for Type {
202 fn is_external(&self, lib: &Library) -> bool {
203 match self {
204 Type::Alias(alias) => alias.is_external(lib),
205 Type::Class(klass) => klass.is_external(lib),
206 Type::Record(record) => record.is_external(lib),
207 Type::Union(union) => union.is_external(lib),
208 Type::Interface(..) => true,
209 Type::Custom(..)
210 | Type::Basic(..)
211 | Type::Enumeration(..)
212 | Type::Bitfield(..)
213 | Type::Function(..)
214 | Type::Array(..)
215 | Type::CArray(..)
216 | Type::FixedArray(..)
217 | Type::PtrArray(..)
218 | Type::HashTable(..)
219 | Type::List(..)
220 | Type::SList(..) => false,
221 }
222 }
223}
224
225pub trait DerivesCopy {
227 fn derives_copy(&self, lib: &Library) -> bool;
228}
229
230impl<T: IsIncomplete> DerivesCopy for T {
231 fn derives_copy(&self, lib: &Library) -> bool {
232 !self.is_incomplete(lib)
234 }
235}
236
237pub trait ImplementsDebug {
239 fn implements_debug(&self, lib: &Library) -> bool;
240}
241
242impl ImplementsDebug for Field {
243 fn implements_debug(&self, lib: &Library) -> bool {
244 match *lib.type_(self.typ) {
245 Type::FixedArray(_, size, _) => size <= RUST_DERIVE_ARRAY_SIZE_LIMIT,
246 Type::Function(Function { ref parameters, .. }) => {
247 parameters.len() <= RUST_DERIVE_PARAM_SIZE_LIMIT
248 }
249 _ => true,
250 }
251 }
252}