use crate::{
DBData,
dynamic::{ArchiveTrait, erase::Erase},
};
use rkyv::archived_value;
use std::{marker::PhantomData, mem};
pub trait Factory<Trait: ArchiveTrait + ?Sized>: Send + Sync {
fn size_of(&self) -> usize;
fn is_zst(&self) -> bool {
self.size_of() == 0
}
fn default_box(&self) -> Box<Trait>;
fn with(&self, f: &mut dyn FnMut(&mut Trait));
unsafe fn archived_value<'a>(&self, bytes: &'a [u8], pos: usize) -> &'a Trait::Archived;
}
struct FactoryImpl<T, Trait: ?Sized> {
phantom: PhantomData<fn(&T, &Trait)>,
}
pub trait WithFactory<T>: 'static {
const FACTORY: &'static dyn Factory<Self>;
}
impl<T, Trait> Factory<Trait> for FactoryImpl<T, Trait>
where
T: DBData + Erase<Trait> + 'static,
Trait: ArchiveTrait + ?Sized,
{
fn default_box(&self) -> Box<Trait> {
Box::<T>::default().erase_box()
}
fn size_of(&self) -> usize {
mem::size_of::<T>()
}
fn with(&self, f: &mut dyn FnMut(&mut Trait)) {
f(T::default().erase_mut())
}
unsafe fn archived_value<'a>(&self, bytes: &'a [u8], pos: usize) -> &'a Trait::Archived {
unsafe {
let archived: &T::Archived = archived_value::<T>(bytes, pos);
<T as Erase<Trait>>::erase_archived(archived)
}
}
}
impl<T, Trait> WithFactory<T> for Trait
where
Trait: ArchiveTrait + ?Sized + 'static,
T: DBData + Erase<Trait>,
{
const FACTORY: &'static dyn Factory<Self> = &FactoryImpl::<T, Self> {
phantom: PhantomData,
};
}