use core::{fmt, marker::PhantomData, ops::Deref};
use rkyv::{
api::high::HighValidator, bytecheck::CheckBytes, rancor::Source,
seal::Seal, util::AlignedVec, Portable,
};
#[derive(Default)]
pub struct OwnedArchive<T, C> {
container: C,
_type: PhantomData<T>,
}
impl<T, C> OwnedArchive<T, C> {
pub fn new<E>(container: C) -> Result<Self, E>
where
T: Portable + for<'a> CheckBytes<HighValidator<'a, E>>,
E: Source,
C: StableBytes,
{
rkyv::access::<T, E>(container.bytes())?;
Ok(Self {
container,
_type: PhantomData,
})
}
pub fn get_mut(&mut self) -> Seal<'_, T>
where
T: Portable,
C: StableBytesMut,
{
unsafe { rkyv::access_unchecked_mut::<T>(self.container.bytes_mut()) }
}
}
impl<T: Portable, C: StableBytes> Deref for OwnedArchive<T, C> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { rkyv::access_unchecked(self.container.bytes()) }
}
}
impl<T, C: Clone> Clone for OwnedArchive<T, C> {
fn clone(&self) -> Self {
Self {
container: self.container.clone(),
_type: self._type,
}
}
}
impl<T: Portable, C: StableBytes> fmt::Debug for OwnedArchive<T, C>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
T::fmt(&**self, f)
}
}
pub unsafe trait StableBytes {
fn bytes(&self) -> &[u8];
}
pub unsafe trait StableBytesMut: StableBytes {
fn bytes_mut(&mut self) -> &mut [u8];
}
unsafe impl<T: StableBytes> StableBytes for &T {
fn bytes(&self) -> &[u8] {
T::bytes(self)
}
}
unsafe impl<T: StableBytes> StableBytes for &mut T {
fn bytes(&self) -> &[u8] {
T::bytes(self)
}
}
unsafe impl<T: StableBytesMut> StableBytesMut for &mut T {
fn bytes_mut(&mut self) -> &mut [u8] {
T::bytes_mut(self)
}
}
unsafe impl StableBytes for [u8] {
fn bytes(&self) -> &[u8] {
self
}
}
unsafe impl StableBytesMut for [u8] {
fn bytes_mut(&mut self) -> &mut [u8] {
self
}
}
unsafe impl StableBytes for AlignedVec {
fn bytes(&self) -> &[u8] {
self.as_ref()
}
}
unsafe impl StableBytesMut for AlignedVec {
fn bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}
unsafe impl StableBytes for Vec<u8> {
fn bytes(&self) -> &[u8] {
self.as_ref()
}
}
unsafe impl StableBytesMut for Vec<u8> {
fn bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}
unsafe impl StableBytes for Box<[u8]> {
fn bytes(&self) -> &[u8] {
self.as_ref()
}
}
unsafe impl StableBytesMut for Box<[u8]> {
fn bytes_mut(&mut self) -> &mut [u8] {
self.as_mut()
}
}
#[cfg(test)]
mod tests {
use rkyv::{munge::munge, rancor, Archive, Deserialize, Serialize};
use super::OwnedArchive;
#[derive(Archive, Clone, PartialEq, Deserialize, Serialize, Debug)]
#[rkyv(compare(PartialEq), derive(Debug))]
pub struct Foo {
hello: u8,
world: u64,
}
#[test]
fn test_owned_archive_vec() {
let stub = Foo { hello: 4, world: 5 };
let bytes = rkyv::to_bytes::<rancor::Error>(&stub).unwrap();
let owned = OwnedArchive::<ArchivedFoo, _>::new::<rancor::Error>(bytes)
.unwrap();
assert_eq!(owned.hello, 4);
assert_eq!(owned.world, 5);
assert_eq!(stub, *owned);
}
#[test]
fn test_owned_archive_vec_mut() {
let stub = Foo { hello: 4, world: 5 };
let bytes = rkyv::to_bytes::<rancor::Error>(&stub).unwrap();
let mut owned =
OwnedArchive::<ArchivedFoo, _>::new::<rancor::Error>(bytes)
.unwrap();
assert_eq!(stub, *owned);
munge!(let ArchivedFoo { mut hello, ..} = owned.get_mut());
assert_eq!(*hello, 4);
*hello = 9;
assert_eq!(owned.hello, 9);
}
}