1use crate::private::layout::ElementSize;
4use crate::schema::{EnumSchema, StructSchema};
5
6pub trait Introspect {
9 fn introspect() -> Type;
11}
12
13#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
18pub struct Type {
19 base: BaseType,
21
22 list_count: usize,
24}
25
26impl Type {
27 fn new_base(base: BaseType) -> Self {
29 Self {
30 base,
31 list_count: 0,
32 }
33 }
34
35 pub fn list_of(mut element_type: Type) -> Self {
37 element_type.list_count += 1;
38 element_type
39 }
40
41 pub fn which(&self) -> TypeVariant {
43 if self.list_count > 0 {
44 TypeVariant::List(Type {
45 base: self.base,
46 list_count: self.list_count - 1,
47 })
48 } else {
49 match self.base {
50 BaseType::Void => TypeVariant::Void,
51 BaseType::Bool => TypeVariant::Bool,
52 BaseType::Int8 => TypeVariant::Int8,
53 BaseType::Int16 => TypeVariant::Int16,
54 BaseType::Int32 => TypeVariant::Int32,
55 BaseType::Int64 => TypeVariant::Int64,
56 BaseType::UInt8 => TypeVariant::UInt8,
57 BaseType::UInt16 => TypeVariant::UInt16,
58 BaseType::UInt32 => TypeVariant::UInt32,
59 BaseType::UInt64 => TypeVariant::UInt64,
60 BaseType::Float32 => TypeVariant::Float32,
61 BaseType::Float64 => TypeVariant::Float64,
62 BaseType::Text => TypeVariant::Text,
63 BaseType::Data => TypeVariant::Data,
64 BaseType::Enum(re) => TypeVariant::Enum(re),
65 BaseType::Struct(rs) => TypeVariant::Struct(rs),
66 BaseType::AnyPointer => TypeVariant::AnyPointer,
67 BaseType::Capability => TypeVariant::Capability,
68 }
69 }
70 }
71
72 pub(crate) fn expected_element_size(&self) -> ElementSize {
75 if self.list_count > 0 {
76 ElementSize::Pointer
77 } else {
78 match self.base {
79 BaseType::Void => ElementSize::Void,
80 BaseType::Bool => ElementSize::Bit,
81 BaseType::Int8 | BaseType::UInt8 => ElementSize::Byte,
82 BaseType::Int16 | BaseType::UInt16 | BaseType::Enum(_) => ElementSize::TwoBytes,
83 BaseType::Int32 | BaseType::UInt32 | BaseType::Float32 => ElementSize::FourBytes,
84 BaseType::Int64 | BaseType::UInt64 | BaseType::Float64 => ElementSize::EightBytes,
85 BaseType::Text | BaseType::Data | BaseType::AnyPointer | BaseType::Capability => {
86 ElementSize::Pointer
87 }
88 BaseType::Struct(_) => ElementSize::InlineComposite,
89 }
90 }
91 }
92
93 pub fn is_pointer_type(&self) -> bool {
95 if self.list_count > 0 {
96 true
97 } else {
98 matches!(
99 self.base,
100 BaseType::Text
101 | BaseType::Data
102 | BaseType::AnyPointer
103 | BaseType::Struct(_)
104 | BaseType::Capability
105 )
106 }
107 }
108
109 #[deprecated(
112 since = "0.27.0",
113 note = "Type now implements Eq. loose_equals ignores generics on structs, while Eq is more precise and most likely the one you want."
114 )]
115 pub fn loose_equals(&self, other: Self) -> bool {
116 match (self.which(), other.which()) {
117 (TypeVariant::Void, TypeVariant::Void) => true,
118 (TypeVariant::Bool, TypeVariant::Bool) => true,
119 (TypeVariant::UInt8, TypeVariant::UInt8) => true,
120 (TypeVariant::UInt16, TypeVariant::UInt16) => true,
121 (TypeVariant::UInt32, TypeVariant::UInt32) => true,
122 (TypeVariant::UInt64, TypeVariant::UInt64) => true,
123 (TypeVariant::Int8, TypeVariant::Int8) => true,
124 (TypeVariant::Int16, TypeVariant::Int16) => true,
125 (TypeVariant::Int32, TypeVariant::Int32) => true,
126 (TypeVariant::Int64, TypeVariant::Int64) => true,
127 (TypeVariant::Float32, TypeVariant::Float32) => true,
128 (TypeVariant::Float64, TypeVariant::Float64) => true,
129 (TypeVariant::Text, TypeVariant::Text) => true,
130 (TypeVariant::Data, TypeVariant::Data) => true,
131 (TypeVariant::Enum(es1), TypeVariant::Enum(es2)) => es1 == es2,
132 (TypeVariant::Struct(rbs1), TypeVariant::Struct(rbs2)) => {
133 core::ptr::eq(rbs1.generic, rbs2.generic)
140 }
141 (TypeVariant::List(element1), TypeVariant::List(element2)) => {
142 element1.loose_equals(element2)
143 }
144 (TypeVariant::AnyPointer, TypeVariant::AnyPointer) => true,
145 (TypeVariant::Capability, TypeVariant::Capability) => true,
146 _ => false,
147 }
148 }
149}
150
151#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
152pub enum TypeVariant {
155 Void,
156 Bool,
157 Int8,
158 Int16,
159 Int32,
160 Int64,
161 UInt8,
162 UInt16,
163 UInt32,
164 UInt64,
165 Float32,
166 Float64,
167 Text,
168 Data,
169 Struct(RawBrandedStructSchema),
170 AnyPointer,
171 Capability,
172 Enum(RawEnumSchema),
173 List(Type),
174}
175
176impl From<TypeVariant> for Type {
177 fn from(tv: TypeVariant) -> Type {
178 match tv {
179 TypeVariant::Void => Type::new_base(BaseType::Void),
180 TypeVariant::Bool => Type::new_base(BaseType::Bool),
181 TypeVariant::Int8 => Type::new_base(BaseType::Int8),
182 TypeVariant::Int16 => Type::new_base(BaseType::Int16),
183 TypeVariant::Int32 => Type::new_base(BaseType::Int32),
184 TypeVariant::Int64 => Type::new_base(BaseType::Int64),
185 TypeVariant::UInt8 => Type::new_base(BaseType::UInt8),
186 TypeVariant::UInt16 => Type::new_base(BaseType::UInt16),
187 TypeVariant::UInt32 => Type::new_base(BaseType::UInt32),
188 TypeVariant::UInt64 => Type::new_base(BaseType::UInt64),
189 TypeVariant::Float32 => Type::new_base(BaseType::Float32),
190 TypeVariant::Float64 => Type::new_base(BaseType::Float64),
191 TypeVariant::Text => Type::new_base(BaseType::Text),
192 TypeVariant::Data => Type::new_base(BaseType::Data),
193 TypeVariant::Struct(rbs) => Type::new_base(BaseType::Struct(rbs)),
194 TypeVariant::AnyPointer => Type::new_base(BaseType::AnyPointer),
195 TypeVariant::Capability => Type::new_base(BaseType::Capability),
196 TypeVariant::Enum(es) => Type::new_base(BaseType::Enum(es)),
197 TypeVariant::List(list) => Type::list_of(list),
198 }
199 }
200}
201
202#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
204enum BaseType {
205 Void,
206 Bool,
207 Int8,
208 Int16,
209 Int32,
210 Int64,
211 UInt8,
212 UInt16,
213 UInt32,
214 UInt64,
215 Float32,
216 Float64,
217 Text,
218 Data,
219 Struct(RawBrandedStructSchema),
220 AnyPointer,
221 Capability,
222 Enum(RawEnumSchema),
223}
224
225macro_rules! primitive_introspect(
226 ($t:ty, $v:ident) => (
227 impl Introspect for $t {
228 fn introspect() -> Type { Type::new_base(BaseType::$v) }
229 }
230 )
231);
232
233primitive_introspect!((), Void);
234primitive_introspect!(bool, Bool);
235primitive_introspect!(i8, Int8);
236primitive_introspect!(i16, Int16);
237primitive_introspect!(i32, Int32);
238primitive_introspect!(i64, Int64);
239primitive_introspect!(u8, UInt8);
240primitive_introspect!(u16, UInt16);
241primitive_introspect!(u32, UInt32);
242primitive_introspect!(u64, UInt64);
243primitive_introspect!(f32, Float32);
244primitive_introspect!(f64, Float64);
245
246#[derive(Copy, Clone)]
249pub struct RawStructSchema {
250 pub(crate) arena: &'static crate::private::arena::GeneratedCodeArena,
252
253 pub(crate) nonunion_members: &'static [u16],
255
256 pub(crate) members_by_discriminant: &'static [u16],
258
259 pub(crate) members_by_name: &'static [u16],
261}
262
263impl RawStructSchema {
264 pub const fn new(
266 arena: &'static crate::private::arena::GeneratedCodeArena,
267 nonunion_members: &'static [u16],
268 members_by_discriminant: &'static [u16],
269 members_by_name: &'static [u16],
270 ) -> Self {
271 Self {
272 arena,
273 nonunion_members,
274 members_by_discriminant,
275 members_by_name,
276 }
277 }
278}
279
280#[derive(Copy, Clone)]
284pub struct RawBrandedStructSchema {
285 pub generic: &'static RawStructSchema,
287
288 pub field_types: fn(u16) -> Type,
290
291 pub annotation_types: fn(Option<u16>, u32) -> Type,
294
295 pub type_id: ::core::any::TypeId,
298}
299
300impl ::core::cmp::PartialEq for RawBrandedStructSchema {
301 fn eq(&self, other: &Self) -> bool {
302 self.type_id == other.type_id
303 }
304}
305impl ::core::cmp::Eq for RawBrandedStructSchema {}
306impl ::core::hash::Hash for RawBrandedStructSchema {
307 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
308 self.type_id.hash(state);
309 }
310}
311
312impl core::fmt::Debug for RawBrandedStructSchema {
313 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
314 write!(
315 f,
316 "RawBrandedStructSchema({:?}, {:?})",
317 self.generic as *const _, self.field_types as *const fn(u16) -> Type
318 )
319 }
320}
321
322impl From<StructSchema> for RawBrandedStructSchema {
323 fn from(value: StructSchema) -> Self {
324 value.raw
325 }
326}
327
328#[derive(Clone, Copy)]
334pub struct RawEnumSchema {
335 pub(crate) arena: &'static crate::private::arena::GeneratedCodeArena,
337
338 pub(crate) annotation_types: fn(Option<u16>, u32) -> Type,
341}
342
343impl core::cmp::PartialEq for RawEnumSchema {
344 fn eq(&self, other: &Self) -> bool {
345 ::core::ptr::eq(self.arena, other.arena)
346 }
347}
348
349impl core::cmp::Eq for RawEnumSchema {}
350impl core::hash::Hash for RawEnumSchema {
351 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
352 (self.arena as *const crate::private::arena::GeneratedCodeArena).hash(state);
353 }
354}
355
356impl core::fmt::Debug for RawEnumSchema {
357 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
358 write!(f, "RawEnumSchema({:?})", self.arena as *const _)
359 }
360}
361
362impl RawEnumSchema {
363 pub const fn new(
365 arena: &'static crate::private::arena::GeneratedCodeArena,
366 annotation_types: fn(Option<u16>, u32) -> Type,
367 ) -> Self {
368 Self {
369 arena,
370 annotation_types,
371 }
372 }
373}
374
375impl From<EnumSchema> for RawEnumSchema {
376 fn from(value: EnumSchema) -> Self {
377 value.raw
378 }
379}
380
381pub fn panic_invalid_field_index(index: u16) -> ! {
388 panic!("invalid field index {index}")
389}
390
391pub fn panic_invalid_annotation_indices(child_index: Option<u16>, index: u32) -> ! {
398 panic!("invalid annotation indices ({child_index:?}, {index})")
399}