Skip to main content

mago_codex/metadata/
flags.rs

1use mago_database::file::FileType;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct MetadataFlags(u64);
6
7impl MetadataFlags {
8    #[inline]
9    #[must_use]
10    pub const fn bits(self) -> u64 {
11        self.0
12    }
13
14    pub const ABSTRACT: MetadataFlags = MetadataFlags(1 << 0);
15    pub const FINAL: MetadataFlags = MetadataFlags(1 << 1);
16    pub const READONLY: MetadataFlags = MetadataFlags(1 << 3);
17    pub const DEPRECATED: MetadataFlags = MetadataFlags(1 << 4);
18    pub const ENUM_INTERFACE: MetadataFlags = MetadataFlags(1 << 5);
19    pub const POPULATED: MetadataFlags = MetadataFlags(1 << 6);
20    pub const INTERNAL: MetadataFlags = MetadataFlags(1 << 7);
21    pub const CONSISTENT_CONSTRUCTOR: MetadataFlags = MetadataFlags(1 << 11);
22    pub const CONSISTENT_TEMPLATES: MetadataFlags = MetadataFlags(1 << 12);
23    pub const UNCHECKED: MetadataFlags = MetadataFlags(1 << 13);
24    pub const USER_DEFINED: MetadataFlags = MetadataFlags(1 << 14);
25    pub const BUILTIN: MetadataFlags = MetadataFlags(1 << 15);
26    pub const HAS_YIELD: MetadataFlags = MetadataFlags(1 << 16);
27    pub const MUST_USE: MetadataFlags = MetadataFlags(1 << 17);
28    pub const HAS_THROW: MetadataFlags = MetadataFlags(1 << 18);
29    pub const PURE: MetadataFlags = MetadataFlags(1 << 19);
30    pub const IGNORE_NULLABLE_RETURN: MetadataFlags = MetadataFlags(1 << 20);
31    pub const IGNORE_FALSABLE_RETURN: MetadataFlags = MetadataFlags(1 << 21);
32    pub const INHERITS_DOCS: MetadataFlags = MetadataFlags(1 << 22);
33    pub const NO_NAMED_ARGUMENTS: MetadataFlags = MetadataFlags(1 << 23);
34    pub const BACKED_ENUM_CASE: MetadataFlags = MetadataFlags(1 << 24);
35    pub const UNIT_ENUM_CASE: MetadataFlags = MetadataFlags(1 << 25);
36    pub const BY_REFERENCE: MetadataFlags = MetadataFlags(1 << 26);
37    pub const VARIADIC: MetadataFlags = MetadataFlags(1 << 27);
38    pub const PROMOTED_PROPERTY: MetadataFlags = MetadataFlags(1 << 28);
39    pub const HAS_DEFAULT: MetadataFlags = MetadataFlags(1 << 29);
40    pub const VIRTUAL_PROPERTY: MetadataFlags = MetadataFlags(1 << 30);
41    pub const ASYMMETRIC_PROPERTY: MetadataFlags = MetadataFlags(1 << 31);
42    pub const STATIC: MetadataFlags = MetadataFlags(1 << 32);
43    pub const WRITEONLY: MetadataFlags = MetadataFlags(1 << 33);
44    // Bit 34 was MAGIC_PROPERTY; magic properties are now identified by their entry in
45    // `ClassLikeMetadata::magic_properties` instead of a flag.
46    pub const MAGIC_METHOD: MetadataFlags = MetadataFlags(1 << 35);
47    pub const API: MetadataFlags = MetadataFlags(1 << 36);
48    pub const MUTATION_FREE: MetadataFlags = MetadataFlags(1 << 37);
49    pub const EXTERNAL_MUTATION_FREE: MetadataFlags = MetadataFlags(1 << 38);
50    pub const SUSPENDS_FIBER: MetadataFlags = MetadataFlags(1 << 39);
51    pub const EXPERIMENTAL: MetadataFlags = MetadataFlags(1 << 40);
52    pub const POLYFILL: MetadataFlags = MetadataFlags(1 << 41);
53    pub const PATCH: MetadataFlags = MetadataFlags(1 << 42);
54    pub const EXTERNAL: MetadataFlags = MetadataFlags(1 << 43);
55}
56
57impl MetadataFlags {
58    #[inline]
59    #[must_use]
60    pub const fn from_bits(bits: u64) -> Self {
61        Self(bits)
62    }
63
64    #[inline]
65    #[must_use]
66    pub const fn empty() -> Self {
67        MetadataFlags(0)
68    }
69
70    #[inline]
71    pub const fn insert(&mut self, other: MetadataFlags) {
72        self.0 |= other.0;
73    }
74
75    #[inline]
76    pub const fn set(&mut self, other: MetadataFlags, value: bool) {
77        if value {
78            self.insert(other);
79        } else {
80            self.0 &= !other.0;
81        }
82    }
83
84    #[inline]
85    #[must_use]
86    pub const fn contains(self, other: MetadataFlags) -> bool {
87        (self.0 & other.0) == other.0
88    }
89
90    #[inline]
91    pub const fn remove(&mut self, other: MetadataFlags) {
92        self.0 &= !other.0;
93    }
94}
95
96impl MetadataFlags {
97    #[inline]
98    #[must_use]
99    pub const fn is_deprecated(self) -> bool {
100        self.contains(Self::DEPRECATED)
101    }
102
103    #[inline]
104    #[must_use]
105    pub const fn is_abstract(self) -> bool {
106        self.contains(Self::ABSTRACT)
107    }
108
109    #[inline]
110    #[must_use]
111    pub const fn is_final(self) -> bool {
112        self.contains(Self::FINAL)
113    }
114
115    #[inline]
116    #[must_use]
117    pub const fn has_yield(self) -> bool {
118        self.contains(Self::HAS_YIELD)
119    }
120
121    #[inline]
122    #[must_use]
123    pub const fn must_use(self) -> bool {
124        self.contains(Self::MUST_USE)
125    }
126
127    #[inline]
128    #[must_use]
129    pub const fn is_pure(self) -> bool {
130        self.contains(Self::PURE)
131    }
132
133    #[inline]
134    #[must_use]
135    pub const fn has_consistent_constructor(self) -> bool {
136        self.contains(Self::CONSISTENT_CONSTRUCTOR)
137    }
138
139    #[inline]
140    #[must_use]
141    pub const fn has_consistent_templates(self) -> bool {
142        self.contains(Self::CONSISTENT_TEMPLATES)
143    }
144
145    #[inline]
146    #[must_use]
147    pub const fn is_user_defined(self) -> bool {
148        self.contains(Self::USER_DEFINED)
149    }
150
151    #[inline]
152    #[must_use]
153    pub const fn is_built_in(self) -> bool {
154        self.contains(Self::BUILTIN)
155    }
156
157    #[inline]
158    #[must_use]
159    pub const fn is_internal(self) -> bool {
160        self.contains(Self::INTERNAL)
161    }
162
163    #[inline]
164    #[must_use]
165    pub const fn is_populated(self) -> bool {
166        self.contains(Self::POPULATED)
167    }
168
169    #[inline]
170    #[must_use]
171    pub const fn is_readonly(self) -> bool {
172        self.contains(Self::READONLY)
173    }
174
175    #[inline]
176    #[must_use]
177    pub const fn is_writeonly(self) -> bool {
178        self.contains(Self::WRITEONLY)
179    }
180
181    #[inline]
182    #[must_use]
183    pub const fn is_enum_interface(self) -> bool {
184        self.contains(Self::ENUM_INTERFACE)
185    }
186
187    #[inline]
188    #[must_use]
189    pub const fn is_unchecked(self) -> bool {
190        self.contains(Self::UNCHECKED)
191    }
192
193    #[inline]
194    #[must_use]
195    pub const fn ignore_nullable_return(self) -> bool {
196        self.contains(Self::IGNORE_NULLABLE_RETURN)
197    }
198
199    #[inline]
200    #[must_use]
201    pub const fn ignore_falsable_return(self) -> bool {
202        self.contains(Self::IGNORE_FALSABLE_RETURN)
203    }
204
205    #[inline]
206    #[must_use]
207    pub const fn inherits_docs(self) -> bool {
208        self.contains(Self::INHERITS_DOCS)
209    }
210
211    #[inline]
212    #[must_use]
213    pub const fn forbids_named_arguments(self) -> bool {
214        self.contains(Self::NO_NAMED_ARGUMENTS)
215    }
216
217    #[inline]
218    #[must_use]
219    pub const fn has_throw(self) -> bool {
220        self.contains(Self::HAS_THROW)
221    }
222
223    #[inline]
224    #[must_use]
225    pub const fn is_backed_enum_case(self) -> bool {
226        self.contains(Self::BACKED_ENUM_CASE)
227    }
228
229    #[inline]
230    #[must_use]
231    pub const fn is_unit_enum_case(self) -> bool {
232        self.contains(Self::UNIT_ENUM_CASE)
233    }
234
235    #[inline]
236    #[must_use]
237    pub const fn is_by_reference(self) -> bool {
238        self.contains(Self::BY_REFERENCE)
239    }
240
241    #[inline]
242    #[must_use]
243    pub const fn is_variadic(self) -> bool {
244        self.contains(Self::VARIADIC)
245    }
246
247    #[inline]
248    #[must_use]
249    pub const fn is_promoted_property(self) -> bool {
250        self.contains(Self::PROMOTED_PROPERTY)
251    }
252
253    #[inline]
254    #[must_use]
255    pub const fn has_default(self) -> bool {
256        self.contains(Self::HAS_DEFAULT)
257    }
258
259    #[inline]
260    #[must_use]
261    pub const fn is_virtual_property(self) -> bool {
262        self.contains(Self::VIRTUAL_PROPERTY)
263    }
264
265    #[inline]
266    #[must_use]
267    pub const fn is_magic_method(self) -> bool {
268        self.contains(Self::MAGIC_METHOD)
269    }
270
271    #[inline]
272    #[must_use]
273    pub const fn is_asymmetric_property(self) -> bool {
274        self.contains(Self::ASYMMETRIC_PROPERTY)
275    }
276
277    #[inline]
278    #[must_use]
279    pub const fn is_static(self) -> bool {
280        self.contains(Self::STATIC)
281    }
282
283    #[inline]
284    #[must_use]
285    pub const fn is_public_api(self) -> bool {
286        self.contains(Self::API)
287    }
288
289    #[inline]
290    #[must_use]
291    pub const fn is_experimental(self) -> bool {
292        self.contains(Self::EXPERIMENTAL)
293    }
294
295    #[inline]
296    #[must_use]
297    pub const fn is_mutation_free(self) -> bool {
298        self.contains(Self::MUTATION_FREE)
299    }
300
301    #[inline]
302    #[must_use]
303    pub const fn is_external_mutation_free(self) -> bool {
304        self.contains(Self::EXTERNAL_MUTATION_FREE)
305    }
306
307    #[inline]
308    #[must_use]
309    pub const fn suspends_fiber(self) -> bool {
310        self.contains(Self::SUSPENDS_FIBER)
311    }
312
313    #[inline]
314    #[must_use]
315    pub const fn is_polyfill(self) -> bool {
316        self.contains(Self::POLYFILL)
317    }
318
319    #[inline]
320    #[must_use]
321    pub const fn is_patch(self) -> bool {
322        self.contains(Self::PATCH)
323    }
324
325    #[inline]
326    #[must_use]
327    pub const fn is_external(self) -> bool {
328        self.contains(Self::EXTERNAL)
329    }
330
331    #[inline]
332    #[must_use]
333    pub const fn origin_flags(file_type: FileType) -> Self {
334        match file_type {
335            FileType::Host => Self::USER_DEFINED,
336            FileType::Builtin => Self::BUILTIN,
337            FileType::Patch => Self::PATCH,
338            FileType::External => Self::EXTERNAL,
339            FileType::Vendored => Self::empty(),
340        }
341    }
342}
343
344impl std::ops::BitOr for MetadataFlags {
345    type Output = Self;
346
347    #[inline]
348    fn bitor(self, rhs: Self) -> Self::Output {
349        MetadataFlags(self.0 | rhs.0)
350    }
351}
352
353impl std::ops::BitAnd for MetadataFlags {
354    type Output = Self;
355
356    #[inline]
357    fn bitand(self, rhs: Self) -> Self::Output {
358        MetadataFlags(self.0 & rhs.0)
359    }
360}
361
362impl std::ops::BitXor for MetadataFlags {
363    type Output = Self;
364
365    #[inline]
366    fn bitxor(self, rhs: Self) -> Self::Output {
367        MetadataFlags(self.0 ^ rhs.0)
368    }
369}
370
371impl std::ops::Not for MetadataFlags {
372    type Output = Self;
373
374    #[inline]
375    fn not(self) -> Self::Output {
376        MetadataFlags(!self.0)
377    }
378}
379
380impl std::ops::BitOrAssign for MetadataFlags {
381    #[inline]
382    fn bitor_assign(&mut self, rhs: Self) {
383        self.0 |= rhs.0;
384    }
385}
386
387impl std::ops::BitAndAssign for MetadataFlags {
388    #[inline]
389    fn bitand_assign(&mut self, rhs: Self) {
390        self.0 &= rhs.0;
391    }
392}
393
394impl std::ops::BitXorAssign for MetadataFlags {
395    #[inline]
396    fn bitxor_assign(&mut self, rhs: Self) {
397        self.0 ^= rhs.0;
398    }
399}