use crate::packed::cow::Packed4Cow;
use crate::packed::slice::{Packable4, Packed4Slice};
use crate::packed::vec::Packed4Vec;
use rkyv::bytecheck::CheckBytes;
use rkyv::munge::munge;
use rkyv::rancor::{fail, Fallible, Source};
use rkyv::ser::{Allocator, Writer};
use rkyv::vec::{ArchivedVec, VecResolver};
use rkyv::{Archive, Deserialize, Place, Portable, Serialize};
#[derive(Debug)]
struct LengthExceedsData {
len: usize,
capacity: usize,
}
impl core::fmt::Display for LengthExceedsData {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"archived packed container declares {} elements but its data section holds {} nibbles",
self.len, self.capacity
)
}
}
impl core::error::Error for LengthExceedsData {}
fn verify_length<E: Source>(len: usize, data: &ArchivedVec<u8>) -> Result<(), E> {
let capacity = data.len() * 2;
if len > capacity {
fail!(LengthExceedsData { len, capacity });
}
Ok(())
}
#[derive(Portable, CheckBytes)]
#[bytecheck(crate = rkyv::bytecheck, verify)]
#[repr(C)]
pub struct ArchivedPacked4Cow<T: Packable4> {
pub(crate) data: ArchivedVec<u8>,
pub(crate) len: rkyv::Archived<usize>,
pub(crate) _marker: core::marker::PhantomData<T>,
}
pub struct Packed4CowResolver {
pub(crate) data_resolver: VecResolver,
}
impl<T: Packable4> Archive for Packed4Cow<'_, T> {
type Archived = ArchivedPacked4Cow<T>;
type Resolver = Packed4CowResolver;
#[inline]
fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
let view = self.as_view();
munge!(let ArchivedPacked4Cow { data, len, _marker: _ } = out);
ArchivedVec::resolve_from_slice(view.as_packed_slice(), resolver.data_resolver, data);
view.len().resolve((), len);
}
}
impl<T: Packable4, S> Serialize<S> for Packed4Cow<'_, T>
where
S: Fallible + Allocator + Writer + ?Sized,
{
#[inline]
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
let view = self.as_view();
let data_resolver = ArchivedVec::serialize_from_slice(view.as_packed_slice(), serializer)?;
Ok(Packed4CowResolver { data_resolver })
}
}
impl<T: Packable4, D> Deserialize<Packed4Cow<'static, T>, D> for ArchivedPacked4Cow<T>
where
D: Fallible + ?Sized,
{
#[inline]
fn deserialize(&self, _deserializer: &mut D) -> Result<Packed4Cow<'static, T>, D::Error> {
let mut vec = Packed4Vec::with_capacity(self.len());
vec.data.extend_from_slice(self.data.as_slice());
vec.len = self.len();
Ok(Packed4Cow::Owned(vec))
}
}
impl<T: Packable4> ArchivedPacked4Cow<T> {
#[inline]
pub fn len(&self) -> usize {
self.len.to_native() as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn as_borrowed(&self) -> Option<Packed4Cow<'_, T>> {
let len = self.len();
Packed4Slice::new(self.data.as_slice(), len).map(Packed4Cow::Borrowed)
}
}
#[derive(Portable, CheckBytes)]
#[bytecheck(crate = rkyv::bytecheck, verify)]
#[repr(C)]
pub struct ArchivedPacked4Vec<T: Packable4> {
pub(crate) data: ArchivedVec<u8>,
pub(crate) len: rkyv::Archived<usize>,
pub(crate) _marker: core::marker::PhantomData<T>,
}
pub struct Packed4VecResolver {
pub(crate) data_resolver: VecResolver,
}
impl<T: Packable4> Archive for Packed4Vec<T> {
type Archived = ArchivedPacked4Vec<T>;
type Resolver = Packed4VecResolver;
#[inline]
fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
munge!(let ArchivedPacked4Vec { data, len, _marker: _ } = out);
ArchivedVec::resolve_from_slice(self.as_packed_slice(), resolver.data_resolver, data);
self.len.resolve((), len);
}
}
impl<T: Packable4, S> Serialize<S> for Packed4Vec<T>
where
S: Fallible + Allocator + Writer + ?Sized,
{
#[inline]
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
let data_resolver = ArchivedVec::serialize_from_slice(self.as_packed_slice(), serializer)?;
Ok(Packed4VecResolver { data_resolver })
}
}
impl<T: Packable4, D> Deserialize<Packed4Vec<T>, D> for ArchivedPacked4Vec<T>
where
D: Fallible + ?Sized,
{
#[inline]
fn deserialize(&self, _deserializer: &mut D) -> Result<Packed4Vec<T>, D::Error> {
let mut vec = Packed4Vec::with_capacity(self.len());
vec.data.extend_from_slice(self.data.as_slice());
vec.len = self.len();
Ok(vec)
}
}
impl<T: Packable4> ArchivedPacked4Vec<T> {
#[inline]
pub fn len(&self) -> usize {
self.len.to_native() as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn as_view(&self) -> Option<Packed4Slice<'_, T>> {
Packed4Slice::new(self.data.as_slice(), self.len())
}
}
unsafe impl<T: Packable4, C> rkyv::bytecheck::Verify<C> for ArchivedPacked4Cow<T>
where
C: Fallible + ?Sized,
C::Error: Source,
{
fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
verify_length(self.len(), &self.data)
}
}
unsafe impl<T: Packable4, C> rkyv::bytecheck::Verify<C> for ArchivedPacked4Vec<T>
where
C: Fallible + ?Sized,
C::Error: Source,
{
fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
verify_length(self.len(), &self.data)
}
}
#[cfg(test)]
mod tests;