use crate::SizeMeasurable;
use rkyv::api::high::HighValidator;
use rkyv::bytecheck::CheckBytes;
use rkyv::de::Pool;
use rkyv::rancor::Strategy;
use rkyv::ser::allocator::ArenaHandle;
use rkyv::ser::sharing::Share;
use rkyv::ser::Serializer;
use rkyv::util::AlignedVec;
use rkyv::{Archive, Deserialize, Serialize};
pub trait Persistable {
fn as_bytes(&self) -> impl AsRef<[u8]> + Send;
fn from_bytes(bytes: &[u8], version: u32) -> Self;
}
#[inline]
pub fn access_archived<A>(bytes: &[u8]) -> Result<&A, rkyv::rancor::Error>
where
A: rkyv::Portable + for<'a> CheckBytes<HighValidator<'a, rkyv::rancor::Error>>,
{
#[cfg(feature = "validate-reads")]
{
rkyv::access::<A, rkyv::rancor::Error>(bytes)
}
#[cfg(not(feature = "validate-reads"))]
{
Ok(unsafe { rkyv::access_unchecked::<A>(bytes) })
}
}
pub(crate) fn checked<T>(bytes: &[u8]) -> T
where
T: Archive,
<T as Archive>::Archived: rkyv::Portable
+ for<'a> CheckBytes<HighValidator<'a, rkyv::rancor::Error>>
+ Deserialize<T, Strategy<Pool, rkyv::rancor::Error>>,
{
let archived = access_archived::<<T as Archive>::Archived>(bytes)
.expect("torn or corrupt page: the archived bytes fail validation");
rkyv::deserialize::<_, rkyv::rancor::Error>(archived)
.expect("validated archive failed to deserialize")
}
impl<T> Persistable for Vec<T>
where
T: Archive
+ for<'a> Serialize<
Strategy<Serializer<AlignedVec, ArenaHandle<'a>, Share>, rkyv::rancor::Error>,
> + Default
+ SizeMeasurable
+ Clone,
<T as Archive>::Archived: Deserialize<T, Strategy<Pool, rkyv::rancor::Error>>
+ for<'a> CheckBytes<HighValidator<'a, rkyv::rancor::Error>>,
{
fn as_bytes(&self) -> impl AsRef<[u8]> {
rkyv::to_bytes::<rkyv::rancor::Error>(self).unwrap()
}
fn from_bytes(bytes: &[u8], _version: u32) -> Self {
checked::<Self>(bytes)
}
}
impl Persistable for u8 {
fn as_bytes(&self) -> impl AsRef<[u8]> {
rkyv::to_bytes::<rkyv::rancor::Error>(self).unwrap()
}
fn from_bytes(bytes: &[u8], _version: u32) -> Self {
checked::<Self>(bytes)
}
}
impl Persistable for String {
fn as_bytes(&self) -> impl AsRef<[u8]> {
rkyv::to_bytes::<rkyv::rancor::Error>(self).unwrap()
}
fn from_bytes(bytes: &[u8], _version: u32) -> Self {
checked::<Self>(bytes)
}
}