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, CopyType, PadTo, TypeHash, Zero},
23};
24
25pub mod deser;
26pub mod impls;
27pub mod ser;
28pub mod traits;
29pub mod utils;
30
31pub mod prelude {
36 #[allow(deprecated)]
37 pub use crate::PhantomDeserData;
38 pub use crate::deser;
39 pub use crate::deser::DeserHelper;
40 pub use crate::deser::DeserInner;
41 pub use crate::deser::DeserType;
42 pub use crate::deser::Deserialize;
43 pub use crate::deser::Flags;
44 pub use crate::deser::MemCase;
45 pub use crate::deser::ReadWithPos;
46 pub use crate::deser::SliceWithPos;
47 pub use crate::impls::iter::SerIter;
48 pub use crate::ser;
49 pub use crate::ser::SerHelper;
50 pub use crate::ser::SerInner;
51 pub use crate::ser::Serialize;
52 pub use crate::traits::*;
53 #[allow(unused_imports)] pub use crate::utils::*;
55 #[cfg(feature = "derive")]
56 pub use epserde_derive::Epserde;
57 pub use {crate::Aligned16, crate::Aligned64};
58}
59
60pub const VERSION: (u16, u16) = (2, 0);
62
63pub const MAGIC: u64 = u64::from_le_bytes(*b"epserde ");
73pub const MAGIC_REV: u64 = MAGIC.swap_bytes();
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
84#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
85#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
86#[repr(align(16))]
87#[derive(Default)]
88pub struct Aligned16(pub [u8; 16]);
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
99#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
100#[repr(align(64))]
101pub struct Aligned64(pub [u8; 64]);
102
103impl Default for Aligned64 {
104 fn default() -> Self {
105 Aligned64([0u8; 64])
106 }
107}
108
109pub const fn pad_align_to(value: usize, pad_to: usize) -> usize {
118 assert!(pad_to == 0 || pad_to.is_power_of_two());
119 value.wrapping_neg() & pad_to.saturating_sub(1)
120}
121
122#[deprecated(
139 since = "0.13.0",
140 note = "use plain `PhantomData<T>` instead: the `Epserde` derive now substitutes \
141its parameter natively. Note: switching an existing struct from \
142`PhantomDeserData<T>` to `PhantomData<T>` changes the struct's type hash, so \
143previously-serialized files will fail to deserialize against the new definition."
144)]
145#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
146pub struct PhantomDeserData<T>(pub PhantomData<T>);
147
148#[allow(deprecated)]
149impl<T: DeserInner> PhantomDeserData<T> {
150 #[inline(always)]
157 pub unsafe fn _deser_eps_inner_special<'a>(
158 _backend: &mut SliceWithPos<'a>,
159 ) -> deser::Result<PhantomDeserData<T::DeserType<'a>>> {
160 Ok(unsafe {
162 transmute::<DeserType<'a, PhantomDeserData<T>>, PhantomDeserData<T::DeserType<'a>>>(
163 PhantomDeserData(PhantomData),
164 )
165 })
166 }
167}
168
169#[allow(deprecated)]
170unsafe impl<T> CopyType for PhantomDeserData<T> {
171 type Copy = Zero;
172}
173
174#[allow(deprecated)]
175impl<T> PadTo for PhantomDeserData<T> {
176 #[inline(always)]
177 fn pad_to() -> usize {
178 0
179 }
180}
181
182#[allow(deprecated)]
183impl<T: TypeHash> TypeHash for PhantomDeserData<T> {
184 #[inline(always)]
185 fn type_hash(hasher: &mut impl core::hash::Hasher) {
186 "PhantomDeserData".hash(hasher);
187 T::type_hash(hasher);
188 }
189}
190
191#[allow(deprecated)]
192impl<T> AlignHash for PhantomDeserData<T> {
193 #[inline(always)]
194 fn align_hash(_hasher: &mut impl core::hash::Hasher, _offset_of: &mut usize) {}
195}
196
197#[allow(deprecated)]
198impl<T> SerInner for PhantomDeserData<T> {
199 type SerType = Self;
201 const IS_ZERO_COPY: bool = true;
202
203 #[inline(always)]
204 unsafe fn _ser_inner(&self, _backend: &mut impl WriteWithNames) -> ser::Result<()> {
205 Ok(())
206 }
207}
208
209#[allow(deprecated)]
210impl<T: DeserInner> DeserInner for PhantomDeserData<T> {
211 unsafe_assume_covariance!();
213 #[inline(always)]
214 unsafe fn _deser_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
215 Ok(PhantomDeserData(PhantomData))
216 }
217 type DeserType<'a> = PhantomDeserData<T::DeserType<'a>>;
218 #[inline(always)]
219 unsafe fn _deser_eps_inner<'a>(
220 _backend: &mut SliceWithPos<'a>,
221 ) -> deser::Result<Self::DeserType<'a>> {
222 Ok(PhantomDeserData(PhantomData))
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::pad_align_to;
229
230 #[test]
231 fn test_pad_align_to() {
232 assert_eq!(7 + pad_align_to(7, 8), 8);
233 assert_eq!(8 + pad_align_to(8, 8), 8);
234 assert_eq!(9 + pad_align_to(9, 8), 16);
235 assert_eq!(36 + pad_align_to(36, 16), 48);
236 }
237
238 #[test]
239 #[should_panic]
240 fn test_pad_align_to_rejects_non_power_of_two() {
241 let _ = pad_align_to(2, 3);
242 }
243}