#![cfg_attr(any(all(feature="std", feature="mmap"), not(doctest)), doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md")))]
#![deny(unconditional_recursion)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
use core::{hash::Hash, marker::PhantomData, mem::transmute};
#[cfg(feature = "derive")]
pub use epserde_derive::{Epserde, TypeInfo};
use crate::{
deser::{DeserInner, DeserType, ReadWithPos, SliceWithPos},
ser::{SerInner, WriteWithNames},
traits::{AlignHash, CopyType, PadTo, TypeHash, Zero},
};
pub mod deser;
pub mod impls;
pub mod ser;
pub mod traits;
pub mod utils;
pub mod prelude {
#[allow(deprecated)]
pub use crate::PhantomDeserData;
pub use crate::deser;
pub use crate::deser::DeserHelper;
pub use crate::deser::DeserInner;
pub use crate::deser::DeserType;
pub use crate::deser::Deserialize;
pub use crate::deser::Flags;
pub use crate::deser::MemCase;
pub use crate::deser::ReadWithPos;
pub use crate::deser::SliceWithPos;
pub use crate::impls::iter::SerIter;
pub use crate::ser;
pub use crate::ser::SerHelper;
pub use crate::ser::SerInner;
pub use crate::ser::Serialize;
pub use crate::traits::*;
#[allow(unused_imports)] pub use crate::utils::*;
#[cfg(feature = "derive")]
pub use epserde_derive::Epserde;
pub use {crate::Aligned16, crate::Aligned64};
}
pub const VERSION: (u16, u16) = (2, 0);
pub const MAGIC: u64 = u64::from_le_bytes(*b"epserde ");
pub const MAGIC_REV: u64 = MAGIC.swap_bytes();
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
#[repr(align(16))]
#[derive(Default)]
pub struct Aligned16(pub [u8; 16]);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
#[repr(align(64))]
pub struct Aligned64(pub [u8; 64]);
impl Default for Aligned64 {
fn default() -> Self {
Aligned64([0u8; 64])
}
}
pub const fn pad_align_to(value: usize, pad_to: usize) -> usize {
assert!(pad_to == 0 || pad_to.is_power_of_two());
value.wrapping_neg() & pad_to.saturating_sub(1)
}
#[deprecated(
since = "0.13.0",
note = "use plain `PhantomData<T>` instead: the `Epserde` derive now substitutes \
its parameter natively. Note: switching an existing struct from \
`PhantomDeserData<T>` to `PhantomData<T>` changes the struct's type hash, so \
previously-serialized files will fail to deserialize against the new definition."
)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PhantomDeserData<T>(pub PhantomData<T>);
#[allow(deprecated)]
impl<T: DeserInner> PhantomDeserData<T> {
#[inline(always)]
pub unsafe fn _deser_eps_inner_special<'a>(
_backend: &mut SliceWithPos<'a>,
) -> deser::Result<PhantomDeserData<T::DeserType<'a>>> {
Ok(unsafe {
transmute::<DeserType<'a, PhantomDeserData<T>>, PhantomDeserData<T::DeserType<'a>>>(
PhantomDeserData(PhantomData),
)
})
}
}
#[allow(deprecated)]
unsafe impl<T> CopyType for PhantomDeserData<T> {
type Copy = Zero;
}
#[allow(deprecated)]
impl<T> PadTo for PhantomDeserData<T> {
#[inline(always)]
fn pad_to() -> usize {
0
}
}
#[allow(deprecated)]
impl<T: TypeHash> TypeHash for PhantomDeserData<T> {
#[inline(always)]
fn type_hash(hasher: &mut impl core::hash::Hasher) {
"PhantomDeserData".hash(hasher);
T::type_hash(hasher);
}
}
#[allow(deprecated)]
impl<T> AlignHash for PhantomDeserData<T> {
#[inline(always)]
fn align_hash(_hasher: &mut impl core::hash::Hasher, _offset_of: &mut usize) {}
}
#[allow(deprecated)]
impl<T> SerInner for PhantomDeserData<T> {
type SerType = Self;
const IS_ZERO_COPY: bool = true;
#[inline(always)]
unsafe fn _ser_inner(&self, _backend: &mut impl WriteWithNames) -> ser::Result<()> {
Ok(())
}
}
#[allow(deprecated)]
impl<T: DeserInner> DeserInner for PhantomDeserData<T> {
unsafe_assume_covariance!();
#[inline(always)]
unsafe fn _deser_full_inner(_backend: &mut impl ReadWithPos) -> deser::Result<Self> {
Ok(PhantomDeserData(PhantomData))
}
type DeserType<'a> = PhantomDeserData<T::DeserType<'a>>;
#[inline(always)]
unsafe fn _deser_eps_inner<'a>(
_backend: &mut SliceWithPos<'a>,
) -> deser::Result<Self::DeserType<'a>> {
Ok(PhantomDeserData(PhantomData))
}
}
#[cfg(test)]
mod tests {
use super::pad_align_to;
#[test]
fn test_pad_align_to() {
assert_eq!(7 + pad_align_to(7, 8), 8);
assert_eq!(8 + pad_align_to(8, 8), 8);
assert_eq!(9 + pad_align_to(9, 8), 16);
assert_eq!(36 + pad_align_to(36, 16), 48);
}
#[test]
#[should_panic]
fn test_pad_align_to_rejects_non_power_of_two() {
let _ = pad_align_to(2, 3);
}
}