1#![cfg_attr(any(all(feature="std", feature="mmap"), not(doctest)), doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md")))]
9#![deny(unconditional_recursion)]
10#![cfg_attr(not(feature = "std"), no_std)]
11#[cfg(not(feature = "std"))]
12extern crate alloc;
13
14use core::{hash::Hash, marker::PhantomData, mem::transmute};
15
16#[cfg(feature = "derive")]
17pub use epserde_derive::{Epserde, TypeInfo};
18
19use crate::{
20 deser::{DeserInner, DeserType, ReadWithPos, SliceWithPos},
21 ser::{SerInner, WriteWithNames},
22 traits::{AlignHash, AlignTo, CopyType, TypeHash, Zero},
23};
24
25pub mod deser;
26pub mod impls;
27pub mod ser;
28pub mod traits;
29pub mod utils;
30
31pub mod prelude {
32 pub use crate::PhantomDeserData;
33 pub use crate::deser;
34 pub use crate::deser::DeserHelper;
35 pub use crate::deser::DeserInner;
36 pub use crate::deser::DeserType;
37 pub use crate::deser::Deserialize;
38 pub use crate::deser::Flags;
39 pub use crate::deser::MemCase;
40 pub use crate::deser::ReadWithPos;
41 pub use crate::deser::SliceWithPos;
42 pub use crate::impls::iter::SerIter;
43 pub use crate::ser;
44 pub use crate::ser::SerHelper;
45 pub use crate::ser::SerInner;
46 pub use crate::ser::Serialize;
47 pub use crate::traits::*;
48 #[allow(unused_imports)] pub use crate::utils::*;
50 #[cfg(feature = "derive")]
51 pub use epserde_derive::Epserde;
52 pub use {crate::Aligned16, crate::Aligned64};
53}
54
55pub const VERSION: (u16, u16) = (1, 1);
57
58pub const MAGIC: u64 = u64::from_ne_bytes(*b"epserde ");
60pub const MAGIC_REV: u64 = u64::from_le_bytes(MAGIC.to_be_bytes());
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
69#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
70#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
71#[repr(align(16))]
72#[derive(Default)]
73pub struct Aligned16(pub [u8; 16]);
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
81#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
82#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
83#[repr(align(64))]
84pub struct Aligned64(pub [u8; 64]);
85
86impl Default for Aligned64 {
87 fn default() -> Self {
88 Aligned64([0u8; 64])
89 }
90}
91
92pub const fn pad_align_to(value: usize, align_to: usize) -> usize {
95 value.wrapping_neg() & (align_to - 1)
96}
97
98#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
132pub struct PhantomDeserData<T>(pub PhantomData<T>);
133
134impl<T: DeserInner> PhantomDeserData<T> {
135 #[inline(always)]
142 pub unsafe fn _deser_eps_inner_special<'a>(
143 _backend: &mut SliceWithPos<'a>,
144 ) -> deser::Result<PhantomDeserData<T::DeserType<'a>>> {
145 Ok(unsafe {
147 transmute::<DeserType<'a, PhantomDeserData<T>>, PhantomDeserData<T::DeserType<'a>>>(
148 PhantomDeserData(PhantomData),
149 )
150 })
151 }
152}
153
154unsafe impl<T> CopyType for PhantomDeserData<T> {
155 type Copy = Zero;
156}
157
158impl<T> AlignTo for PhantomDeserData<T> {
159 #[inline(always)]
160 fn align_to() -> usize {
161 0
162 }
163}
164
165impl<T: TypeHash> TypeHash for PhantomDeserData<T> {
166 #[inline(always)]
167 fn type_hash(hasher: &mut impl core::hash::Hasher) {
168 "PhantomDeserData".hash(hasher);
169 T::type_hash(hasher);
170 }
171}
172
173impl<T> AlignHash for PhantomDeserData<T> {
174 #[inline(always)]
175 fn align_hash(_hasher: &mut impl core::hash::Hasher, _offset_of: &mut usize) {}
176}
177
178impl<T> SerInner for PhantomDeserData<T> {
179 type SerType = Self;
181 const IS_ZERO_COPY: bool = true;
182
183 #[inline(always)]
184 unsafe fn _ser_inner(&self, _backend: &mut impl WriteWithNames) -> ser::Result<()> {
185 Ok(())
186 }
187}
188
189impl<T: DeserInner> DeserInner for PhantomDeserData<T> {
190 unsafe_assume_covariance!();
192 #[inline(always)]
193 unsafe fn _deser_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
194 Ok(PhantomDeserData(PhantomData))
195 }
196 type DeserType<'a> = PhantomDeserData<T::DeserType<'a>>;
197 #[inline(always)]
198 unsafe fn _deser_eps_inner<'a>(
199 _backend: &mut SliceWithPos<'a>,
200 ) -> deser::Result<Self::DeserType<'a>> {
201 Ok(PhantomDeserData(PhantomData))
202 }
203}
204
205#[cfg(test)]
206#[test]
207fn test_pad_align_to() {
208 assert_eq!(7 + pad_align_to(7, 8), 8);
209 assert_eq!(8 + pad_align_to(8, 8), 8);
210 assert_eq!(9 + pad_align_to(9, 8), 16);
211 assert_eq!(36 + pad_align_to(36, 16), 48);
212}