1#![cfg_attr(any(feature="std", 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}
53
54pub const VERSION: (u16, u16) = (1, 1);
56
57pub const MAGIC: u64 = u64::from_ne_bytes(*b"epserde ");
59pub const MAGIC_REV: u64 = u64::from_le_bytes(MAGIC.to_be_bytes());
61
62pub fn pad_align_to(value: usize, align_to: usize) -> usize {
65 value.wrapping_neg() & (align_to - 1)
66}
67
68#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
102pub struct PhantomDeserData<T: ?Sized>(pub PhantomData<T>);
103
104impl<T: DeserInner> PhantomDeserData<T> {
105 #[inline(always)]
112 pub unsafe fn _deser_eps_inner_special<'a>(
113 _backend: &mut SliceWithPos<'a>,
114 ) -> deser::Result<PhantomDeserData<T::DeserType<'a>>> {
115 Ok(unsafe {
117 transmute::<DeserType<'a, PhantomDeserData<T>>, PhantomDeserData<T::DeserType<'a>>>(
118 PhantomDeserData(PhantomData),
119 )
120 })
121 }
122}
123
124unsafe impl<T> CopyType for PhantomDeserData<T> {
125 type Copy = Zero;
126}
127
128impl<T> AlignTo for PhantomDeserData<T> {
129 #[inline(always)]
130 fn align_to() -> usize {
131 0
132 }
133}
134
135impl<T: TypeHash> TypeHash for PhantomDeserData<T> {
136 #[inline(always)]
137 fn type_hash(hasher: &mut impl core::hash::Hasher) {
138 "PhantomDeserData".hash(hasher);
139 T::type_hash(hasher);
140 }
141}
142
143impl<T> AlignHash for PhantomDeserData<T> {
144 #[inline(always)]
145 fn align_hash(_hasher: &mut impl core::hash::Hasher, _offset_of: &mut usize) {}
146}
147
148impl<T> SerInner for PhantomDeserData<T> {
149 type SerType = Self;
152 const IS_ZERO_COPY: bool = true;
153
154 #[inline(always)]
155 unsafe fn _ser_inner(&self, _backend: &mut impl WriteWithNames) -> ser::Result<()> {
156 Ok(())
157 }
158}
159
160impl<T: DeserInner> DeserInner for PhantomDeserData<T> {
161 #[inline(always)]
162 unsafe fn _deser_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
163 Ok(PhantomDeserData(PhantomData))
164 }
165 type DeserType<'a> = PhantomDeserData<T::DeserType<'a>>;
166 #[inline(always)]
167 unsafe fn _deser_eps_inner<'a>(
168 _backend: &mut SliceWithPos<'a>,
169 ) -> deser::Result<Self::DeserType<'a>> {
170 Ok(PhantomDeserData(PhantomData))
171 }
172}
173
174#[test]
175
176fn test_pad_align_to() {
177 assert_eq!(7 + pad_align_to(7, 8), 8);
178 assert_eq!(8 + pad_align_to(8, 8), 8);
179 assert_eq!(9 + pad_align_to(9, 8), 16);
180 assert_eq!(36 + pad_align_to(36, 16), 48);
181}