use crate::traits::*;
use crate::*;
use crate::traits::CryptoHasher;
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;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[cfg(feature = "std")]
#[error("Error opening file during ε-serde serialization: {0}")]
FileOpenError(#[source] std::io::Error),
#[cfg(feature = "std")]
#[error("I/O error during ε-serde serialization: {0}")]
IoError(#[source] std::io::Error),
#[error("Write error during ε-serde serialization")]
WriteError,
#[error(
"Iterator length mismatch during ε-serde serialization: expected {expected} items, got {actual}"
)]
IteratorLengthMismatch { actual: usize, expected: usize },
#[error(
"Cannot serialize an exhausted RangeInclusive, as deserialization cannot reconstruct it"
)]
ExhaustedRange,
}
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)?;
unsafe { backend.write("ROOT", self) }?;
backend.flush()
}
}
pub fn write_header<S: TypeHash + AlignHash>(backend: &mut impl WriteWithNames) -> Result<()> {
unsafe { backend.write("MAGIC", &MAGIC) }?;
unsafe { backend.write("VERSION_MAJOR", &VERSION.0) }?;
unsafe { backend.write("VERSION_MINOR", &VERSION.1) }?;
unsafe { backend.write("USIZE_SIZE", &(core::mem::size_of::<usize>() as u8)) }?;
let mut type_hasher = CryptoHasher::new();
S::type_hash(&mut type_hasher);
let mut align_hasher = CryptoHasher::new();
let mut offset_of = 0;
S::align_hash(&mut align_hasher, &mut offset_of);
unsafe { backend.write("TYPE_HASH", &type_hasher.finalize()) }?;
unsafe { backend.write("ALIGN_HASH", &align_hasher.finalize()) }?;
unsafe { backend.write("TYPE_NAME", &core::any::type_name::<S>()) }
}
pub trait SerHelper<T: CopySelector> {
unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> Result<()>;
}