Skip to content

Commit 8e558b3

Browse files
committed
Add from_raw_parts-sytle interfaces to RelPtr and ArchivedBox
1 parent 0bb6445 commit 8e558b3

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

rkyv/src/boxed.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@ impl<T: ArchivePointee + ?Sized> ArchivedBox<T> {
5858
})
5959
}
6060

61+
/// Resolves an archived box from a [`BoxResolver`] which contains
62+
/// the raw [`<T as ArchivePointee>::ArchivedMetadata`] directly.
63+
///
64+
/// # Safety
65+
///
66+
/// - `pos` must be the position of `out` within the archive
67+
/// - `resolver` must be obtained by following the safety documentation of
68+
/// [`BoxResolver::from_raw_parts`].
69+
///
70+
/// [`<T as ArchivePointee>::ArchivedMetadata`]: ArchivePointee::ArchivedMetadata
71+
pub unsafe fn resolve_from_raw_parts(
72+
pos: usize,
73+
resolver: BoxResolver<<T as ArchivePointee>::ArchivedMetadata>,
74+
out: *mut Self,
75+
) {
76+
let (fp, fo) = out_field!(out.0);
77+
RelPtr::resolve_emplace_from_raw_parts(pos + fp, resolver.pos, resolver.metadata_resolver, fo);
78+
}
79+
6180
#[doc(hidden)]
6281
#[inline]
6382
pub fn is_null(&self) -> bool {
@@ -190,9 +209,39 @@ impl<T: ArchivePointee + ?Sized> fmt::Pointer for ArchivedBox<T> {
190209
}
191210

192211
/// The resolver for `Box`.
193-
pub struct BoxResolver<T> {
212+
pub struct BoxResolver<M> {
194213
pos: usize,
195-
metadata_resolver: T,
214+
metadata_resolver: M,
215+
}
216+
217+
impl<M> BoxResolver<M> {
218+
/// Createa a new [`BoxResolver<M>`] from raw parts. Note that `M` here is ***not*** the same
219+
/// `T` which should be serialized/contained in the resulting [`ArchivedBox<T>`], and is rather
220+
/// a type that can be used to resolve any needed [`ArchivePointee::ArchivedMetadata`]
221+
/// for the serialized pointed-to value.
222+
///
223+
/// In most cases, you won't need to create a [`BoxResolver`] yourself and can instead obtain it through
224+
/// [`ArchivedBox::serialize_from_ref`] or [`ArchivedBox::serialize_copy_from_slice`].
225+
///
226+
/// # Safety
227+
///
228+
/// Constructing a valid resolver is quite fraught. Please make sure you understand what the implications are before doing it.
229+
///
230+
/// - `pos`: You must ensure that you serialized and resolved (i.e. [`Serializer::serialize_value`])
231+
/// a `T` which will be pointed to by the final [`ArchivedBox<T>`] that this resolver will help resolve
232+
/// at the given `pos` within the archive.
233+
///
234+
/// - `metadata_resolver`: You must also ensure that the given `metadata_resolver` can be used to successfully produce
235+
/// valid [`<T as ArchivePointee>::ArchivedMetadata`] for that serialized `T`. This means it must either be:
236+
/// - The necessary [`<T as ArchivePointee>::ArchivedMetadata`] itself, in which case you may use the created
237+
/// [`BoxResolver<<T as ArchivePointee>::ArchivedMetadta>`] as a resolver in [`ArchivedBox::resolve_from_raw_parts`]
238+
/// - An [`ArchiveUnsized::MetadataResolver`] obtained from some `value: &U` where `U: ArchiveUnsized<Archived = T>`, in which case you
239+
/// must pass that same `value: &U` into [`ArchivedBox::resolve_from_ref`] along with this [`BoxResolver`].
240+
///
241+
/// [`<T as ArchivePointee>::ArchivedMetadata`]: ArchivePointee::ArchivedMetadata
242+
pub unsafe fn from_raw_parts(pos: usize, metadata_resolver: M) -> Self {
243+
Self { pos, metadata_resolver }
244+
}
196245
}
197246

198247
#[cfg(feature = "validation")]

rkyv/src/rel_ptr/mod.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,65 @@ impl<T: ArchivePointee + ?Sized, O: Offset> RelPtr<T, O> {
383383
Self::try_resolve_emplace(from, to, value, metadata_resolver, out).unwrap();
384384
}
385385

386+
/// Attempts to create a relative pointer from one position to another given
387+
/// raw pointer metadata.
388+
///
389+
/// This does the same thing as [`RelPtr::try_resolve_emplace`] but you must supply
390+
/// the [`<T as ArchivePointee>::ArchivedMetadata`][ArchivePointee::ArchivedMetadata]
391+
/// yourself directly rather than through an implementation of [`ArchiveUnsized`] on some
392+
/// value.
393+
///
394+
/// # Safety
395+
///
396+
/// - `from` must be the position of `out` within the archive
397+
/// - `to` must be the position of some valid `T`
398+
/// - `value` must be the value being serialized
399+
/// - `archived_metadata` must produce valid metadata for the pointee of the resulting
400+
/// `RelPtr` (the thing being pointed at) when [`<T as ArchivePointee>::pointer_metadata(archived_metadata)`][ArchivePointee::pointer_metadata]
401+
/// is called.
402+
pub unsafe fn try_resolve_emplace_from_raw_parts(
403+
from: usize,
404+
to: usize,
405+
archived_metadata: <T as ArchivePointee>::ArchivedMetadata,
406+
out: *mut Self,
407+
) -> Result<(), OffsetError> {
408+
let (fp, fo) = out_field!(out.raw_ptr);
409+
RawRelPtr::try_emplace(from + fp, to, fo)?;
410+
let (_fp, fo) = out_field!(out.metadata);
411+
*fo = archived_metadata;
412+
Ok(())
413+
}
414+
415+
/// Creates a relative pointer from one position to another given
416+
/// raw pointer metadata.
417+
///
418+
/// This does the same thing as [`RelPtr::resolve_emplace`] but you must supply
419+
/// the [`<T as ArchivePointee>::ArchivedMetadata`][ArchivePointee::ArchivedMetadata]
420+
/// yourself directly rather than through an implementation of [`ArchiveUnsized`] on some
421+
/// value.
422+
///
423+
/// # Panics
424+
///
425+
/// - The offset between `from` and `to` does not fit in an `isize`
426+
/// - The offset between `from` and `to` exceeds the offset storage
427+
///
428+
/// # Safety
429+
///
430+
/// - `from` must be the position of `out` within the archive
431+
/// - `to` must be the position of some valid `T`
432+
/// - `value` must be the value being serialized
433+
/// - `archived_metadata` must produce valid metadata for the pointee of the resulting
434+
/// `RelPtr` (the thing being pointed at) when [`<T as ArchivePointee>::pointer_metadata(archived_metadata)`][ArchivePointee::pointer_metadata]
435+
/// is called.
436+
pub unsafe fn resolve_emplace_from_raw_parts(
437+
from: usize,
438+
to: usize,
439+
archived_metadata: <T as ArchivePointee>::ArchivedMetadata,
440+
out: *mut Self,
441+
) {
442+
Self::try_resolve_emplace_from_raw_parts(from, to, archived_metadata, out).unwrap();
443+
}
444+
386445
/// Gets the base pointer for the relative pointer.
387446
#[inline]
388447
pub fn base(&self) -> *const u8 {

0 commit comments

Comments
 (0)