1use crate::type_kind::TypeKind;
7
8#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
10pub struct TypeFlags(u32);
11
12impl Default for TypeFlags {
13 fn default() -> Self {
14 Self::new()
15 }
16}
17
18impl TypeFlags {
19 pub const NONE: Self = Self(0);
20 pub const IS_BLITTABLE: Self = Self(1 << 0);
22 pub const IS_SCALAR: Self = Self(1 << 1);
24 pub const IS_STORAGE: Self = Self(1 << 2);
26 pub const IS_ALLOWED_RETURN: Self = Self(1 << 3);
27
28 #[must_use]
29 pub const fn new() -> Self {
30 Self::NONE
31 }
32
33 #[must_use]
34 pub const fn contains(self, flag: Self) -> bool {
35 (self.0 & flag.0) != 0
36 }
37
38 #[must_use]
39 pub const fn union(self, other: Self) -> Self {
40 Self(self.0 | other.0)
41 }
42
43 #[allow(clippy::too_many_lines)]
45 #[must_use]
46 pub fn compute_for_type_kind(kind: &TypeKind) -> Self {
47 let mut flags = Self::NONE;
48
49 match kind {
50 TypeKind::Codepoint => {
51 flags = flags
52 .union(Self::IS_BLITTABLE)
53 .union(Self::IS_STORAGE)
54 .union(Self::IS_ALLOWED_RETURN)
55 .union(Self::IS_SCALAR);
56 }
57 TypeKind::Byte => {
58 flags = flags
59 .union(Self::IS_BLITTABLE)
60 .union(Self::IS_STORAGE)
61 .union(Self::IS_ALLOWED_RETURN)
62 .union(Self::IS_SCALAR);
63 }
64 TypeKind::Int => {
65 flags = flags
66 .union(Self::IS_BLITTABLE)
67 .union(Self::IS_STORAGE)
68 .union(Self::IS_ALLOWED_RETURN)
69 .union(Self::IS_SCALAR);
70 }
71 TypeKind::String(..) => {
72 flags = flags
73 .union(Self::IS_BLITTABLE)
74 .union(Self::IS_ALLOWED_RETURN)
75 .union(Self::IS_SCALAR);
76 }
77 TypeKind::StringStorage(_, _, _) => {
78 flags = flags
79 .union(Self::IS_BLITTABLE)
80 .union(Self::IS_STORAGE)
81 .union(Self::IS_SCALAR);
82 }
83
84 TypeKind::Float => {
85 flags = flags
86 .union(Self::IS_BLITTABLE)
87 .union(Self::IS_STORAGE)
88 .union(Self::IS_ALLOWED_RETURN)
89 .union(Self::IS_SCALAR);
90 }
91 TypeKind::Bool => {
92 flags = flags
93 .union(Self::IS_BLITTABLE)
94 .union(Self::IS_STORAGE)
95 .union(Self::IS_ALLOWED_RETURN)
96 .union(Self::IS_SCALAR);
97 }
98 TypeKind::Unit => {
99 flags = flags
100 .union(Self::IS_BLITTABLE)
101 .union(Self::IS_STORAGE)
102 .union(Self::IS_ALLOWED_RETURN)
103 .union(Self::IS_SCALAR);
104 }
105 TypeKind::Function(_) => {}
106 TypeKind::Enum(enum_type) => {
107 if enum_type.are_all_variants_with_blittable_payload() {
108 flags = flags
109 .union(Self::IS_BLITTABLE)
110 .union(Self::IS_ALLOWED_RETURN);
111 } else {
112 panic!("enums should be blittable")
113 }
114 if enum_type.are_all_variants_with_storage_payload() {
115 flags = flags.union(Self::IS_STORAGE);
116 }
117 }
118 TypeKind::Tuple(types) => {
119 if types.iter().all(|t| t.flags.contains(Self::IS_BLITTABLE)) {
121 flags = flags
122 .union(Self::IS_BLITTABLE)
123 .union(Self::IS_ALLOWED_RETURN);
124 }
125 if types.iter().all(|t| t.flags.contains(Self::IS_STORAGE)) {
126 flags = flags.union(Self::IS_STORAGE);
127 }
128 }
129 TypeKind::Optional(inner) => {
130 if inner.flags.contains(Self::IS_BLITTABLE) {
132 flags = flags
133 .union(Self::IS_BLITTABLE)
134 .union(Self::IS_ALLOWED_RETURN);
135 }
136 if inner.flags.contains(Self::IS_STORAGE) {
137 flags = flags.union(Self::IS_STORAGE);
138 }
139 }
140 TypeKind::NamedStruct(named) => {
141 if named.anon_struct_type.flags.contains(Self::IS_BLITTABLE) {
142 flags = flags
143 .union(Self::IS_BLITTABLE)
144 .union(Self::IS_ALLOWED_RETURN);
145 }
146 if named.anon_struct_type.flags.contains(Self::IS_STORAGE) {
147 flags = flags.union(Self::IS_STORAGE);
148 }
149 }
150 TypeKind::AnonymousStruct(anon) => {
151 if anon
152 .field_name_sorted_fields
153 .iter()
154 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_BLITTABLE))
155 {
156 flags = flags
157 .union(Self::IS_BLITTABLE)
158 .union(Self::IS_ALLOWED_RETURN);
159 }
160
161 if anon
162 .field_name_sorted_fields
163 .iter()
164 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_STORAGE))
165 {
166 flags = flags.union(Self::IS_STORAGE);
167 }
168 }
169 TypeKind::MapStorage(key, value, _) => {
170 if key.is_blittable() && value.is_blittable() {
171 flags = flags.union(Self::IS_BLITTABLE);
172 }
173
174 if key.is_storage() && value.is_storage() {
175 flags = flags.union(Self::IS_STORAGE);
176 }
177 }
178 TypeKind::DynamicLengthMapView(_, _) => {
179 flags = flags.union(Self::IS_ALLOWED_RETURN);
180 }
181 TypeKind::FixedCapacityAndLengthArray(inner, _) => {
182 if inner.is_blittable() {
183 flags = flags.union(Self::IS_BLITTABLE);
184 }
185 if inner.is_storage() {
186 flags = flags.union(Self::IS_STORAGE);
187 }
188 }
189 TypeKind::SliceView(_) => {
190 flags = flags.union(Self::IS_ALLOWED_RETURN);
191 }
192 TypeKind::VecStorage(inner, _) => {
193 if inner.is_blittable() {
194 flags = flags.union(Self::IS_BLITTABLE);
195 }
196 if inner.is_storage() {
197 flags = flags.union(Self::IS_STORAGE);
198 }
199 }
200 TypeKind::DynamicLengthVecView(_) => {
201 flags = flags.union(Self::IS_ALLOWED_RETURN);
202 }
203
204 TypeKind::StackStorage(inner, _) => {
205 if inner.is_blittable() {
206 flags = flags.union(Self::IS_BLITTABLE);
207 }
208 if inner.is_storage() {
209 flags = flags.union(Self::IS_STORAGE);
210 }
211 }
212 TypeKind::StackView(_) => {
213 flags = flags.union(Self::IS_ALLOWED_RETURN);
214 }
215
216 TypeKind::QueueStorage(inner, _) => {
217 if inner.is_blittable() {
218 flags = flags.union(Self::IS_BLITTABLE);
219 }
220 if inner.is_storage() {
221 flags = flags.union(Self::IS_STORAGE);
222 }
223 }
224 TypeKind::QueueView(_) => {
225 flags = flags.union(Self::IS_ALLOWED_RETURN);
226 }
227 TypeKind::GridStorage(inner, _, _) => {
228 if inner.is_blittable() {
229 flags = flags.union(Self::IS_BLITTABLE);
230 }
231 if inner.is_storage() {
232 flags = flags.union(Self::IS_STORAGE);
233 }
234 }
235 TypeKind::GridView(_) => {
236 flags = flags.union(Self::IS_ALLOWED_RETURN);
237 }
238 TypeKind::SparseStorage(inner, _) => {
239 if inner.is_blittable() {
240 flags = flags.union(Self::IS_BLITTABLE);
241 }
242 if inner.is_storage() {
243 flags = flags.union(Self::IS_STORAGE);
244 }
245 }
246 TypeKind::SparseView(_) => {
247 flags = flags.union(Self::IS_ALLOWED_RETURN);
248 }
249 TypeKind::Range(_inner) => {
250 flags = flags
251 .union(Self::IS_BLITTABLE)
252 .union(Self::IS_ALLOWED_RETURN);
253 flags = flags.union(Self::IS_STORAGE);
254 }
255 }
256
257 flags
258 }
259}