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