1use crate::*;
2
3pub(crate) const unsafe fn serialize_const_enum(
5 ptr: *const (),
6 mut to: ConstVec<u8>,
7 layout: &EnumLayout,
8) -> ConstVec<u8> {
9 let byte_ptr = ptr as *const u8;
10 let discriminant = layout.discriminant.read(byte_ptr);
11
12 let mut i = 0;
13 while i < layout.variants.len() {
14 let EnumVariant {
16 tag, name, data, ..
17 } = &layout.variants[i];
18 if discriminant == *tag {
19 to = write_map(to, 1);
20 to = write_map_key(to, name);
21 let data_ptr = ptr.wrapping_byte_offset(layout.variants_offset as _);
22 to = serialize_const_struct(data_ptr, to, data);
23 break;
24 }
25 i += 1;
26 }
27 to
28}
29
30#[derive(Debug, Copy, Clone)]
32pub struct EnumLayout {
33 pub(crate) size: usize,
34 discriminant: PrimitiveLayout,
35 variants_offset: usize,
36 variants: &'static [EnumVariant],
37}
38
39impl EnumLayout {
40 pub const fn new(
42 size: usize,
43 discriminant: PrimitiveLayout,
44 variants: &'static [EnumVariant],
45 ) -> Self {
46 let mut max_align = 1;
47 let mut i = 0;
48 while i < variants.len() {
49 let EnumVariant { align, .. } = &variants[i];
50 if *align > max_align {
51 max_align = *align;
52 }
53 i += 1;
54 }
55
56 let variants_offset_raw = discriminant.size;
57 let padding = (max_align - (variants_offset_raw % max_align)) % max_align;
58 let variants_offset = variants_offset_raw + padding;
59
60 assert!(variants_offset % max_align == 0);
61
62 Self {
63 size,
64 discriminant,
65 variants_offset,
66 variants,
67 }
68 }
69}
70
71#[derive(Debug, Copy, Clone)]
73pub struct EnumVariant {
74 name: &'static str,
75 tag: u32,
77 data: StructLayout,
78 align: usize,
79}
80
81impl EnumVariant {
82 pub const fn new(name: &'static str, tag: u32, data: StructLayout, align: usize) -> Self {
84 Self {
85 name,
86 tag,
87 data,
88 align,
89 }
90 }
91}
92
93pub(crate) const fn deserialize_const_enum<'a>(
95 from: &'a [u8],
96 layout: &EnumLayout,
97 out: &mut [MaybeUninit<u8>],
98) -> Option<&'a [u8]> {
99 let Ok((map, remaining)) = take_map(from) else {
101 return None;
102 };
103
104 let Ok((deserilized_name, from)) = take_str(map.bytes) else {
106 return None;
107 };
108
109 let mut i = 0;
111 let mut matched_variant = false;
112 while i < layout.variants.len() {
113 let EnumVariant {
115 name, data, tag, ..
116 } = &layout.variants[i];
117 if str_eq(deserilized_name, name) {
118 layout.discriminant.write(*tag, out);
119 let Some((_, out)) = out.split_at_mut_checked(layout.variants_offset) else {
120 return None;
121 };
122 if deserialize_const_struct(from, data, out).is_none() {
123 return None;
124 }
125 matched_variant = true;
126 break;
127 }
128 i += 1;
129 }
130 if !matched_variant {
131 return None;
132 }
133
134 Some(remaining)
135}