Skip to main content

mago_codex/ttype/
flags.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4/// Flags representing various properties of a type union.
5///
6/// This replaces 9 individual boolean fields with a compact 16-bit representation,
7/// reducing memory usage from 9 bytes to 2 bytes per TUnion instance.
8#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
9pub struct UnionFlags(u16);
10
11impl UnionFlags {
12    /// Indicates the union had a template type at some point.
13    pub const HAD_TEMPLATE: UnionFlags = UnionFlags(1 << 0);
14    /// Indicates the value is passed by reference.
15    pub const BY_REFERENCE: UnionFlags = UnionFlags(1 << 1);
16    /// Indicates no references exist to this type.
17    pub const REFERENCE_FREE: UnionFlags = UnionFlags(1 << 2);
18    /// Indicates the type may be undefined due to a try block.
19    pub const POSSIBLY_UNDEFINED_FROM_TRY: UnionFlags = UnionFlags(1 << 3);
20    /// Indicates the type may be undefined.
21    pub const POSSIBLY_UNDEFINED: UnionFlags = UnionFlags(1 << 4);
22    /// Indicates nullable issues should be ignored for this type.
23    pub const IGNORE_NULLABLE_ISSUES: UnionFlags = UnionFlags(1 << 5);
24    /// Indicates falsable issues should be ignored for this type.
25    pub const IGNORE_FALSABLE_ISSUES: UnionFlags = UnionFlags(1 << 6);
26    /// Indicates the type came from a template default value.
27    pub const FROM_TEMPLATE_DEFAULT: UnionFlags = UnionFlags(1 << 7);
28    /// Indicates the type has been populated with codebase information.
29    pub const POPULATED: UnionFlags = UnionFlags(1 << 8);
30    /// Indicates the null in this union came from nullsafe short-circuit.
31    pub const NULLSAFE_NULL: UnionFlags = UnionFlags(1 << 9);
32}
33
34impl UnionFlags {
35    #[inline]
36    #[must_use]
37    pub const fn empty() -> Self {
38        UnionFlags(0)
39    }
40
41    #[inline]
42    pub const fn insert(&mut self, flag: UnionFlags) {
43        self.0 |= flag.0;
44    }
45
46    #[inline]
47    pub const fn set(&mut self, flag: UnionFlags, value: bool) {
48        if value {
49            self.insert(flag);
50        } else {
51            self.0 &= !flag.0;
52        }
53    }
54
55    #[inline]
56    pub const fn contains(self, flag: UnionFlags) -> bool {
57        (self.0 & flag.0) == flag.0
58    }
59
60    #[inline]
61    pub const fn intersects(self, other: UnionFlags) -> bool {
62        (self.0 & other.0) != 0
63    }
64
65    #[inline]
66    #[must_use]
67    pub const fn union(&self, other: UnionFlags) -> UnionFlags {
68        UnionFlags(self.0 | other.0)
69    }
70
71    #[inline]
72    #[must_use]
73    pub const fn intersection(&self, other: UnionFlags) -> UnionFlags {
74        UnionFlags(self.0 & other.0)
75    }
76}
77
78impl std::ops::BitOr for UnionFlags {
79    type Output = Self;
80
81    #[inline]
82    fn bitor(self, rhs: Self) -> Self::Output {
83        UnionFlags(self.0 | rhs.0)
84    }
85}
86
87impl std::ops::BitOrAssign for UnionFlags {
88    #[inline]
89    fn bitor_assign(&mut self, rhs: Self) {
90        self.0 |= rhs.0;
91    }
92}
93
94impl std::ops::BitAnd for UnionFlags {
95    type Output = Self;
96
97    #[inline]
98    fn bitand(self, rhs: Self) -> Self::Output {
99        UnionFlags(self.0 & rhs.0)
100    }
101}
102
103impl std::ops::BitAndAssign for UnionFlags {
104    #[inline]
105    fn bitand_assign(&mut self, rhs: Self) {
106        self.0 &= rhs.0;
107    }
108}
109
110impl std::ops::Not for UnionFlags {
111    type Output = Self;
112
113    #[inline]
114    fn not(self) -> Self::Output {
115        UnionFlags(!self.0)
116    }
117}