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