use crate::traits::*;
use crate::*;
use core::hash::Hasher;
pub mod write_with_names;
pub use write_with_names::*;
pub mod helpers;
pub use helpers::*;
pub mod write;
pub use write::*;
#[cfg(feature = "std")]
use std::{io::BufWriter, path::Path};
pub type Result<T> = core::result::Result<T, Error>;
pub type SerType<T> = <T as SerInner>::SerType;
pub trait Serialize {
unsafe fn serialize(&self, backend: &mut impl WriteNoStd) -> Result<usize> {
let mut write_with_pos = WriterWithPos::new(backend);
unsafe { self.ser_on_field_write(&mut write_with_pos) }?;
Ok(write_with_pos.pos())
}
unsafe fn serialize_with_schema(&self, backend: &mut impl WriteNoStd) -> Result<Schema> {
let mut writer_with_pos = WriterWithPos::new(backend);
let mut schema_writer = SchemaWriter::new(&mut writer_with_pos);
unsafe { self.ser_on_field_write(&mut schema_writer) }?;
Ok(schema_writer.schema)
}
unsafe fn ser_on_field_write(&self, backend: &mut impl WriteWithNames) -> Result<()>;
#[cfg(feature = "std")]
unsafe fn store(&self, path: impl AsRef<Path>) -> Result<()> {
let file = std::fs::File::create(path).map_err(Error::FileOpenError)?;
let mut buf_writer = BufWriter::new(file);
unsafe { self.serialize(&mut buf_writer)? };
Ok(())
}
}
pub trait SerInner {
type SerType;
const IS_ZERO_COPY: bool;
unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> Result<()>;
}
impl<T: SerInner<SerType: TypeHash + AlignHash>> Serialize for T {
unsafe fn ser_on_field_write(&self, backend: &mut impl WriteWithNames) -> Result<()> {
write_header::<SerType<Self>>(backend)?;
backend.write("ROOT", self)?;
backend.flush()
}
}
pub fn write_header<S: TypeHash + AlignHash>(backend: &mut impl WriteWithNames) -> Result<()> {
backend.write("MAGIC", &MAGIC)?;
backend.write("VERSION_MAJOR", &VERSION.0)?;
backend.write("VERSION_MINOR", &VERSION.1)?;
backend.write("USIZE_SIZE", &(core::mem::size_of::<usize>() as u8))?;
let mut type_hasher = xxhash_rust::xxh3::Xxh3::new();
S::type_hash(&mut type_hasher);
let mut align_hasher = xxhash_rust::xxh3::Xxh3::new();
let mut offset_of = 0;
S::align_hash(&mut align_hasher, &mut offset_of);
backend.write("TYPE_HASH", &type_hasher.finish())?;
backend.write("REPR_HASH", &align_hasher.finish())?;
backend.write("TYPE_NAME", &core::any::type_name::<S>())
}
pub trait SerHelper<T: CopySelector> {
unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> Result<()>;
}
#[derive(Debug)]
pub enum Error {
WriteError,
#[cfg(feature = "std")]
FileOpenError(std::io::Error),
IteratorLengthMismatch { actual: usize, expected: usize },
}
impl core::error::Error for Error {}
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
Self::WriteError => write!(f, "Write error during ε-serde serialization"),
#[cfg(feature = "std")]
Self::FileOpenError(error) => {
write!(
f,
"Error opening file during ε-serde serialization: {}",
error
)
}
Self::IteratorLengthMismatch { actual, expected } => write!(
f,
"Iterator length mismatch during ε-serde serialization: expected {} items, got {}",
expected, actual
),
}
}
}