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