use super::SimdCow;
use crate::align::Alignment;
use crate::arch::SimdArch;
use crate::vec::AlignedVec;
use crate::view::SimdView;
use rkyv::munge::munge;
use rkyv::rancor::Fallible;
use rkyv::ser::{Allocator, Writer};
use rkyv::{Place, Portable};
#[derive(Portable, rkyv::bytecheck::CheckBytes)]
#[bytecheck(crate = rkyv::bytecheck)]
#[repr(transparent)]
pub struct ArchivedSimdCow<T> {
pub(crate) elements: rkyv::vec::ArchivedVec<T>,
}
pub struct SimdCowResolver {
pub(crate) elements_resolver: rkyv::vec::VecResolver,
}
impl<'a, T, Arch, Align> rkyv::Archive for SimdCow<'a, T, Arch, Align>
where
T: rkyv::Archive,
Arch: SimdArch,
Align: Alignment,
{
type Archived = ArchivedSimdCow<T::Archived>;
type Resolver = SimdCowResolver;
#[inline]
fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
munge!(let ArchivedSimdCow { elements } = out);
rkyv::vec::ArchivedVec::resolve_from_slice(&self[..], resolver.elements_resolver, elements);
}
}
impl<'a, T, Arch, Align, S> rkyv::Serialize<S> for SimdCow<'a, T, Arch, Align>
where
T: rkyv::Serialize<S> + rkyv::Archive,
Arch: SimdArch,
Align: Alignment,
S: Fallible + Allocator + Writer + ?Sized,
{
#[inline]
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
let elements_resolver =
rkyv::vec::ArchivedVec::serialize_from_slice(&self[..], serializer)?;
Ok(SimdCowResolver { elements_resolver })
}
}
impl<T, U, Arch, Align, D> rkyv::Deserialize<SimdCow<'static, U, Arch, Align>, D>
for ArchivedSimdCow<T>
where
T: rkyv::Deserialize<U, D>,
Arch: SimdArch,
Align: Alignment,
D: Fallible + ?Sized,
{
#[inline]
fn deserialize(
&self,
deserializer: &mut D,
) -> Result<SimdCow<'static, U, Arch, Align>, D::Error> {
let slice = self.elements.as_slice();
let mut v = AlignedVec::with_capacity(slice.len());
for x in slice {
v.push(x.deserialize(deserializer)?);
}
Ok(SimdCow::Owned(v))
}
}
impl<T> ArchivedSimdCow<T> {
#[inline]
pub fn len(&self) -> usize {
self.elements.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.elements.as_slice()
}
#[inline]
pub unsafe fn as_borrowed<'a, Arch, Align>(&'a self) -> Option<SimdCow<'a, T, Arch, Align>>
where
Arch: SimdArch,
Align: Alignment,
{
let slice = self.elements.as_slice();
let view = SimdView::new(slice)?;
Some(SimdCow::Borrowed(view))
}
}
impl<T> core::ops::Deref for ArchivedSimdCow<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.elements.as_slice()
}
}