pub mod serializers;
use crate::{Archive, ArchiveUnsized, Fallible, RelPtr, Serialize, SerializeUnsized};
use core::{alloc::Layout, mem, ptr::NonNull, slice};
pub trait Serializer: Fallible {
fn pos(&self) -> usize;
fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error>;
#[inline]
fn pad(&mut self, padding: usize) -> Result<(), Self::Error> {
const MAX_ZEROES: usize = 32;
const ZEROES: [u8; MAX_ZEROES] = [0; MAX_ZEROES];
debug_assert!(padding < MAX_ZEROES);
self.write(&ZEROES[0..padding])
}
#[inline]
fn align(&mut self, align: usize) -> Result<usize, Self::Error> {
let mask = align - 1;
debug_assert_eq!(align & mask, 0);
self.pad((align - (self.pos() & mask)) & mask)?;
Ok(self.pos())
}
#[inline]
fn align_for<T>(&mut self) -> Result<usize, Self::Error> {
self.align(mem::align_of::<T>())
}
unsafe fn resolve_aligned<T: Archive + ?Sized>(
&mut self,
value: &T,
resolver: T::Resolver,
) -> Result<usize, Self::Error> {
let pos = self.pos();
debug_assert_eq!(pos & (mem::align_of::<T::Archived>() - 1), 0);
let mut resolved = mem::MaybeUninit::<T::Archived>::uninit();
resolved.as_mut_ptr().write_bytes(0, 1);
value.resolve(pos, resolver, resolved.as_mut_ptr());
let data = resolved.as_ptr().cast::<u8>();
let len = mem::size_of::<T::Archived>();
self.write(slice::from_raw_parts(data, len))?;
Ok(pos)
}
#[inline]
fn serialize_value<T: Serialize<Self>>(&mut self, value: &T) -> Result<usize, Self::Error> {
let resolver = value.serialize(self)?;
self.align_for::<T::Archived>()?;
unsafe { self.resolve_aligned(value, resolver) }
}
unsafe fn resolve_unsized_aligned<T: ArchiveUnsized + ?Sized>(
&mut self,
value: &T,
to: usize,
metadata_resolver: T::MetadataResolver,
) -> Result<usize, Self::Error> {
let from = self.pos();
debug_assert_eq!(from & (mem::align_of::<RelPtr<T::Archived>>() - 1), 0);
let mut resolved = mem::MaybeUninit::<RelPtr<T::Archived>>::uninit();
resolved.as_mut_ptr().write_bytes(0, 1);
value.resolve_unsized(from, to, metadata_resolver, resolved.as_mut_ptr());
let data = resolved.as_ptr().cast::<u8>();
let len = mem::size_of::<RelPtr<T::Archived>>();
self.write(slice::from_raw_parts(data, len))?;
Ok(from)
}
#[inline]
fn serialize_unsized_value<T: SerializeUnsized<Self> + ?Sized>(
&mut self,
value: &T,
) -> Result<usize, Self::Error> {
let to = value.serialize_unsized(self)?;
let metadata_resolver = value.serialize_metadata(self)?;
self.align_for::<RelPtr<T::Archived>>()?;
unsafe { self.resolve_unsized_aligned(value, to, metadata_resolver) }
}
}
pub trait ScratchSpace: Fallible {
unsafe fn push_scratch(&mut self, layout: Layout) -> Result<NonNull<[u8]>, Self::Error>;
unsafe fn pop_scratch(&mut self, ptr: NonNull<u8>, layout: Layout) -> Result<(), Self::Error>;
}
pub trait SharedSerializeRegistry: Fallible {
fn get_shared_ptr(&self, value: *const u8) -> Option<usize>;
#[inline]
fn get_shared<T: ?Sized>(&self, value: &T) -> Option<usize> {
self.get_shared_ptr(value as *const T as *const u8)
}
fn add_shared_ptr(&mut self, value: *const u8, pos: usize) -> Result<(), Self::Error>;
#[inline]
fn add_shared<T: ?Sized>(&mut self, value: &T, pos: usize) -> Result<(), Self::Error> {
self.add_shared_ptr(value as *const T as *const u8, pos)
}
#[inline]
fn serialize_shared<T: SerializeUnsized<Self> + ?Sized>(
&mut self,
value: &T,
) -> Result<usize, Self::Error>
where
Self: Serializer,
{
if let Some(pos) = self.get_shared(value) {
Ok(pos)
} else {
let pos = value.serialize_unsized(self)?;
self.add_shared(value, pos)?;
Ok(pos)
}
}
}