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::Int => {
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::Float => {
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_SCALAR)
68 .union(Self::IS_ALLOWED_RETURN); }
70 TypeKind::Bool => {
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::Unit => {
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::Function(_) => {}
85 TypeKind::Enum(enum_type) => {
86 if enum_type.are_all_variants_with_blittable_payload() {
87 flags = flags
88 .union(Self::IS_BLITTABLE)
89 .union(Self::IS_ALLOWED_RETURN);
90 } else {
91 panic!("enums should be blittable")
92 }
93 if enum_type.are_all_variants_with_storage_payload() {
94 flags = flags.union(Self::IS_STORAGE);
95 }
96 }
97 TypeKind::Tuple(types) => {
98 if types.iter().all(|t| t.flags.contains(Self::IS_BLITTABLE)) {
100 flags = flags
101 .union(Self::IS_BLITTABLE)
102 .union(Self::IS_ALLOWED_RETURN);
103 }
104 if types.iter().all(|t| t.flags.contains(Self::IS_STORAGE)) {
105 flags = flags.union(Self::IS_STORAGE);
106 }
107 }
108 TypeKind::Optional(inner) => {
109 if inner.flags.contains(Self::IS_BLITTABLE) {
111 flags = flags
112 .union(Self::IS_BLITTABLE)
113 .union(Self::IS_ALLOWED_RETURN);
114 }
115 if inner.flags.contains(Self::IS_STORAGE) {
116 flags = flags.union(Self::IS_STORAGE);
117 }
118 }
119 TypeKind::NamedStruct(named) => {
120 if named.anon_struct_type.flags.contains(Self::IS_BLITTABLE) {
121 flags = flags
122 .union(Self::IS_BLITTABLE)
123 .union(Self::IS_ALLOWED_RETURN);
124 }
125 if named.anon_struct_type.flags.contains(Self::IS_STORAGE) {
126 flags = flags.union(Self::IS_STORAGE);
127 }
128 }
129 TypeKind::AnonymousStruct(anon) => {
130 if anon.field_name_sorted_fields.iter().all(|(_name, field)| {
131 assert!(
132 field.field_type.is_blittable(),
133 "what is wrong with field: {field}"
134 );
135 field.field_type.flags.contains(Self::IS_BLITTABLE)
136 }) {
137 flags = flags
138 .union(Self::IS_BLITTABLE)
139 .union(Self::IS_ALLOWED_RETURN);
140 }
141
142 if anon
143 .field_name_sorted_fields
144 .iter()
145 .all(|(name, field)| field.field_type.flags.contains(Self::IS_STORAGE))
146 {
147 flags = flags.union(Self::IS_STORAGE);
148 }
149 }
150 TypeKind::MapStorage(key, value, _) => {
151 if key.is_blittable() && value.is_blittable() {
152 flags = flags.union(Self::IS_BLITTABLE);
153 }
154
155 if key.is_storage() && value.is_storage() {
156 flags = flags.union(Self::IS_STORAGE);
157 }
158 }
159 TypeKind::DynamicLengthMapView(_, _) => {
160 flags = flags.union(Self::IS_ALLOWED_RETURN);
161 }
162 TypeKind::FixedCapacityAndLengthArray(inner, _) => {
163 if inner.is_blittable() {
164 flags = flags.union(Self::IS_BLITTABLE);
165 }
166 if inner.is_storage() {
167 flags = flags.union(Self::IS_STORAGE);
168 }
169 }
170 TypeKind::SliceView(_) => {
171 flags = flags.union(Self::IS_ALLOWED_RETURN);
172 }
173 TypeKind::VecStorage(inner, _) => {
174 if inner.is_blittable() {
175 flags = flags.union(Self::IS_BLITTABLE);
176 }
177 if inner.is_storage() {
178 flags = flags.union(Self::IS_STORAGE);
179 }
180 }
181 TypeKind::DynamicLengthVecView(_) => {
182 flags = flags.union(Self::IS_ALLOWED_RETURN);
183 }
184
185 TypeKind::StackStorage(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::StackView(_) => {
194 flags = flags.union(Self::IS_ALLOWED_RETURN);
195 }
196
197 TypeKind::QueueStorage(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::QueueView(_) => {
206 flags = flags.union(Self::IS_ALLOWED_RETURN);
207 }
208 TypeKind::GridStorage(inner, _, _) => {
209 if inner.is_blittable() {
210 flags = flags.union(Self::IS_BLITTABLE);
211 }
212 if inner.is_storage() {
213 flags = flags.union(Self::IS_STORAGE);
214 }
215 }
216 TypeKind::GridView(_) => {
217 flags = flags.union(Self::IS_ALLOWED_RETURN);
218 }
219 TypeKind::SparseStorage(inner, _) => {
220 if inner.is_blittable() {
221 flags = flags.union(Self::IS_BLITTABLE);
222 }
223 if inner.is_storage() {
224 flags = flags.union(Self::IS_STORAGE);
225 }
226 }
227 TypeKind::SparseView(_) => {
228 flags = flags.union(Self::IS_ALLOWED_RETURN);
229 }
230 TypeKind::Range(inner) => {
231 flags = flags
232 .union(Self::IS_BLITTABLE)
233 .union(Self::IS_ALLOWED_RETURN);
234 flags = flags.union(Self::IS_STORAGE);
235 }
236
237 _ => {}
238 }
239
240 flags
241 }
242}