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::Any => {
51 flags = flags
52 .union(Self::IS_BLITTABLE)
53 .union(Self::IS_STORAGE)
54 .union(Self::IS_ALLOWED_RETURN);
55 }
56 TypeKind::Codepoint => {
57 flags = flags
58 .union(Self::IS_BLITTABLE)
59 .union(Self::IS_STORAGE)
60 .union(Self::IS_ALLOWED_RETURN)
61 .union(Self::IS_SCALAR);
62 }
63 TypeKind::Byte => {
64 flags = flags
65 .union(Self::IS_BLITTABLE)
66 .union(Self::IS_STORAGE)
67 .union(Self::IS_ALLOWED_RETURN)
68 .union(Self::IS_SCALAR);
69 }
70 TypeKind::Int => {
71 flags = flags
72 .union(Self::IS_BLITTABLE)
73 .union(Self::IS_STORAGE)
74 .union(Self::IS_ALLOWED_RETURN)
75 .union(Self::IS_SCALAR);
76 }
77 TypeKind::String(..) => {
78 flags = flags
79 .union(Self::IS_BLITTABLE)
80 .union(Self::IS_ALLOWED_RETURN)
81 .union(Self::IS_SCALAR);
82 }
83 TypeKind::StringStorage(_, _, _) => {
84 flags = flags
85 .union(Self::IS_BLITTABLE)
86 .union(Self::IS_STORAGE)
87 .union(Self::IS_SCALAR);
88 }
89
90 TypeKind::Float => {
91 flags = flags
92 .union(Self::IS_BLITTABLE)
93 .union(Self::IS_STORAGE)
94 .union(Self::IS_ALLOWED_RETURN)
95 .union(Self::IS_SCALAR);
96 }
97 TypeKind::Bool => {
98 flags = flags
99 .union(Self::IS_BLITTABLE)
100 .union(Self::IS_STORAGE)
101 .union(Self::IS_ALLOWED_RETURN)
102 .union(Self::IS_SCALAR);
103 }
104 TypeKind::Unit => {
105 flags = flags
106 .union(Self::IS_BLITTABLE)
107 .union(Self::IS_STORAGE)
108 .union(Self::IS_ALLOWED_RETURN)
109 .union(Self::IS_SCALAR);
110 }
111 TypeKind::Function(_) => {}
112 TypeKind::Enum(enum_type) => {
113 if enum_type.are_all_variants_with_blittable_payload() {
114 flags = flags
115 .union(Self::IS_BLITTABLE)
116 .union(Self::IS_ALLOWED_RETURN);
117 } else {
118 panic!("enums should be blittable")
119 }
120 if enum_type.are_all_variants_with_storage_payload() {
121 flags = flags.union(Self::IS_STORAGE);
122 }
123 }
124 TypeKind::Tuple(types) => {
125 if types.iter().all(|t| t.flags.contains(Self::IS_BLITTABLE)) {
127 flags = flags
128 .union(Self::IS_BLITTABLE)
129 .union(Self::IS_ALLOWED_RETURN);
130 }
131 if types.iter().all(|t| t.flags.contains(Self::IS_STORAGE)) {
132 flags = flags.union(Self::IS_STORAGE);
133 }
134 }
135 TypeKind::Optional(inner) => {
136 if inner.flags.contains(Self::IS_BLITTABLE) {
138 flags = flags
139 .union(Self::IS_BLITTABLE);
140 }
141 if inner.flags.contains(Self::IS_ALLOWED_RETURN) {
143 flags = flags
144 .union(Self::IS_ALLOWED_RETURN);
145 }
146 if inner.flags.contains(Self::IS_STORAGE) {
147 flags = flags.union(Self::IS_STORAGE);
148 }
149 }
150 TypeKind::NamedStruct(named) => {
151 if named.anon_struct_type.flags.contains(Self::IS_BLITTABLE) {
152 flags = flags
153 .union(Self::IS_BLITTABLE);
154 }
155 if named.anon_struct_type.flags.contains(Self::IS_STORAGE) {
156 flags = flags.union(Self::IS_STORAGE);
157 }
158 if named.anon_struct_type.flags.contains(Self::IS_ALLOWED_RETURN) {
159 flags = flags
160 .union(Self::IS_ALLOWED_RETURN);
161 }
162 }
163 TypeKind::AnonymousStruct(anon) => {
164 if anon
165 .field_name_sorted_fields
166 .iter()
167 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_BLITTABLE))
168 {
169 flags = flags
170 .union(Self::IS_BLITTABLE);
171 }
172
173 anon
174 .field_name_sorted_fields
175 .iter()
176 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_ALLOWED_RETURN));
177 flags = flags
178 .union(Self::IS_ALLOWED_RETURN);
179
180 if anon
181 .field_name_sorted_fields
182 .iter()
183 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_STORAGE))
184 {
185 flags = flags.union(Self::IS_STORAGE);
186 }
187 }
188 TypeKind::MapStorage(key, value, _) => {
189 if key.is_blittable() && value.is_blittable() {
190 flags = flags.union(Self::IS_BLITTABLE);
191 }
192
193 if key.is_storage() && value.is_storage() {
194 flags = flags.union(Self::IS_STORAGE);
195 }
196 }
197 TypeKind::DynamicLengthMapView(_, _) => {
198 flags = flags.union(Self::IS_ALLOWED_RETURN);
199 }
200 TypeKind::FixedCapacityAndLengthArray(inner, _) => {
201 if inner.is_blittable() {
202 flags = flags.union(Self::IS_BLITTABLE);
203 }
204 if inner.is_storage() {
205 flags = flags.union(Self::IS_STORAGE);
206 }
207 }
208 TypeKind::SliceView(_) => {
209 flags = flags.union(Self::IS_ALLOWED_RETURN);
210 }
211 TypeKind::VecStorage(inner, _) => {
212 if inner.is_blittable() {
213 flags = flags.union(Self::IS_BLITTABLE);
214 }
215 if inner.is_storage() {
216 flags = flags.union(Self::IS_STORAGE);
217 }
218 }
219 TypeKind::DynamicLengthVecView(_) => {
220 flags = flags.union(Self::IS_ALLOWED_RETURN);
221 }
222
223 TypeKind::StackStorage(inner, _) => {
224 if inner.is_blittable() {
225 flags = flags.union(Self::IS_BLITTABLE);
226 }
227 if inner.is_storage() {
228 flags = flags.union(Self::IS_STORAGE);
229 }
230 }
231 TypeKind::StackView(_) => {
232 flags = flags.union(Self::IS_ALLOWED_RETURN);
233 }
234
235 TypeKind::QueueStorage(inner, _) => {
236 if inner.is_blittable() {
237 flags = flags.union(Self::IS_BLITTABLE);
238 }
239 if inner.is_storage() {
240 flags = flags.union(Self::IS_STORAGE);
241 }
242 }
243 TypeKind::QueueView(_) => {
244 flags = flags.union(Self::IS_ALLOWED_RETURN);
245 }
246 TypeKind::GridStorage(inner, _, _) => {
247 if inner.is_blittable() {
248 flags = flags.union(Self::IS_BLITTABLE);
249 }
250 if inner.is_storage() {
251 flags = flags.union(Self::IS_STORAGE);
252 }
253 }
254 TypeKind::GridView(_) => {
255 flags = flags.union(Self::IS_ALLOWED_RETURN);
256 }
257 TypeKind::SparseStorage(inner, _) => {
258 if inner.is_blittable() {
259 flags = flags.union(Self::IS_BLITTABLE);
260 }
261 if inner.is_storage() {
262 flags = flags.union(Self::IS_STORAGE);
263 }
264 }
265 TypeKind::SparseView(_) => {
266 flags = flags.union(Self::IS_ALLOWED_RETURN);
267 }
268 TypeKind::Range(_inner) => {
269 flags = flags
270 .union(Self::IS_BLITTABLE)
271 .union(Self::IS_ALLOWED_RETURN);
272 flags = flags.union(Self::IS_STORAGE);
273 }
274 }
275
276 flags
277 }
278}