const_serialize/
list.rs

1use crate::*;
2
3/// The layout for a dynamically sized list. The list layout is just a length and an item layout.
4#[derive(Debug, Copy, Clone)]
5pub struct ListLayout {
6    /// The size of the struct backing the list
7    pub(crate) size: usize,
8    /// The byte offset of the length field
9    len_offset: usize,
10    /// The layout of the length field
11    len_layout: PrimitiveLayout,
12    /// The byte offset of the data field
13    data_offset: usize,
14    /// The layout of the data field
15    data_layout: ArrayLayout,
16}
17
18impl ListLayout {
19    /// Create a new list layout
20    pub const fn new(
21        size: usize,
22        len_offset: usize,
23        len_layout: PrimitiveLayout,
24        data_offset: usize,
25        data_layout: ArrayLayout,
26    ) -> Self {
27        Self {
28            size,
29            len_offset,
30            len_layout,
31            data_offset,
32            data_layout,
33        }
34    }
35}
36
37/// Serialize a dynamically sized list that is stored at the pointer passed in
38pub(crate) const unsafe fn serialize_const_list(
39    ptr: *const (),
40    mut to: ConstVec<u8>,
41    layout: &ListLayout,
42) -> ConstVec<u8> {
43    // Read the length of the list
44    let len_ptr = ptr.wrapping_byte_offset(layout.len_offset as _);
45    let len = layout.len_layout.read(len_ptr as *const u8) as usize;
46
47    let data_ptr = ptr.wrapping_byte_offset(layout.data_offset as _);
48    let item_layout = layout.data_layout.item_layout;
49    // If the item size is 1, deserialize as bytes directly
50    if item_layout.size() == 1 {
51        let slice = std::slice::from_raw_parts(data_ptr as *const u8, len);
52        to = write_bytes(to, slice);
53    }
54    // Otherwise, deserialize as a list of items
55    else {
56        let mut i = 0;
57        to = write_array(to, len);
58        while i < len {
59            let item = data_ptr.wrapping_byte_offset((i * item_layout.size()) as _);
60            to = serialize_const_ptr(item, to, item_layout);
61            i += 1;
62        }
63    }
64    to
65}
66
67/// Deserialize a list type into the out buffer at the offset passed in. Returns a new version of the buffer with the data added.
68pub(crate) const fn deserialize_const_list<'a>(
69    from: &'a [u8],
70    layout: &ListLayout,
71    out: &mut [MaybeUninit<u8>],
72) -> Option<&'a [u8]> {
73    let Some((_, len_out)) = out.split_at_mut_checked(layout.len_offset) else {
74        return None;
75    };
76
77    // If the list items are only one byte, serialize as bytes directly
78    let item_layout = layout.data_layout.item_layout;
79    if item_layout.size() == 1 {
80        let Ok((bytes, new_from)) = take_bytes(from) else {
81            return None;
82        };
83        // Write out the length of the list
84        layout.len_layout.write(bytes.len() as u32, len_out);
85        let Some((_, data_out)) = out.split_at_mut_checked(layout.data_offset) else {
86            return None;
87        };
88        let mut offset = 0;
89        while offset < bytes.len() {
90            data_out[offset] = MaybeUninit::new(bytes[offset]);
91            offset += 1;
92        }
93        Some(new_from)
94    }
95    // Otherwise, serialize as an list of objects
96    else {
97        let Ok((len, mut from)) = take_array(from) else {
98            return None;
99        };
100        // Write out the length of the list
101        layout.len_layout.write(len as u32, len_out);
102        let Some((_, mut data_out)) = out.split_at_mut_checked(layout.data_offset) else {
103            return None;
104        };
105        let mut i = 0;
106        while i < len {
107            let Some(new_from) = deserialize_const_ptr(from, item_layout, data_out) else {
108                return None;
109            };
110            let Some((_, item_out)) = data_out.split_at_mut_checked(item_layout.size()) else {
111                return None;
112            };
113            data_out = item_out;
114            from = new_from;
115            i += 1;
116        }
117        Some(from)
118    }
119}