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::Byte => {
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::Int => {
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::String => {
65 flags = flags
66 .union(Self::IS_BLITTABLE)
67 .union(Self::IS_ALLOWED_RETURN)
68 .union(Self::IS_SCALAR);
69 }
70 TypeKind::StringStorage(_, _) => {
71 flags = flags
72 .union(Self::IS_BLITTABLE)
73 .union(Self::IS_STORAGE)
74 .union(Self::IS_SCALAR);
75 }
76
77 TypeKind::Float => {
78 flags = flags
79 .union(Self::IS_BLITTABLE)
80 .union(Self::IS_STORAGE)
81 .union(Self::IS_ALLOWED_RETURN)
82 .union(Self::IS_SCALAR);
83 }
84 TypeKind::Bool => {
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::Unit => {
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::Function(_) => {}
99 TypeKind::Enum(enum_type) => {
100 if enum_type.are_all_variants_with_blittable_payload() {
101 flags = flags
102 .union(Self::IS_BLITTABLE)
103 .union(Self::IS_ALLOWED_RETURN);
104 } else {
105 panic!("enums should be blittable")
106 }
107 if enum_type.are_all_variants_with_storage_payload() {
108 flags = flags.union(Self::IS_STORAGE);
109 }
110 }
111 TypeKind::Tuple(types) => {
112 if types.iter().all(|t| t.flags.contains(Self::IS_BLITTABLE)) {
114 flags = flags
115 .union(Self::IS_BLITTABLE)
116 .union(Self::IS_ALLOWED_RETURN);
117 }
118 if types.iter().all(|t| t.flags.contains(Self::IS_STORAGE)) {
119 flags = flags.union(Self::IS_STORAGE);
120 }
121 }
122 TypeKind::Optional(inner) => {
123 if inner.flags.contains(Self::IS_BLITTABLE) {
125 flags = flags
126 .union(Self::IS_BLITTABLE)
127 .union(Self::IS_ALLOWED_RETURN);
128 }
129 if inner.flags.contains(Self::IS_STORAGE) {
130 flags = flags.union(Self::IS_STORAGE);
131 }
132 }
133 TypeKind::NamedStruct(named) => {
134 if named.anon_struct_type.flags.contains(Self::IS_BLITTABLE) {
135 flags = flags
136 .union(Self::IS_BLITTABLE)
137 .union(Self::IS_ALLOWED_RETURN);
138 }
139 if named.anon_struct_type.flags.contains(Self::IS_STORAGE) {
140 flags = flags.union(Self::IS_STORAGE);
141 }
142 }
143 TypeKind::AnonymousStruct(anon) => {
144 if anon
145 .field_name_sorted_fields
146 .iter()
147 .all(|(name, field)| field.field_type.flags.contains(Self::IS_BLITTABLE))
148 {
149 flags = flags
150 .union(Self::IS_BLITTABLE)
151 .union(Self::IS_ALLOWED_RETURN);
152 }
153
154 if anon
155 .field_name_sorted_fields
156 .iter()
157 .all(|(name, field)| field.field_type.flags.contains(Self::IS_STORAGE))
158 {
159 flags = flags.union(Self::IS_STORAGE);
160 }
161 }
162 TypeKind::MapStorage(key, value, _) => {
163 if key.is_blittable() && value.is_blittable() {
164 flags = flags.union(Self::IS_BLITTABLE);
165 }
166
167 if key.is_storage() && value.is_storage() {
168 flags = flags.union(Self::IS_STORAGE);
169 }
170 }
171 TypeKind::DynamicLengthMapView(_, _) => {
172 flags = flags.union(Self::IS_ALLOWED_RETURN);
173 }
174 TypeKind::FixedCapacityAndLengthArray(inner, _) => {
175 if inner.is_blittable() {
176 flags = flags.union(Self::IS_BLITTABLE);
177 }
178 if inner.is_storage() {
179 flags = flags.union(Self::IS_STORAGE);
180 }
181 }
182 TypeKind::SliceView(_) => {
183 flags = flags.union(Self::IS_ALLOWED_RETURN);
184 }
185 TypeKind::VecStorage(inner, _) => {
186 if inner.is_blittable() {
187 flags = flags.union(Self::IS_BLITTABLE);
188 }
189 if inner.is_storage() {
190 flags = flags.union(Self::IS_STORAGE);
191 }
192 }
193 TypeKind::DynamicLengthVecView(_) => {
194 flags = flags.union(Self::IS_ALLOWED_RETURN);
195 }
196
197 TypeKind::StackStorage(inner, _) => {
198 if inner.is_blittable() {
199 flags = flags.union(Self::IS_BLITTABLE);
200 }
201 if inner.is_storage() {
202 flags = flags.union(Self::IS_STORAGE);
203 }
204 }
205 TypeKind::StackView(_) => {
206 flags = flags.union(Self::IS_ALLOWED_RETURN);
207 }
208
209 TypeKind::QueueStorage(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::QueueView(_) => {
218 flags = flags.union(Self::IS_ALLOWED_RETURN);
219 }
220 TypeKind::GridStorage(inner, _, _) => {
221 if inner.is_blittable() {
222 flags = flags.union(Self::IS_BLITTABLE);
223 }
224 if inner.is_storage() {
225 flags = flags.union(Self::IS_STORAGE);
226 }
227 }
228 TypeKind::GridView(_) => {
229 flags = flags.union(Self::IS_ALLOWED_RETURN);
230 }
231 TypeKind::SparseStorage(inner, _) => {
232 if inner.is_blittable() {
233 flags = flags.union(Self::IS_BLITTABLE);
234 }
235 if inner.is_storage() {
236 flags = flags.union(Self::IS_STORAGE);
237 }
238 }
239 TypeKind::SparseView(_) => {
240 flags = flags.union(Self::IS_ALLOWED_RETURN);
241 }
242 TypeKind::Range(inner) => {
243 flags = flags
244 .union(Self::IS_BLITTABLE)
245 .union(Self::IS_ALLOWED_RETURN);
246 flags = flags.union(Self::IS_STORAGE);
247 }
248
249 _ => {}
250 }
251
252 flags
253 }
254}