Skip to main content

hermes_simd_core/cow/
rkyv.rs

1//! Zero-copy serialization support for Clone-on-Write SIMD containers using `rkyv`.
2
3use super::SimdCow;
4use crate::align::Alignment;
5use crate::arch::SimdArch;
6use crate::vec::AlignedVec;
7use crate::view::SimdView;
8
9#[repr(transparent)]
10/// Archived representation of a `SimdCow` used by `rkyv` zero-copy serialization.
11pub struct ArchivedSimdCow<T> {
12    pub(crate) elements: rkyv::vec::ArchivedVec<T>,
13}
14
15/// Resolver type for `SimdCow` serialization.
16pub struct SimdCowResolver {
17    pub(crate) elements_resolver: rkyv::vec::VecResolver,
18}
19
20impl<'a, T, Arch, Align> rkyv::Archive for SimdCow<'a, T, Arch, Align>
21where
22    T: rkyv::Archive,
23    Arch: SimdArch,
24    Align: Alignment,
25{
26    type Archived = ArchivedSimdCow<T::Archived>;
27    type Resolver = SimdCowResolver;
28
29    #[inline]
30    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
31        let out_elements = core::ptr::addr_of_mut!((*out).elements);
32        rkyv::vec::ArchivedVec::resolve_from_slice(
33            &self[..],
34            pos,
35            resolver.elements_resolver,
36            out_elements,
37        );
38    }
39}
40
41impl<'a, T, Arch, Align, S> rkyv::Serialize<S> for SimdCow<'a, T, Arch, Align>
42where
43    T: rkyv::Serialize<S> + rkyv::Archive,
44    Arch: SimdArch,
45    Align: Alignment,
46    S: rkyv::Fallible + rkyv::ser::Serializer + ?Sized,
47    [T]: rkyv::SerializeUnsized<S>,
48{
49    #[inline]
50    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
51        let elements_resolver =
52            rkyv::vec::ArchivedVec::serialize_from_slice(&self[..], serializer)?;
53        Ok(SimdCowResolver { elements_resolver })
54    }
55}
56
57impl<T, Arch, Align, D> rkyv::Deserialize<SimdCow<'static, T, Arch, Align>, D>
58    for ArchivedSimdCow<T>
59where
60    T: rkyv::Archive,
61    T: rkyv::Deserialize<T, D>,
62    Arch: SimdArch,
63    Align: Alignment,
64    D: rkyv::Fallible + ?Sized,
65{
66    #[inline]
67    fn deserialize(
68        &self,
69        deserializer: &mut D,
70    ) -> Result<SimdCow<'static, T, Arch, Align>, D::Error> {
71        let slice = self.elements.as_slice();
72        let mut v = AlignedVec::with_capacity(slice.len());
73        for x in slice {
74            v.push(x.deserialize(deserializer)?);
75        }
76        Ok(SimdCow::Owned(v))
77    }
78}
79
80impl<T> ArchivedSimdCow<T> {
81    /// Returns the length of the archived vector.
82    #[inline]
83    pub fn len(&self) -> usize {
84        self.elements.len()
85    }
86
87    /// Returns `true` if the archived vector is empty.
88    #[inline]
89    pub fn is_empty(&self) -> bool {
90        self.elements.is_empty()
91    }
92
93    /// Access the archived elements as a slice.
94    #[inline]
95    pub fn as_slice(&self) -> &[T] {
96        self.elements.as_slice()
97    }
98
99    /// Zero-copy conversion of the archived SimdCow to a borrowed SimdCow.
100    ///
101    /// # Safety
102    /// The alignment of the underlying archived memory must satisfy `Align`.
103    #[inline]
104    pub unsafe fn as_borrowed<'a, Arch, Align>(&'a self) -> Option<SimdCow<'a, T, Arch, Align>>
105    where
106        Arch: SimdArch,
107        Align: Alignment,
108    {
109        let slice = self.elements.as_slice();
110        let view = SimdView::new(slice)?;
111        Some(SimdCow::Borrowed(view))
112    }
113}
114
115impl<T> core::ops::Deref for ArchivedSimdCow<T> {
116    type Target = [T];
117
118    #[inline]
119    fn deref(&self) -> &Self::Target {
120        self.elements.as_slice()
121    }
122}