1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4use std::mem::MaybeUninit;
5
6mod const_buffers;
7pub use const_buffers::ConstReadBuffer;
8mod cbor;
9mod const_vec;
10mod r#enum;
11pub use r#enum::*;
12mod r#struct;
13pub use r#struct::*;
14mod primitive;
15pub use primitive::*;
16mod list;
17pub use list::*;
18mod array;
19pub use array::*;
20mod str;
21pub use str::*;
22
23pub use const_serialize_macro::SerializeConst;
24pub use const_vec::ConstVec;
25
26use crate::cbor::{
27 str_eq, take_array, take_bytes, take_map, take_number, take_str, write_array, write_bytes,
28 write_map, write_map_key, write_number,
29};
30
31#[derive(Debug, Copy, Clone)]
33pub enum Layout {
34 Enum(EnumLayout),
36 Struct(StructLayout),
38 Array(ArrayLayout),
40 Primitive(PrimitiveLayout),
42 List(ListLayout),
44}
45
46impl Layout {
47 pub const fn size(&self) -> usize {
49 match self {
50 Layout::Enum(layout) => layout.size,
51 Layout::Struct(layout) => layout.size,
52 Layout::Array(layout) => layout.len * layout.item_layout.size(),
53 Layout::List(layout) => layout.size,
54 Layout::Primitive(layout) => layout.size,
55 }
56 }
57}
58
59pub unsafe trait SerializeConst: Sized {
64 const MEMORY_LAYOUT: Layout;
66 const _ASSERT: () = assert!(Self::MEMORY_LAYOUT.size() == std::mem::size_of::<Self>());
68}
69
70const unsafe fn serialize_const_ptr(
72 ptr: *const (),
73 to: ConstVec<u8>,
74 layout: &Layout,
75) -> ConstVec<u8> {
76 match layout {
77 Layout::Enum(layout) => serialize_const_enum(ptr, to, layout),
78 Layout::Struct(layout) => serialize_const_struct(ptr, to, layout),
79 Layout::Array(layout) => serialize_const_array(ptr, to, layout),
80 Layout::List(layout) => serialize_const_list(ptr, to, layout),
81 Layout::Primitive(layout) => serialize_const_primitive(ptr, to, layout),
82 }
83}
84
85#[must_use = "The data is serialized into the returned buffer"]
108pub const fn serialize_const<T: SerializeConst>(data: &T, to: ConstVec<u8>) -> ConstVec<u8> {
109 let ptr = data as *const T as *const ();
110 unsafe { serialize_const_ptr(ptr, to, &T::MEMORY_LAYOUT) }
112}
113
114const fn deserialize_const_ptr<'a>(
116 from: &'a [u8],
117 layout: &Layout,
118 out: &mut [MaybeUninit<u8>],
119) -> Option<&'a [u8]> {
120 match layout {
121 Layout::Enum(layout) => deserialize_const_enum(from, layout, out),
122 Layout::Struct(layout) => deserialize_const_struct(from, layout, out),
123 Layout::Array(layout) => deserialize_const_array(from, layout, out),
124 Layout::List(layout) => deserialize_const_list(from, layout, out),
125 Layout::Primitive(layout) => deserialize_const_primitive(from, layout, out),
126 }
127}
128
129#[macro_export]
158macro_rules! deserialize_const {
159 ($type:ty, $buffer:expr) => {
160 unsafe {
161 const __SIZE: usize = std::mem::size_of::<$type>();
162 $crate::deserialize_const_raw::<__SIZE, $type>($buffer)
163 }
164 };
165}
166
167#[must_use = "The data is deserialized from the input buffer"]
171pub const unsafe fn deserialize_const_raw<const N: usize, T: SerializeConst>(
172 from: &[u8],
173) -> Option<(&[u8], T)> {
174 let mut out = [MaybeUninit::uninit(); N];
176 let Some(from) = deserialize_const_ptr(from, &T::MEMORY_LAYOUT, &mut out) else {
178 return None;
179 };
180 Some((from, unsafe {
182 std::mem::transmute_copy::<[MaybeUninit<u8>; N], T>(&out)
183 }))
184}
185
186pub const fn serialize_eq<T: SerializeConst>(first: &T, second: &T) -> bool {
188 let first_serialized = ConstVec::<u8>::new();
189 let first_serialized = serialize_const(first, first_serialized);
190 let second_serialized = ConstVec::<u8>::new();
191 let second_serialized = serialize_const(second, second_serialized);
192 let first_buf = first_serialized.as_ref();
193 let second_buf = second_serialized.as_ref();
194 if first_buf.len() != second_buf.len() {
195 return false;
196 }
197 let mut i = 0;
198 while i < first_buf.len() {
199 if first_buf[i] != second_buf[i] {
200 return false;
201 }
202 i += 1;
203 }
204 true
205}