use crate::{
DBData,
dynamic::{DataTrait, DowncastTrait, Erase, SerializeDyn},
trace::DbspSerializer,
};
use rkyv::{Archive, Fallible, Serialize, archived_value, with::Inline};
use std::{marker::PhantomData, mem::transmute};
pub trait Item<'a, K, A>: SerializeDyn
where
K: DataTrait + ?Sized,
A: DataTrait + ?Sized,
{
#[allow(clippy::wrong_self_convention)]
fn from_refs(&mut self, key: &'a K, aux: &'a A);
}
pub trait ArchivedItem<'a, K, A>: 'a
where
K: DataTrait + ?Sized,
A: DataTrait + ?Sized,
{
fn fst(&self) -> &K::Archived;
fn snd(&self) -> &A::Archived;
fn split(&self) -> (&K::Archived, &A::Archived);
fn equal(&self, other: &dyn ArchivedItem<'a, K, A>) -> bool;
}
impl<K, A> PartialEq for dyn ArchivedItem<'_, K, A>
where
K: DataTrait + ?Sized,
A: DataTrait + ?Sized,
{
fn eq(&self, other: &Self) -> bool {
self.equal(other)
}
}
impl<K, A> Eq for dyn ArchivedItem<'_, K, A>
where
K: DataTrait + ?Sized,
A: DataTrait + ?Sized,
{
}
pub trait ItemFactory<K, A>: Send + Sync
where
K: DataTrait + ?Sized,
A: DataTrait + ?Sized,
{
fn new_pair<'a>(&self, key: &'a K, aux: &'a A) -> Box<dyn Item<'a, K, A> + 'a>;
fn with<'a>(&self, key: &'a K, aux: &'a A, f: &mut dyn FnMut(&dyn Item<'a, K, A>));
unsafe fn archived_value<'a>(
&self,
bytes: &'a [u8],
pos: usize,
) -> &'a dyn ArchivedItem<'a, K, A>;
}
#[derive(Archive, Serialize)]
pub struct RefTup2<'a, K, A>(#[with(Inline)] pub &'a K, #[with(Inline)] pub &'a A)
where
K: DBData,
A: DBData;
impl<K, A> SerializeDyn for RefTup2<'_, K, A>
where
K: DBData,
A: DBData,
{
fn serialize(
&self,
serializer: &mut DbspSerializer,
) -> Result<usize, <DbspSerializer<'_> as Fallible>::Error> {
rkyv::ser::Serializer::serialize_value(serializer, self)
}
}
impl<'a, K, A, KTrait, ATrait> Item<'a, KTrait, ATrait> for RefTup2<'a, K, A>
where
K: DBData + Erase<KTrait>,
A: DBData + Erase<ATrait>,
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
{
fn from_refs(&mut self, key: &'a KTrait, aux: &'a ATrait) {
self.0 = unsafe { key.downcast::<K>() };
self.1 = unsafe { aux.downcast::<A>() };
}
}
#[repr(transparent)]
struct Tup2Deserialize<'a, K, A, KTrait, ATrait>
where
K: DBData + Erase<KTrait>,
A: DBData + Erase<ATrait>,
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
{
tup: ArchivedRefTup2<'a, K, A>,
phantom: PhantomData<fn(&KTrait, &ATrait)>,
}
impl<'a, K, A, KTrait, ATrait> Tup2Deserialize<'a, K, A, KTrait, ATrait>
where
K: DBData + Erase<KTrait>,
A: DBData + Erase<ATrait>,
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
{
fn new<'b>(tup: &'b ArchivedRefTup2<'a, K, A>) -> &'b Self {
unsafe { transmute(tup) }
}
}
impl<'a, K, A, KTrait, ATrait> ArchivedItem<'a, KTrait, ATrait>
for Tup2Deserialize<'a, K, A, KTrait, ATrait>
where
K: DBData + Erase<KTrait>,
A: DBData + Erase<ATrait>,
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
{
fn fst(&self) -> &KTrait::Archived {
<K as Erase<KTrait>>::erase_archived(&self.tup.0)
}
fn snd(&self) -> &ATrait::Archived {
<A as Erase<ATrait>>::erase_archived(&self.tup.1)
}
fn split(&self) -> (&KTrait::Archived, &ATrait::Archived) {
(
<K as Erase<KTrait>>::erase_archived(&self.tup.0),
<A as Erase<ATrait>>::erase_archived(&self.tup.1),
)
}
fn equal(&self, other: &dyn ArchivedItem<'a, KTrait, ATrait>) -> bool {
let (other_k, other_a) = other.split();
unsafe {
&self.tup.0 == other_k.downcast::<K::Archived>()
&& &self.tup.1 == other_a.downcast::<A::Archived>()
}
}
}
pub struct RefTup2Factory<K, A>
where
K: DBData,
A: DBData,
{
phantom: PhantomData<(K, A)>,
}
impl<K, A> RefTup2Factory<K, A>
where
K: DBData,
A: DBData,
{
}
unsafe impl<K, A> Send for RefTup2Factory<K, A>
where
K: DBData,
A: DBData,
{
}
unsafe impl<K, A> Sync for RefTup2Factory<K, A>
where
K: DBData,
A: DBData,
{
}
impl<K, A, KTrait, ATrait> ItemFactory<KTrait, ATrait> for RefTup2Factory<K, A>
where
K: DBData + Erase<KTrait>,
A: DBData + Erase<ATrait>,
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
{
fn new_pair<'a>(
&self,
key: &'a KTrait,
aux: &'a ATrait,
) -> Box<dyn Item<'a, KTrait, ATrait> + 'a> {
unsafe { Box::new(RefTup2(key.downcast::<K>(), aux.downcast::<A>())) }
}
fn with<'a>(
&self,
key: &'a KTrait,
aux: &'a ATrait,
f: &mut dyn FnMut(&dyn Item<'a, KTrait, ATrait>),
) {
unsafe { f(&RefTup2(key.downcast::<K>(), aux.downcast::<A>())) }
}
unsafe fn archived_value<'a>(
&self,
bytes: &'a [u8],
pos: usize,
) -> &'a dyn ArchivedItem<'a, KTrait, ATrait> {
unsafe {
let archived: &ArchivedRefTup2<'a, K, A> =
archived_value::<RefTup2<'a, K, A>>(bytes, pos);
Tup2Deserialize::new(archived)
}
}
}
pub trait WithItemFactory<KTrait, ATrait>: 'static
where
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
{
const ITEM_FACTORY: &'static dyn ItemFactory<KTrait, ATrait>;
}
impl<K, A, KTrait, ATrait> WithItemFactory<KTrait, ATrait> for RefTup2Factory<K, A>
where
KTrait: DataTrait + ?Sized,
ATrait: DataTrait + ?Sized,
K: DBData + Erase<KTrait>,
A: DBData + Erase<ATrait>,
{
const ITEM_FACTORY: &'static dyn ItemFactory<KTrait, ATrait> = &RefTup2Factory::<K, A> {
phantom: PhantomData,
};
}