dbsp/dynamic/
rkyv.rs

1use super::{AsAny, Comparable, DowncastTrait};
2use crate::{
3    derive_comparison_traits,
4    storage::file::{Deserializer, Serializer},
5};
6use rkyv::{
7    Archive, Archived, Deserialize, Fallible, Serialize, archived_value,
8    de::deserializers::SharedDeserializeMap,
9};
10use std::{cmp::Ordering, marker::PhantomData, mem::transmute};
11
12/// Trait for DBData that can be deserialized with [`rkyv`].
13///
14/// The associated type `Repr` with the bound + connecting it to Archived
15/// seems to be the key for rust to know the bounds exist globally in the code
16/// without having to specify the bounds everywhere.
17pub trait ArchivedDBData: Serialize<Serializer> + Archive<Archived = Self::Repr> + Sized {
18    type Repr: Deserialize<Self, Deserializer> + Ord;
19}
20
21/// We also automatically implement this bound for everything that satisfies it.
22impl<T> ArchivedDBData for T
23where
24    T: Archive + Serialize<Serializer>,
25    Archived<T>: Deserialize<T, Deserializer> + Ord,
26{
27    type Repr = Archived<T>;
28}
29
30/// Object-safe version of the `Serialize` trait.
31pub trait SerializeDyn {
32    fn serialize(
33        &self,
34        serializer: &mut Serializer,
35    ) -> Result<usize, <Serializer as Fallible>::Error>;
36}
37
38pub trait DeserializableDyn {
39    /// Deserialize `self` from the given slice and offset.
40    ///
41    /// # Safety
42    ///
43    /// The offset must store a valid serialized value of the
44    /// concrete type that `self` points to.
45    unsafe fn deserialize_from_bytes(&mut self, bytes: &[u8], pos: usize);
46}
47
48impl<T> SerializeDyn for T
49where
50    T: ArchivedDBData,
51{
52    fn serialize(
53        &self,
54        serializer: &mut Serializer,
55    ) -> Result<usize, <Serializer as Fallible>::Error> {
56        rkyv::ser::Serializer::serialize_value(serializer, self)
57    }
58}
59impl<T> DeserializableDyn for T
60where
61    T: ArchivedDBData,
62{
63    unsafe fn deserialize_from_bytes(&mut self, bytes: &[u8], pos: usize) {
64        unsafe {
65            let archived: &<Self as Archive>::Archived = archived_value::<Self>(bytes, pos);
66
67            *self = archived
68                .deserialize(&mut SharedDeserializeMap::new())
69                .unwrap();
70        }
71    }
72}
73
74/// Object-safe version of the `Deserialize` trait.
75pub trait DeserializeDyn<Trait: ?Sized>: AsAny + Comparable {
76    fn deserialize(&self, target: &mut Trait);
77
78    fn eq_target(&self, target: &Trait) -> bool;
79    fn cmp_target(&self, target: &Trait) -> Option<Ordering>;
80}
81
82#[repr(transparent)]
83pub struct DeserializeImpl<T: Archive, Trait: ?Sized> {
84    pub archived: T::Archived,
85    phantom: PhantomData<fn(T, Box<Trait>)>,
86}
87
88impl<T: Archive, Trait: ?Sized> AsRef<T::Archived> for DeserializeImpl<T, Trait> {
89    fn as_ref(&self) -> &T::Archived {
90        &self.archived
91    }
92}
93
94impl<T: Archive, Trait: ?Sized> DeserializeImpl<T, Trait> {
95    pub fn new(archived: &T::Archived) -> &Self {
96        unsafe { transmute(archived) }
97    }
98}
99
100impl<T, Trait> PartialEq for DeserializeImpl<T, Trait>
101where
102    T: Archive,
103    T::Archived: PartialEq,
104    Trait: ?Sized,
105{
106    fn eq(&self, other: &Self) -> bool {
107        self.archived.eq(&other.archived)
108    }
109}
110
111impl<T, Trait> Eq for DeserializeImpl<T, Trait>
112where
113    T: Archive,
114    T::Archived: Eq,
115    Trait: ?Sized,
116{
117}
118
119impl<T, Trait> PartialOrd for DeserializeImpl<T, Trait>
120where
121    T: Archive,
122    T::Archived: PartialOrd,
123    Trait: ?Sized,
124{
125    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
126        self.archived.partial_cmp(&other.archived)
127    }
128}
129
130impl<T, Trait> Ord for DeserializeImpl<T, Trait>
131where
132    T: Archive,
133    T::Archived: Ord,
134    Trait: ?Sized,
135{
136    fn cmp(&self, other: &Self) -> Ordering {
137        self.archived.cmp(&other.archived)
138    }
139}
140
141impl<T, Trait> DeserializeDyn<Trait> for DeserializeImpl<T, Trait>
142where
143    T: ArchivedDBData + Eq + Ord + 'static,
144    Trait: DowncastTrait + ?Sized + 'static,
145{
146    fn deserialize(&self, target: &mut Trait) {
147        *unsafe { target.downcast_mut::<T>() } = self
148            .archived
149            .deserialize(&mut SharedDeserializeMap::new())
150            .unwrap()
151    }
152
153    fn eq_target(&self, other: &Trait) -> bool {
154        self.archived
155            .deserialize(&mut SharedDeserializeMap::new())
156            .unwrap()
157            .eq(unsafe { other.downcast::<T>() })
158    }
159
160    fn cmp_target(&self, other: &Trait) -> Option<Ordering> {
161        self.archived
162            .deserialize(&mut SharedDeserializeMap::new())
163            .unwrap()
164            .partial_cmp(unsafe { other.downcast::<T>() })
165    }
166}
167
168/// Trait for trait objects that can be deserialized into a trait object of
169/// type `TargetTrait`.
170pub trait DeserializeTrait<TargetTrait: ?Sized>:
171    DeserializeDyn<TargetTrait> + DowncastTrait + Eq + Ord
172{
173}
174
175impl<Trait, TargetTrait: ?Sized> DeserializeTrait<TargetTrait> for Trait where
176    Trait: DeserializeDyn<TargetTrait> + DowncastTrait + Eq + Ord + ?Sized
177{
178}
179
180pub type DynDeserialize<Trait> = dyn DeserializeDyn<Trait>;
181
182derive_comparison_traits!(DynDeserialize<Trait> where Trait: DowncastTrait + ?Sized + 'static);
183
184impl<Trait: ?Sized + 'static> DowncastTrait for DynDeserialize<Trait> {}
185
186/// Trait for trait objects that can be serialized and deserialized with `rkyv`.
187pub trait ArchiveTrait: SerializeDyn {
188    type Archived: DeserializeTrait<Self> + ?Sized;
189}