Trait rkyv::ArchiveUnsized [−][src]
A counterpart of Archive
that’s suitable for unsized types.
Instead of archiving its value directly, ArchiveUnsized
archives a RelPtr
to its archived
type. As a consequence, its resolver must be usize
.
ArchiveUnsized
is automatically implemented for all types that implement Archive
.
ArchiveUnsized
is already implemented for slices and string slices, and the rkyv_dyn
crate
can be used to archive trait objects. Other unsized types must manually implement
ArchiveUnsized
.
Examples
use core::{ mem, ops::{Deref, DerefMut}, }; use ptr_meta::Pointee; use rkyv::{ archived_unsized_value, offset_of, ser::{serializers::WriteSerializer, Serializer}, AlignedVec, Archive, Archived, ArchivedMetadata, ArchivedUsize, ArchivePointee, ArchiveUnsized, RelPtr, Serialize, SerializeUnsized, }; // We're going to be dealing mostly with blocks that have a trailing slice pub struct Block<H, T: ?Sized> { head: H, tail: T, } impl<H, T> Pointee for Block<H, [T]> { type Metadata = usize; } // For blocks with trailing slices, we need to store the length of the slice in the metadata. pub struct BlockSliceMetadata { len: ArchivedUsize, } // ArchivePointee is automatically derived for sized types because pointers to sized types don't // need to store any extra information. Because we're making an unsized block, we need to define // what metadata gets stored with our data pointer. impl<H, T> ArchivePointee for Block<H, [T]> { // This is the extra data that needs to get stored for blocks with trailing slices type ArchivedMetadata = BlockSliceMetadata; // We need to be able to turn our archived metadata into regular metadata for our type fn pointer_metadata(archived: &Self::ArchivedMetadata) -> <Self as Pointee>::Metadata { archived.len as usize } } // We're implementing ArchiveUnsized for just Block<H, [T]>. We can still implement Archive for // blocks with sized tails and they won't conflict. impl<H: Archive, T: Archive> ArchiveUnsized for Block<H, [T]> { // We'll reuse our block type as our archived type. type Archived = Block<Archived<H>, [Archived<T>]>; // This is where we'd put any resolve data for our metadata. // Most of the time, this can just be () because most metadata is Copy, but the option is // there if you need it. type MetadataResolver = (); // Here's where we make the metadata for our pointer. // This also gets the position and resolver for the metadata, but we don't need it in this // case. fn resolve_metadata( &self, _: usize, _: Self::MetadataResolver ) -> ArchivedMetadata<Self> { BlockSliceMetadata { len: self.tail.len() as ArchivedUsize, } } } // The bounds we use on our serializer type indicate that we need basic serializer capabilities, // and then whatever capabilities our head and tail types need to serialize themselves. impl<H: Serialize<S>, T: Serialize<S>, S: Serializer + ?Sized> SerializeUnsized<S> for Block<H, [T]> { // This is where we construct our unsized type in the serializer fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> { // First, we archive the head and all the tails. This will make sure that when we // finally build our block, we don't accidentally mess up the structure with serialized // dependencies. let head_resolver = self.head.serialize(serializer)?; let mut tail_resolvers = Vec::new(); for tail in self.tail.iter() { tail_resolvers.push(tail.serialize(serializer)?); } // Now we align our serializer for our archived type and write it. // We can't align for unsized types so we treat the trailing slice like an array of 0 // length for now. serializer.align_for::<Block<Archived<H>, [Archived<T>; 0]>>()?; let result = unsafe { serializer.resolve_aligned(&self.head, head_resolver)? }; serializer.align_for::<Archived<T>>()?; for (tail, tail_resolver) in self.tail.iter().zip(tail_resolvers.drain(..)) { unsafe { serializer.resolve_aligned(tail, tail_resolver)?; } } Ok(result) } // This is where we serialize the metadata for our type. In this case, we do all the work in // resolve and don't need to do anything here. fn serialize_metadata(&self, serializer: &mut S) -> Result<Self::MetadataResolver, S::Error> { Ok(()) } } let value = Block { head: "Numbers 1-4".to_string(), tail: [1, 2, 3, 4], }; // We have a Block<String, [i32; 4]> but we want to it to be a Block<String, [i32]>, so we need // to do more pointer transmutation let ptr = (&value as *const Block<String, [i32; 4]>).cast::<()>(); let unsized_value = unsafe { &*mem::transmute::<(*const (), usize), *const Block<String, [i32]>>((ptr, 4)) }; let mut serializer = WriteSerializer::new(AlignedVec::new()); let pos = serializer.serialize_unsized_value(unsized_value) .expect("failed to archive block"); let buf = serializer.into_inner(); let archived_ref = unsafe { archived_unsized_value::<Block<String, [i32]>>(buf.as_slice(), pos) }; assert_eq!(archived_ref.head, "Numbers 1-4"); assert_eq!(archived_ref.tail.len(), 4); assert_eq!(archived_ref.tail, [1, 2, 3, 4]);
Associated Types
type Archived: ArchivePointee + ?Sized
[src]
The archived counterpart of this type. Unlike Archive
, it may be unsized.
type MetadataResolver
[src]
The resolver for the metadata of this type.
Required methods
fn resolve_metadata(
&self,
pos: usize,
resolver: Self::MetadataResolver
) -> ArchivedMetadata<Self>
[src]
&self,
pos: usize,
resolver: Self::MetadataResolver
) -> ArchivedMetadata<Self>
Creates the archived version of the metadata for this value at the given position.
Provided methods
unsafe fn resolve_unsized(
&self,
from: usize,
to: usize,
resolver: Self::MetadataResolver
) -> RelPtr<Self::Archived>
[src]
&self,
from: usize,
to: usize,
resolver: Self::MetadataResolver
) -> RelPtr<Self::Archived>
Resolves a relative pointer to this value with the given from
and to
.
Safety
The caller must guarantee that to
is the location of an archived value and resolver
is
the metadata resolver for that value.
Implementations on Foreign Types
impl<T: Archive> ArchiveUnsized for [T]
[src]
type Archived = [T::Archived]
type MetadataResolver = ()
fn resolve_metadata(
&self,
_: usize,
_: Self::MetadataResolver
) -> ArchivedMetadata<Self>
[src]
&self,
_: usize,
_: Self::MetadataResolver
) -> ArchivedMetadata<Self>
impl ArchiveUnsized for str
[src]
type Archived = str
type MetadataResolver = ()
fn resolve_metadata(
&self,
_: usize,
_: Self::MetadataResolver
) -> ArchivedMetadata<Self>
[src]
&self,
_: usize,
_: Self::MetadataResolver
) -> ArchivedMetadata<Self>
Implementors
impl<T: Archive> ArchiveUnsized for T
[src]
type Archived = T::Archived
type MetadataResolver = ()
fn resolve_metadata(
&self,
_: usize,
_: Self::MetadataResolver
) -> ArchivedMetadata<Self>
[src]
&self,
_: usize,
_: Self::MetadataResolver
) -> ArchivedMetadata<Self>