1use std::{mem::size_of, sync::Arc};
4
5use itertools::Itertools;
6use salsa::Update;
7
8impl Location for () {}
9
10impl<L: Location> Layout<L> {
11 pub fn display_name(&self) -> String {
12 match &self {
13 Layout::Primitive(primitive_def) => match primitive_def {
14 PrimitiveLayout::Array(array_def) => format!(
15 "[{}; {}]",
16 array_def.element_type.display_name(),
17 array_def.length
18 ),
19 PrimitiveLayout::Bool(_) => "bool".to_string(),
20 PrimitiveLayout::Char(_) => "char".to_string(),
21 PrimitiveLayout::Float(float_def) => {
22 format!("f{}", float_def.size * 8)
23 }
24 PrimitiveLayout::Function(function_def) => function_def.display_name(),
25 PrimitiveLayout::Int(int_def) => int_def.display_name(),
26 PrimitiveLayout::Never(_) => "!".to_string(),
27 PrimitiveLayout::Pointer(pointer_def) => {
28 format!("*{}", pointer_def.pointed_type.display_name())
29 }
30 PrimitiveLayout::Reference(reference_def) => {
31 let mut_ref = if reference_def.mutable { "mut " } else { "" };
32 format!("&{}{}", mut_ref, reference_def.pointed_type.display_name())
33 }
34 PrimitiveLayout::Slice(slice_def) => {
35 format!("&[{}]", slice_def.element_type.display_name())
36 }
37 PrimitiveLayout::Str(_) => "str".to_string(),
38 PrimitiveLayout::StrSlice(_) => "&str".to_string(),
39 PrimitiveLayout::Tuple(tuple_def) => {
40 let elements = tuple_def
41 .elements
42 .iter()
43 .map(|(_, element)| element.display_name())
44 .join(", ");
45 format!("({elements})")
46 }
47 PrimitiveLayout::Unit(_) => "()".to_string(),
48 PrimitiveLayout::UnsignedInt(unsigned_int_def) => unsigned_int_def.display_name(),
49 },
50 Layout::Std(std_def) => match std_def {
51 StdLayout::SmartPtr(smart_ptr_def) => {
52 let inner = smart_ptr_def.inner_type.display_name();
53 match smart_ptr_def.variant {
54 SmartPtrVariant::Box => format!("Box<{inner}>"),
55 _ => format!("{:?}<{}>", smart_ptr_def.variant, inner),
56 }
57 }
58 StdLayout::Map(map_def) => map_def.display_name(),
59 StdLayout::Option(option_def) => {
60 let inner_type = option_def.some_type.display_name();
61 format!("Option<{inner_type}>")
62 }
63 StdLayout::Result(result_def) => {
64 let ok_type = result_def.ok_type.display_name();
65 let err_type = result_def.err_type.display_name();
66 format!("Result<{ok_type}, {err_type}>")
67 }
68 StdLayout::String(_) => "String".to_string(),
69 StdLayout::Vec(vec_def) => {
70 let inner_type = vec_def.inner_type.display_name();
71 format!("Vec<{inner_type}>")
72 }
73 },
74 Layout::Struct(struct_def) => struct_def.name.clone(),
75 Layout::Enum(enum_def) => enum_def.name.clone(),
76 Layout::CEnum(c_enum_def) => c_enum_def.name.clone(),
77 Layout::Alias { name } => name.to_string(),
78 }
79 }
80
81 pub fn size(&self) -> Option<usize> {
82 match &self {
83 Layout::Primitive(primitive_def) => primitive_def.size(),
84 Layout::Std(std_def) => std_def.size(),
85 Layout::Struct(struct_def) => Some(struct_def.size),
86 Layout::Enum(enum_def) => Some(enum_def.size),
87 Layout::CEnum(c_enum_def) => Some(c_enum_def.size),
88 Layout::Alias { name: _ } => None,
89 }
90 }
91
92 pub fn matching_type(&self, other: &Layout<L>) -> bool {
93 match (self, other) {
94 (Layout::Primitive(p1), Layout::Primitive(p2)) => p1.matching_type(p2),
95 (Layout::Std(s1), Layout::Std(s2)) => s1.matching_type(s2),
96 (Layout::Struct(s1), Layout::Struct(s2)) => s1.name == s2.name,
97 (Layout::Struct(s1), Layout::Alias { name }) => &s1.name == name,
98 (Layout::Alias { name: left }, Layout::Alias { name: right }) => left == right,
99 (Layout::Alias { name }, x) | (x, Layout::Alias { name }) => name == &x.display_name(),
100 (Layout::Enum(e1), Layout::Enum(e2)) => e1.name == e2.name,
101 (Layout::CEnum(e1), Layout::CEnum(e2)) => e1.name == e2.name,
102 _ => false,
103 }
104 }
105
106 pub fn as_reference(&self, location: L) -> Layout<L>
107 where
108 Self: Clone,
109 {
110 Layout::Primitive(PrimitiveLayout::Reference(ReferenceLayout {
111 mutable: false,
112 pointed_type: TypeDefinition::new(location, self.clone()),
113 }))
114 }
115
116 pub fn dereferenced(&self) -> &Layout<L> {
117 match self {
118 Layout::Primitive(PrimitiveLayout::Pointer(pointer_def)) => {
119 pointer_def.pointed_type.layout.dereferenced()
120 }
121 Layout::Primitive(PrimitiveLayout::Reference(reference_def)) => {
122 reference_def.pointed_type.layout.dereferenced()
123 }
124 _ => {
125 self
127 }
128 }
129 }
130}
131
132impl<L: Location> From<PrimitiveLayout<L>> for Layout<L> {
134 fn from(primitive: PrimitiveLayout<L>) -> Self {
135 Layout::Primitive(primitive)
136 }
137}
138
139impl<L: Location> From<StdLayout<L>> for Layout<L> {
140 fn from(std_def: StdLayout<L>) -> Self {
141 Layout::Std(std_def)
142 }
143}
144
145impl<L: Location> From<StructLayout<L>> for Layout<L> {
146 fn from(struct_def: StructLayout<L>) -> Self {
147 Layout::Struct(struct_def)
148 }
149}
150
151impl<L: Location> From<EnumLayout<L>> for Layout<L> {
152 fn from(enum_def: EnumLayout<L>) -> Self {
153 Layout::Enum(enum_def)
154 }
155}
156
157impl<L: Location> From<ArrayLayout<L>> for PrimitiveLayout<L> {
159 fn from(array: ArrayLayout<L>) -> Self {
160 PrimitiveLayout::Array(array)
161 }
162}
163
164impl<L: Location> From<FloatLayout> for PrimitiveLayout<L> {
165 fn from(float: FloatLayout) -> Self {
166 PrimitiveLayout::Float(float)
167 }
168}
169
170impl<L: Location> From<FunctionLayout<L>> for PrimitiveLayout<L> {
171 fn from(function: FunctionLayout<L>) -> Self {
172 PrimitiveLayout::Function(function)
173 }
174}
175
176impl<L: Location> From<IntLayout> for PrimitiveLayout<L> {
177 fn from(int: IntLayout) -> Self {
178 PrimitiveLayout::Int(int)
179 }
180}
181
182impl<L: Location> From<PointerLayout<L>> for PrimitiveLayout<L> {
183 fn from(pointer: PointerLayout<L>) -> Self {
184 PrimitiveLayout::Pointer(pointer)
185 }
186}
187
188impl<L: Location> From<ReferenceLayout<L>> for PrimitiveLayout<L> {
189 fn from(reference: ReferenceLayout<L>) -> Self {
190 PrimitiveLayout::Reference(reference)
191 }
192}
193
194impl<L: Location> From<SliceLayout<L>> for PrimitiveLayout<L> {
195 fn from(slice: SliceLayout<L>) -> Self {
196 PrimitiveLayout::Slice(slice)
197 }
198}
199
200impl<L: Location> From<StrSliceLayout> for PrimitiveLayout<L> {
201 fn from(str_slice: StrSliceLayout) -> Self {
202 PrimitiveLayout::StrSlice(str_slice)
203 }
204}
205
206impl<L: Location> From<TupleLayout<L>> for PrimitiveLayout<L> {
207 fn from(tuple: TupleLayout<L>) -> Self {
208 PrimitiveLayout::Tuple(tuple)
209 }
210}
211
212impl<L: Location> From<UnitLayout> for PrimitiveLayout<L> {
213 fn from(unit: UnitLayout) -> Self {
214 PrimitiveLayout::Unit(unit)
215 }
216}
217
218impl<L: Location> From<UnsignedIntLayout> for PrimitiveLayout<L> {
219 fn from(uint: UnsignedIntLayout) -> Self {
220 PrimitiveLayout::UnsignedInt(uint)
221 }
222}
223
224impl<L: Location> From<SmartPtrLayout<L>> for StdLayout<L> {
226 fn from(smart_ptr: SmartPtrLayout<L>) -> Self {
227 StdLayout::SmartPtr(smart_ptr)
228 }
229}
230
231impl<L: Location> From<MapLayout<L>> for StdLayout<L> {
232 fn from(map: MapLayout<L>) -> Self {
233 StdLayout::Map(map)
234 }
235}
236
237impl<L: Location> From<StringLayout<L>> for StdLayout<L> {
238 fn from(string: StringLayout<L>) -> Self {
239 StdLayout::String(string)
240 }
241}
242
243impl<L: Location> From<VecLayout<L>> for StdLayout<L> {
244 fn from(vec: VecLayout<L>) -> Self {
245 StdLayout::Vec(vec)
246 }
247}
248
249impl<L: Location> From<()> for PrimitiveLayout<L> {
251 fn from(_: ()) -> Self {
252 PrimitiveLayout::Bool(())
253 }
254}
255
256impl<L: Location> From<UnsignedIntLayout> for Layout<L> {
258 fn from(uint: UnsignedIntLayout) -> Self {
259 Layout::Primitive(PrimitiveLayout::UnsignedInt(uint))
260 }
261}
262
263impl<L: Location> From<IntLayout> for Layout<L> {
264 fn from(int: IntLayout) -> Self {
265 Layout::Primitive(PrimitiveLayout::Int(int))
266 }
267}
268
269impl<L: Location> From<FloatLayout> for Layout<L> {
270 fn from(float: FloatLayout) -> Self {
271 Layout::Primitive(PrimitiveLayout::Float(float))
272 }
273}
274
275impl<L: Location> From<ReferenceLayout<L>> for Layout<L> {
276 fn from(reference: ReferenceLayout<L>) -> Self {
277 Layout::Primitive(PrimitiveLayout::Reference(reference))
278 }
279}
280
281impl<L: Location> From<StringLayout<L>> for Layout<L> {
282 fn from(string: StringLayout<L>) -> Self {
283 Layout::Std(StdLayout::String(string))
284 }
285}
286
287impl<L: Location> From<VecLayout<L>> for Layout<L> {
288 fn from(vec: VecLayout<L>) -> Self {
289 Layout::Std(StdLayout::Vec(vec))
290 }
291}
292
293impl<L: Location> From<MapLayout<L>> for Layout<L> {
294 fn from(map: MapLayout<L>) -> Self {
295 Layout::Std(StdLayout::Map(map))
296 }
297}
298
299impl<L: Location> From<SmartPtrLayout<L>> for Layout<L> {
300 fn from(smart_ptr: SmartPtrLayout<L>) -> Self {
301 Layout::Std(StdLayout::SmartPtr(smart_ptr))
302 }
303}
304
305#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
306pub struct TypeDefinition<L = ()>
307where
308 L: Location,
309{
310 pub layout: Arc<Layout<L>>,
315
316 pub location: L,
320}
321
322impl<L> TypeDefinition<L>
323where
324 L: Location,
325{
326 pub fn new(location: L, layout: Layout<L>) -> Self {
327 Self {
328 layout: Arc::new(layout),
329 location,
330 }
331 }
332
333 pub fn display_name(&self) -> String {
334 self.layout.display_name()
335 }
336
337 pub fn size(&self) -> Option<usize> {
338 self.layout.size()
339 }
340
341 pub fn matching_type(&self, other: &Self) -> bool {
342 self.location.matches(&other.location) || self.layout.matching_type(&other.layout)
343 }
344}
345
346pub trait Location: Update {
347 fn matches(&self, _other: &Self) -> bool {
348 false
351 }
352}
353
354#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
355pub enum Layout<L = ()>
356where
357 L: Location,
358{
359 Primitive(PrimitiveLayout<L>),
366
367 Std(StdLayout<L>),
369
370 Struct(StructLayout<L>),
373
374 Enum(EnumLayout<L>),
376
377 CEnum(CEnumLayout),
379
380 Alias { name: String },
382}
383
384#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
386pub enum PrimitiveLayout<L = ()>
387where
388 L: Location,
389{
390 Array(ArrayLayout<L>),
391 Bool(()),
392 Char(()),
393 Float(FloatLayout),
394 Function(FunctionLayout<L>),
395 Int(IntLayout),
396 Never(()),
397 Pointer(PointerLayout<L>),
398 Reference(ReferenceLayout<L>),
399 Slice(SliceLayout<L>),
400 Str(()),
405 StrSlice(StrSliceLayout),
408 Tuple(TupleLayout<L>),
409 Unit(UnitLayout),
410 UnsignedInt(UnsignedIntLayout),
411 }
413
414impl<L: Location> PrimitiveLayout<L> {
415 fn size(&self) -> Option<usize> {
416 let size = match self {
417 PrimitiveLayout::Array(array_def) => {
418 let element_size = array_def.element_type.size()?;
419 element_size * array_def.length
420 }
421 PrimitiveLayout::Bool(_) => {
422 1
424 }
425 PrimitiveLayout::Char(_) => {
426 4
428 }
429 PrimitiveLayout::Float(float_def) => float_def.size,
430 PrimitiveLayout::Function(_)
431 | PrimitiveLayout::Pointer(_)
432 | PrimitiveLayout::Reference(_) => {
433 size_of::<usize>()
435 }
436 PrimitiveLayout::Int(int_def) => {
437 int_def.size
439 }
440 PrimitiveLayout::Never(_) => {
441 0
443 }
444 PrimitiveLayout::Slice(_) => size_of::<&[u8]>(),
445 PrimitiveLayout::Str(_) => unimplemented!(),
446 PrimitiveLayout::StrSlice(_) => size_of::<&str>(),
447 PrimitiveLayout::Tuple(tuple_def) => tuple_def.size,
448 PrimitiveLayout::Unit(_) => 0,
449 PrimitiveLayout::UnsignedInt(unsigned_int_def) => {
450 unsigned_int_def.size
452 }
453 };
454
455 Some(size)
456 }
457
458 fn matching_type(&self, other: &Self) -> bool {
459 use PrimitiveLayout::*;
460 match (self, other) {
461 (Pointer(l), Pointer(r)) => l.pointed_type.matching_type(&r.pointed_type),
462 (Reference(l), Reference(r)) => l.pointed_type.matching_type(&r.pointed_type),
463 (Slice(l), Slice(r)) => l.element_type.matching_type(&r.element_type),
464 (Array(l), Array(r)) => l.element_type.matching_type(&r.element_type),
465 (Tuple(l), Tuple(r)) => {
466 if l.elements.len() != r.elements.len() {
467 return false;
468 }
469 l.elements
470 .iter()
471 .zip(r.elements.iter())
472 .all(|((_, l), (_, r))| l.matching_type(r))
473 }
474
475 (Function(l), Function(r)) => {
476 l.arg_types.len() == r.arg_types.len()
477 && l.return_type.is_none() == r.return_type.is_none()
478 && l.return_type
479 .as_ref()
480 .zip(r.return_type.as_ref())
481 .is_none_or(|(l_ret, r_ret)| l_ret.matching_type(r_ret))
482 && l.arg_types
483 .iter()
484 .zip(r.arg_types.iter())
485 .all(|(l_arg, r_arg)| l_arg.matching_type(r_arg))
486 }
487 (Bool(_), Bool(_))
488 | (Char(_), Char(_))
489 | (Never(_), Never(_))
490 | (Str(_), Str(_))
491 | (Unit(_), Unit(_)) => true,
492 (Float(l), Float(r)) => l == r,
493 (Int(l), Int(r)) => l == r,
494 (UnsignedInt(l), UnsignedInt(r)) => l == r,
495
496 (StrSlice(l), StrSlice(r)) => l == r,
497 _ => false,
498 }
499 }
500}
501
502#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
503pub struct ArrayLayout<L = ()>
504where
505 L: Location,
506{
507 pub element_type: TypeDefinition<L>,
508 pub length: usize,
509}
510
511#[derive(Debug, PartialEq, Eq, Clone, Hash, Update, Copy)]
512pub struct FloatLayout {
513 pub size: usize,
514}
515#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
516pub struct FunctionLayout<L = ()>
517where
518 L: Location,
519{
520 pub return_type: Option<TypeDefinition<L>>,
521 pub arg_types: Vec<TypeDefinition<L>>,
522}
523
524impl<L: Location> FunctionLayout<L> {
525 pub fn display_name(&self) -> String {
526 let arg_types = self
527 .arg_types
528 .iter()
529 .map(|arg| arg.display_name())
530 .collect::<Vec<_>>()
531 .join(", ");
532
533 let mut signature = format!("fn({arg_types})");
534
535 if let Some(l) = self.return_type.as_ref() {
536 signature += &format!(" -> {}", l.display_name());
537 }
538 signature
539 }
540}
541
542#[derive(Debug, PartialEq, Eq, Clone, Hash, Update, Copy)]
543pub struct IntLayout {
544 pub size: usize,
545}
546
547impl IntLayout {
548 pub fn display_name(&self) -> String {
549 format!("i{}", self.size * 8)
550 }
551}
552
553#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
554pub struct PointerLayout<L = ()>
555where
556 L: Location,
557{
558 pub mutable: bool,
559 pub pointed_type: TypeDefinition<L>,
560}
561#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
562pub struct ReferenceLayout<L = ()>
563where
564 L: Location,
565{
566 pub mutable: bool,
569
570 pub pointed_type: TypeDefinition<L>,
571}
572
573#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
574pub struct SliceLayout<L = ()>
575where
576 L: Location,
577{
578 pub element_type: TypeDefinition<L>,
579 pub data_ptr_offset: usize,
580 pub length_offset: usize,
581}
582
583#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
584pub struct StrSliceLayout {
585 pub data_ptr_offset: usize,
586 pub length_offset: usize,
587}
588
589#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
590pub struct TupleLayout<L = ()>
591where
592 L: Location,
593{
594 pub elements: Vec<(usize, TypeDefinition<L>)>,
596 pub size: usize,
597}
598#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
599pub struct UnitLayout;
600
601#[derive(Debug, PartialEq, Eq, Clone, Hash, Update, Copy)]
602pub struct UnsignedIntLayout {
603 pub size: usize,
606}
607
608impl UnsignedIntLayout {
609 pub fn display_name(&self) -> String {
610 format!("u{}", self.size * 8)
611 }
612}
613
614#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
615pub enum StdLayout<L = ()>
616where
617 L: Location,
618{
619 SmartPtr(SmartPtrLayout<L>),
620 Map(MapLayout<L>),
621 Option(OptionLayout<L>),
622 Result(ResultLayout<L>),
623 String(StringLayout<L>),
624 Vec(VecLayout<L>),
625}
626
627impl<L: Location> StdLayout<L> {
628 fn size(&self) -> Option<usize> {
629 let size = match self {
630 StdLayout::SmartPtr(smart_ptr_def) => match smart_ptr_def.variant {
631 SmartPtrVariant::Box => size_of::<Box<()>>(),
632 SmartPtrVariant::Rc => size_of::<std::rc::Rc<()>>(),
633 SmartPtrVariant::Arc => size_of::<std::sync::Arc<()>>(),
634 SmartPtrVariant::RefCell => size_of::<std::cell::RefCell<()>>(),
635 SmartPtrVariant::Mutex => size_of::<std::sync::Mutex<()>>(),
636 SmartPtrVariant::RwLock => size_of::<std::sync::RwLock<()>>(),
637 SmartPtrVariant::Cell => size_of::<std::cell::Cell<()>>(),
638 SmartPtrVariant::UnsafeCell => size_of::<std::cell::UnsafeCell<()>>(),
639 },
640 StdLayout::Map(map_def) => match map_def.variant {
641 MapVariant::HashMap { .. } => size_of::<std::collections::HashMap<(), ()>>(),
642 MapVariant::BTreeMap { .. } => size_of::<std::collections::BTreeMap<(), ()>>(),
643 MapVariant::IndexMap => unimplemented!(),
644 },
645 StdLayout::Option(def) => def.size,
646 StdLayout::Result(def) => def.size,
647 StdLayout::String(_) | StdLayout::Vec(_) => size_of::<Vec<()>>(),
648 };
649
650 Some(size)
651 }
652
653 fn matching_type(&self, other: &Self) -> bool {
654 match (self, other) {
655 (StdLayout::SmartPtr(l), StdLayout::SmartPtr(r)) => {
656 l.variant == r.variant && l.inner_type.matching_type(&r.inner_type)
657 }
658 (StdLayout::Map(l), StdLayout::Map(r)) => {
659 l.variant == r.variant
660 && l.key_type.matching_type(&r.key_type)
661 && l.value_type.matching_type(&r.value_type)
662 }
663 (StdLayout::Option(l), StdLayout::Option(r)) => l.some_type.matching_type(&r.some_type),
664 (StdLayout::Result(l), StdLayout::Result(r)) => {
665 l.ok_type.matching_type(&r.ok_type) && l.err_type.matching_type(&r.err_type)
666 }
667 (StdLayout::String(_), StdLayout::String(_)) => true,
668 (StdLayout::Vec(l), StdLayout::Vec(r)) => l.inner_type.matching_type(&r.inner_type),
669 _ => false,
670 }
671 }
672}
673
674#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
675pub struct SmartPtrLayout<L = ()>
676where
677 L: Location,
678{
679 pub inner_type: TypeDefinition<L>,
680 pub inner_ptr_offset: usize,
681 pub data_ptr_offset: usize,
682 pub variant: SmartPtrVariant,
683}
684
685#[derive(Debug, PartialEq, Eq, Clone, Hash, Update, Copy)]
686pub enum SmartPtrVariant {
687 Box,
688 Rc,
689 Arc,
690 RefCell,
691 Mutex,
692 RwLock,
693 Cell,
694 UnsafeCell,
695}
696
697impl SmartPtrVariant {
698 pub fn name(&self) -> &'static str {
699 match self {
700 SmartPtrVariant::Box => "Box",
701 SmartPtrVariant::Rc => "Rc",
702 SmartPtrVariant::Arc => "Arc",
703 SmartPtrVariant::RefCell => "RefCell",
704 SmartPtrVariant::Mutex => "Mutex",
705 SmartPtrVariant::RwLock => "RwLock",
706 SmartPtrVariant::Cell => "Cell",
707 SmartPtrVariant::UnsafeCell => "UnsafeCell",
708 }
709 }
710}
711
712#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
713pub struct MapLayout<L = ()>
714where
715 L: Location,
716{
717 pub key_type: TypeDefinition<L>,
718 pub value_type: TypeDefinition<L>,
719 pub variant: MapVariant,
720}
721
722impl<L: Location> MapLayout<L> {
723 pub fn display_name(&self) -> String {
724 format!(
725 "{}<{}, {}>",
726 self.variant.name(),
727 self.key_type.display_name(),
728 self.value_type.display_name()
729 )
730 }
731}
732
733#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
734pub struct BTreeRootLayout {
735 pub node_offset: usize, pub height_offset: usize, }
738
739#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
740pub struct BTreeNodeLayout {
741 pub keys_offset: usize, pub vals_offset: usize, pub len_offset: usize, pub edges_offset: usize, }
746
747#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
748pub enum MapVariant {
749 HashMap {
750 bucket_mask_offset: usize, ctrl_offset: usize, items_offset: usize, pair_size: usize, key_offset: usize, value_offset: usize, },
757 BTreeMap {
758 length_offset: usize, root_offset: usize, root_layout: BTreeRootLayout, node_layout: BTreeNodeLayout, },
763 IndexMap,
764}
765
766impl MapVariant {
767 pub fn name(&self) -> &'static str {
768 match self {
769 MapVariant::HashMap { .. } => "HashMap",
770 MapVariant::BTreeMap { .. } => "BTreeMap",
771 MapVariant::IndexMap => "IndexMap",
772 }
773 }
774}
775
776#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
777pub struct StringLayout<L = ()>(pub VecLayout<L>)
778where
779 L: Location;
780
781#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
782pub struct VecLayout<L = ()>
783where
784 L: Location,
785{
786 pub length_offset: usize,
788 pub data_ptr_offset: usize,
790 pub capacity_offset: usize,
792 pub inner_type: TypeDefinition<L>,
794}
795
796impl<L: Location + Default> VecLayout<L> {
797 pub fn new<T: Into<Layout<L>>>(inner_type: T) -> Self {
798 Self {
799 length_offset: 0,
800 data_ptr_offset: 0,
801 capacity_offset: 0,
802 inner_type: TypeDefinition::new(Default::default(), inner_type.into()),
803 }
804 }
805}
806
807#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
808pub struct StructLayout<L = ()>
809where
810 L: Location,
811{
812 pub name: String,
813 pub size: usize,
814 pub alignment: usize,
815 pub fields: Vec<StructField<L>>,
816}
817#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
818pub struct StructField<L = ()>
819where
820 L: Location,
821{
822 pub name: String,
823 pub offset: usize,
824 pub ty: TypeDefinition<L>,
825}
826
827#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
828pub struct Discriminant {
829 pub ty: DiscriminantType,
830 pub offset: usize,
831}
832
833impl Discriminant {
834 pub fn size(&self) -> usize {
835 match &self.ty {
836 DiscriminantType::Int(int_def) => int_def.size,
837 DiscriminantType::UnsignedInt(unsigned_int_def) => unsigned_int_def.size,
838 DiscriminantType::Implicit => 4, }
840 }
841}
842
843#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
844pub enum DiscriminantType {
845 Int(IntLayout),
846 UnsignedInt(UnsignedIntLayout),
847 Implicit,
848}
849
850#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
851pub struct EnumLayout<L = ()>
852where
853 L: Location,
854{
855 pub name: String,
856 pub discriminant: Discriminant,
857 pub variants: Vec<EnumVariantLayout<L>>,
858 pub size: usize,
859}
860
861#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
862pub struct EnumVariantLayout<L = ()>
863where
864 L: Location,
865{
866 pub name: String,
867 pub discriminant: Option<i128>,
872 pub layout: TypeDefinition<L>,
873}
874
875#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
876pub struct OptionLayout<L = ()>
877where
878 L: Location,
879{
880 pub name: String,
881 pub discriminant: Discriminant,
882 pub some_offset: usize,
883 pub some_type: TypeDefinition<L>,
884 pub size: usize,
885}
886
887#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
888pub struct ResultLayout<L = ()>
889where
890 L: Location,
891{
892 pub name: String,
893 pub discriminant: Discriminant,
894 pub ok_type: TypeDefinition<L>,
895 pub ok_offset: usize,
896 pub err_type: TypeDefinition<L>,
897 pub err_offset: usize,
898 pub size: usize,
899}
900
901#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
902pub struct CEnumLayout {
903 pub name: String,
904 pub discriminant_type: DiscriminantType,
905 pub variants: Vec<CEnumVariant>,
906 pub size: usize,
907}
908
909#[derive(Debug, PartialEq, Eq, Clone, Hash, Update)]
910pub struct CEnumVariant {
911 pub name: String,
912 pub value: i128,
913}
914
915impl UnsignedIntLayout {
917 pub fn u8() -> Self {
918 Self { size: 1 }
919 }
920 pub fn u32() -> Self {
921 Self { size: 4 }
922 }
923 pub fn u64() -> Self {
924 Self { size: 8 }
925 }
926}
927
928impl IntLayout {
929 pub fn i32() -> Self {
930 Self { size: 4 }
931 }
932}
933
934impl<L: Location + Default> ReferenceLayout<L> {
935 pub fn new_mutable<T: Into<Layout<L>>>(pointed_type: T) -> Self {
936 Self {
937 mutable: true,
938 pointed_type: TypeDefinition::new(Default::default(), pointed_type.into()),
939 }
940 }
941
942 pub fn new_immutable<T: Into<Layout<L>>>(pointed_type: T) -> Self {
943 Self {
944 mutable: false,
945 pointed_type: TypeDefinition::new(Default::default(), pointed_type.into()),
946 }
947 }
948}