1use crate::*;
2
3#[derive(Debug, Copy, Clone)]
5pub struct StructFieldLayout {
6 name: &'static str,
7 offset: usize,
8 layout: Layout,
9}
10
11impl StructFieldLayout {
12 pub const fn new(name: &'static str, offset: usize, layout: Layout) -> Self {
14 Self {
15 name,
16 offset,
17 layout,
18 }
19 }
20}
21
22#[derive(Debug, Copy, Clone)]
24pub struct StructLayout {
25 pub(crate) size: usize,
26 pub(crate) data: &'static [StructFieldLayout],
27}
28
29impl StructLayout {
30 pub const fn new(size: usize, data: &'static [StructFieldLayout]) -> Self {
32 Self { size, data }
33 }
34}
35
36pub(crate) const unsafe fn serialize_const_struct(
38 ptr: *const (),
39 to: ConstVec<u8>,
40 layout: &StructLayout,
41) -> ConstVec<u8> {
42 let mut i = 0;
43 let field_count = layout.data.len();
44 let mut to = write_map(to, field_count);
45 while i < field_count {
46 let StructFieldLayout {
48 name,
49 offset,
50 layout,
51 } = &layout.data[i];
52 to = write_map_key(to, name);
53 let field = ptr.wrapping_byte_add(*offset as _);
54 to = serialize_const_ptr(field, to, layout);
55 i += 1;
56 }
57 to
58}
59
60pub(crate) const fn deserialize_const_struct<'a>(
62 from: &'a [u8],
63 layout: &StructLayout,
64 out: &mut [MaybeUninit<u8>],
65) -> Option<&'a [u8]> {
66 let Ok((map, from)) = take_map(from) else {
67 return None;
68 };
69 let mut i = 0;
70 while i < layout.data.len() {
71 let StructFieldLayout {
73 name,
74 offset,
75 layout,
76 } = &layout.data[i];
77 let Ok(Some(from)) = map.find(name) else {
78 return None;
79 };
80 let Some((_, field_bytes)) = out.split_at_mut_checked(*offset) else {
81 return None;
82 };
83 if deserialize_const_ptr(from, layout, field_bytes).is_none() {
84 return None;
85 }
86 i += 1;
87 }
88 Some(from)
89}
90
91macro_rules! impl_serialize_const_tuple {
92 ($($generic:ident: $generic_number:expr),*) => {
93 impl_serialize_const_tuple!(@impl ($($generic,)*) = $($generic: $generic_number),*);
94 };
95 (@impl $inner:ty = $($generic:ident: $generic_number:expr),*) => {
96 unsafe impl<$($generic: SerializeConst),*> SerializeConst for ($($generic,)*) {
97 const MEMORY_LAYOUT: Layout = {
98 Layout::Struct(StructLayout {
99 size: std::mem::size_of::<($($generic,)*)>(),
100 data: &[
101 $(
102 StructFieldLayout::new(stringify!($generic_number), std::mem::offset_of!($inner, $generic_number), $generic::MEMORY_LAYOUT),
103 )*
104 ],
105 })
106 };
107 }
108 };
109}
110
111impl_serialize_const_tuple!(T1: 0);
112impl_serialize_const_tuple!(T1: 0, T2: 1);
113impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2);
114impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3);
115impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3, T5: 4);
116impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5);
117impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6);
118impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6, T8: 7);
119impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6, T8: 7, T9: 8);
120impl_serialize_const_tuple!(T1: 0, T2: 1, T3: 2, T4: 3, T5: 4, T6: 5, T7: 6, T8: 7, T9: 8, T10: 9);