Skip to content

Commit

Permalink
Add from_raw_parts-sytle interfaces to RelPtr and ArchivedBox
Browse files Browse the repository at this point in the history
  • Loading branch information
fu5ha committed Oct 12, 2022
1 parent 0bb6445 commit 8e558b3
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 2 deletions.
53 changes: 51 additions & 2 deletions rkyv/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,25 @@ impl<T: ArchivePointee + ?Sized> ArchivedBox<T> {
})
}

/// Resolves an archived box from a [`BoxResolver`] which contains
/// the raw [`<T as ArchivePointee>::ArchivedMetadata`] directly.
///
/// # Safety
///
/// - `pos` must be the position of `out` within the archive
/// - `resolver` must be obtained by following the safety documentation of
/// [`BoxResolver::from_raw_parts`].
///
/// [`<T as ArchivePointee>::ArchivedMetadata`]: ArchivePointee::ArchivedMetadata
pub unsafe fn resolve_from_raw_parts(
pos: usize,
resolver: BoxResolver<<T as ArchivePointee>::ArchivedMetadata>,
out: *mut Self,
) {
let (fp, fo) = out_field!(out.0);
RelPtr::resolve_emplace_from_raw_parts(pos + fp, resolver.pos, resolver.metadata_resolver, fo);
}

#[doc(hidden)]
#[inline]
pub fn is_null(&self) -> bool {
Expand Down Expand Up @@ -190,9 +209,39 @@ impl<T: ArchivePointee + ?Sized> fmt::Pointer for ArchivedBox<T> {
}

/// The resolver for `Box`.
pub struct BoxResolver<T> {
pub struct BoxResolver<M> {
pos: usize,
metadata_resolver: T,
metadata_resolver: M,
}

impl<M> BoxResolver<M> {
/// Createa a new [`BoxResolver<M>`] from raw parts. Note that `M` here is ***not*** the same
/// `T` which should be serialized/contained in the resulting [`ArchivedBox<T>`], and is rather
/// a type that can be used to resolve any needed [`ArchivePointee::ArchivedMetadata`]
/// for the serialized pointed-to value.
///
/// In most cases, you won't need to create a [`BoxResolver`] yourself and can instead obtain it through
/// [`ArchivedBox::serialize_from_ref`] or [`ArchivedBox::serialize_copy_from_slice`].
///
/// # Safety
///
/// Constructing a valid resolver is quite fraught. Please make sure you understand what the implications are before doing it.
///
/// - `pos`: You must ensure that you serialized and resolved (i.e. [`Serializer::serialize_value`])
/// a `T` which will be pointed to by the final [`ArchivedBox<T>`] that this resolver will help resolve
/// at the given `pos` within the archive.
///
/// - `metadata_resolver`: You must also ensure that the given `metadata_resolver` can be used to successfully produce
/// valid [`<T as ArchivePointee>::ArchivedMetadata`] for that serialized `T`. This means it must either be:
/// - The necessary [`<T as ArchivePointee>::ArchivedMetadata`] itself, in which case you may use the created
/// [`BoxResolver<<T as ArchivePointee>::ArchivedMetadta>`] as a resolver in [`ArchivedBox::resolve_from_raw_parts`]
/// - An [`ArchiveUnsized::MetadataResolver`] obtained from some `value: &U` where `U: ArchiveUnsized<Archived = T>`, in which case you
/// must pass that same `value: &U` into [`ArchivedBox::resolve_from_ref`] along with this [`BoxResolver`].
///
/// [`<T as ArchivePointee>::ArchivedMetadata`]: ArchivePointee::ArchivedMetadata
pub unsafe fn from_raw_parts(pos: usize, metadata_resolver: M) -> Self {
Self { pos, metadata_resolver }
}
}

#[cfg(feature = "validation")]
Expand Down
59 changes: 59 additions & 0 deletions rkyv/src/rel_ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,65 @@ impl<T: ArchivePointee + ?Sized, O: Offset> RelPtr<T, O> {
Self::try_resolve_emplace(from, to, value, metadata_resolver, out).unwrap();
}

/// Attempts to create a relative pointer from one position to another given
/// raw pointer metadata.
///
/// This does the same thing as [`RelPtr::try_resolve_emplace`] but you must supply
/// the [`<T as ArchivePointee>::ArchivedMetadata`][ArchivePointee::ArchivedMetadata]
/// yourself directly rather than through an implementation of [`ArchiveUnsized`] on some
/// value.
///
/// # Safety
///
/// - `from` must be the position of `out` within the archive
/// - `to` must be the position of some valid `T`
/// - `value` must be the value being serialized
/// - `archived_metadata` must produce valid metadata for the pointee of the resulting
/// `RelPtr` (the thing being pointed at) when [`<T as ArchivePointee>::pointer_metadata(archived_metadata)`][ArchivePointee::pointer_metadata]
/// is called.
pub unsafe fn try_resolve_emplace_from_raw_parts(
from: usize,
to: usize,
archived_metadata: <T as ArchivePointee>::ArchivedMetadata,
out: *mut Self,
) -> Result<(), OffsetError> {
let (fp, fo) = out_field!(out.raw_ptr);
RawRelPtr::try_emplace(from + fp, to, fo)?;
let (_fp, fo) = out_field!(out.metadata);
*fo = archived_metadata;
Ok(())
}

/// Creates a relative pointer from one position to another given
/// raw pointer metadata.
///
/// This does the same thing as [`RelPtr::resolve_emplace`] but you must supply
/// the [`<T as ArchivePointee>::ArchivedMetadata`][ArchivePointee::ArchivedMetadata]
/// yourself directly rather than through an implementation of [`ArchiveUnsized`] on some
/// value.
///
/// # Panics
///
/// - The offset between `from` and `to` does not fit in an `isize`
/// - The offset between `from` and `to` exceeds the offset storage
///
/// # Safety
///
/// - `from` must be the position of `out` within the archive
/// - `to` must be the position of some valid `T`
/// - `value` must be the value being serialized
/// - `archived_metadata` must produce valid metadata for the pointee of the resulting
/// `RelPtr` (the thing being pointed at) when [`<T as ArchivePointee>::pointer_metadata(archived_metadata)`][ArchivePointee::pointer_metadata]
/// is called.
pub unsafe fn resolve_emplace_from_raw_parts(
from: usize,
to: usize,
archived_metadata: <T as ArchivePointee>::ArchivedMetadata,
out: *mut Self,
) {
Self::try_resolve_emplace_from_raw_parts(from, to, archived_metadata, out).unwrap();
}

/// Gets the base pointer for the relative pointer.
#[inline]
pub fn base(&self) -> *const u8 {
Expand Down

0 comments on commit 8e558b3

Please sign in to comment.