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 pub(crate) field_newtypes: &'static [&'static [u64]],
266
267 pub(crate) newtype_ids: &'static [u64],
271
272 pub(crate) any_offsets: &'static [u32],
276
277 pub(crate) any_discriminant_offset: u32,
279}
280
281impl RawStructSchema {
282 pub const fn new(
284 arena: &'static crate::private::arena::GeneratedCodeArena,
285 nonunion_members: &'static [u16],
286 members_by_discriminant: &'static [u16],
287 members_by_name: &'static [u16],
288 ) -> Self {
289 Self {
290 arena,
291 nonunion_members,
292 members_by_discriminant,
293 members_by_name,
294 field_newtypes: &[],
295 newtype_ids: &[],
296 any_offsets: &[],
297 any_discriminant_offset: 0,
298 }
299 }
300
301 pub const fn with_field_newtypes(mut self, field_newtypes: &'static [&'static [u64]]) -> Self {
303 self.field_newtypes = field_newtypes;
304 self
305 }
306
307 pub const fn with_any_layout(
311 mut self,
312 newtype_ids: &'static [u64],
313 offsets: &'static [u32],
314 discriminant_offset: u32,
315 ) -> Self {
316 self.newtype_ids = newtype_ids;
317 self.any_offsets = offsets;
318 self.any_discriminant_offset = discriminant_offset;
319 self
320 }
321}
322
323#[derive(Copy, Clone)]
327pub struct RawBrandedStructSchema {
328 pub generic: &'static RawStructSchema,
330
331 pub field_types: fn(u16) -> Type,
333
334 pub annotation_types: fn(Option<u16>, u32) -> Type,
337
338 pub type_id: ::core::any::TypeId,
341}
342
343impl ::core::cmp::PartialEq for RawBrandedStructSchema {
344 fn eq(&self, other: &Self) -> bool {
345 self.type_id == other.type_id
346 }
347}
348impl ::core::cmp::Eq for RawBrandedStructSchema {}
349impl ::core::hash::Hash for RawBrandedStructSchema {
350 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
351 self.type_id.hash(state);
352 }
353}
354
355impl core::fmt::Debug for RawBrandedStructSchema {
356 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
357 write!(
358 f,
359 "RawBrandedStructSchema({:?}, {:?})",
360 self.generic as *const _, self.field_types as *const fn(u16) -> Type
361 )
362 }
363}
364
365impl From<StructSchema> for RawBrandedStructSchema {
366 fn from(value: StructSchema) -> Self {
367 value.raw
368 }
369}
370
371#[derive(Clone, Copy)]
377pub struct RawEnumSchema {
378 pub(crate) arena: &'static crate::private::arena::GeneratedCodeArena,
380
381 pub(crate) annotation_types: fn(Option<u16>, u32) -> Type,
384}
385
386impl core::cmp::PartialEq for RawEnumSchema {
387 fn eq(&self, other: &Self) -> bool {
388 ::core::ptr::eq(self.arena, other.arena)
389 }
390}
391
392impl core::cmp::Eq for RawEnumSchema {}
393impl core::hash::Hash for RawEnumSchema {
394 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
395 (self.arena as *const crate::private::arena::GeneratedCodeArena).hash(state);
396 }
397}
398
399impl core::fmt::Debug for RawEnumSchema {
400 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
401 write!(f, "RawEnumSchema({:?})", self.arena as *const _)
402 }
403}
404
405impl RawEnumSchema {
406 pub const fn new(
408 arena: &'static crate::private::arena::GeneratedCodeArena,
409 annotation_types: fn(Option<u16>, u32) -> Type,
410 ) -> Self {
411 Self {
412 arena,
413 annotation_types,
414 }
415 }
416}
417
418impl From<EnumSchema> for RawEnumSchema {
419 fn from(value: EnumSchema) -> Self {
420 value.raw
421 }
422}
423
424pub fn panic_invalid_field_index(index: u16) -> ! {
431 panic!("invalid field index {index}")
432}
433
434pub fn panic_invalid_annotation_indices(child_index: Option<u16>, index: u32) -> ! {
441 panic!("invalid annotation indices ({child_index:?}, {index})")
442}