rkyv/
rel_ptr.rs

1//! Relative pointer implementations and options.
2
3use core::{
4    error::Error,
5    fmt,
6    marker::{PhantomData, PhantomPinned},
7    ptr::addr_of_mut,
8};
9
10use munge::munge;
11use rancor::{fail, Panic, ResultExt as _, Source};
12
13use crate::{
14    primitive::{
15        ArchivedI16, ArchivedI32, ArchivedI64, ArchivedU16, ArchivedU32,
16        ArchivedU64,
17    },
18    seal::Seal,
19    traits::{ArchivePointee, NoUndef},
20    Place, Portable,
21};
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24struct IsizeOverflow;
25
26impl fmt::Display for IsizeOverflow {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        write!(f, "the offset overflowed the range of `isize`")
29    }
30}
31
32impl Error for IsizeOverflow {}
33
34/// A offset that can be used with [`RawRelPtr`].
35pub trait Offset: Copy + NoUndef {
36    /// Creates a new offset between a `from` position and a `to` position.
37    fn from_isize<E: Source>(value: isize) -> Result<Self, E>;
38
39    /// Gets the offset as an `isize`.
40    fn to_isize(self) -> isize;
41}
42
43macro_rules! impl_offset_single_byte {
44    ($ty:ty) => {
45        impl Offset for $ty {
46            fn from_isize<E: Source>(value: isize) -> Result<Self, E> {
47                // `pointer::add`` and `pointer::offset` require that the
48                // computed offsets cannot overflow an isize, which is why we're
49                // using signed_offset instead of `checked_sub` for unsized
50                // types.
51                Self::try_from(value).into_error()
52            }
53
54            #[inline]
55            fn to_isize(self) -> isize {
56                // We're guaranteed that our offset will not exceed the
57                // capacity of an `isize`
58                self as isize
59            }
60        }
61    };
62}
63
64impl_offset_single_byte!(i8);
65impl_offset_single_byte!(u8);
66
67macro_rules! impl_offset_multi_byte {
68    ($ty:ty, $archived:ty) => {
69        impl Offset for $archived {
70            fn from_isize<E: Source>(value: isize) -> Result<Self, E> {
71                // `pointer::add`` and `pointer::offset` require that the
72                // computed offsets cannot overflow an isize, which is why we're
73                // using signed_offset instead of `checked_sub` for unsized
74                // types.
75                Ok(<$archived>::from_native(
76                    <$ty>::try_from(value).into_error()?,
77                ))
78            }
79
80            #[inline]
81            fn to_isize(self) -> isize {
82                // We're guaranteed that our offset will not exceed the
83                // capacity of an `isize`.
84                self.to_native() as isize
85            }
86        }
87    };
88}
89
90impl_offset_multi_byte!(i16, ArchivedI16);
91impl_offset_multi_byte!(i32, ArchivedI32);
92impl_offset_multi_byte!(i64, ArchivedI64);
93
94impl_offset_multi_byte!(u16, ArchivedU16);
95impl_offset_multi_byte!(u32, ArchivedU32);
96impl_offset_multi_byte!(u64, ArchivedU64);
97
98/// An untyped pointer which resolves relative to its position in memory.
99///
100/// This is the most fundamental building block in rkyv. It allows the
101/// construction and use of pointers that can be safely relocated as long as the
102/// source and target are moved together. This is what allows memory to be moved
103/// from disk into memory and accessed without decoding.
104///
105/// Regular pointers are *absolute*, meaning that the pointer can be moved
106/// without being invalidated. However, the pointee **cannot** be moved,
107/// otherwise the pointer is invalidated.
108///
109/// Relative pointers are *relative*, meaning that the **pointer** can be moved
110/// with the **pointee** without invalidating the pointer. However, if either
111/// the **pointer** or the **pointee** move independently, the pointer will be
112/// invalidated.
113#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
114#[derive(Portable)]
115#[rkyv(crate)]
116#[repr(transparent)]
117pub struct RawRelPtr<O> {
118    offset: O,
119    _phantom: PhantomPinned,
120}
121
122/// Calculates the offset between two positions as an `isize`.
123///
124/// This function exists solely to get the distance between two `usizes` as an
125/// `isize` with a full range of values.
126///
127/// # Examples
128///
129/// ```
130/// # use rkyv::rel_ptr::signed_offset;
131/// # use rancor::Error;
132/// assert!(signed_offset::<Error>(0, 1).is_ok_and(|x| x == 1));
133/// assert!(signed_offset::<Error>(1, 0).is_ok_and(|x| x == -1));
134/// assert!(signed_offset::<Error>(0, isize::MAX as usize)
135///     .is_ok_and(|x| x == isize::MAX));
136/// assert!(signed_offset::<Error>(isize::MAX as usize, 0)
137///     .is_ok_and(|x| x == -isize::MAX));
138/// assert!(signed_offset::<Error>(0, isize::MAX as usize + 1).is_err());
139/// assert!(signed_offset::<Error>(isize::MAX as usize + 1, 0)
140///     .is_ok_and(|x| x == isize::MIN));
141/// assert!(signed_offset::<Error>(0, isize::MAX as usize + 2).is_err());
142/// assert!(signed_offset::<Error>(isize::MAX as usize + 2, 0).is_err());
143/// ```
144pub fn signed_offset<E: Source>(from: usize, to: usize) -> Result<isize, E> {
145    let (result, overflow) = to.overflowing_sub(from);
146    if (!overflow && result <= (isize::MAX as usize))
147        || (overflow && result >= (isize::MIN as usize))
148    {
149        Ok(result as isize)
150    } else {
151        fail!(IsizeOverflow);
152    }
153}
154
155impl<O: Offset> RawRelPtr<O> {
156    /// Attempts to create an invalid `RawRelPtr` in-place.
157    pub fn try_emplace_invalid<E: Source>(out: Place<Self>) -> Result<(), E> {
158        Self::try_emplace::<E>(out.pos() + 1, out)
159    }
160
161    /// Creates an invalid `RawRelPtr` in-place.
162    ///
163    /// # Panics
164    ///
165    /// - If an offset of `1` does not fit in an `isize`
166    /// - If an offset of `1` exceeds the offset storage
167    pub fn emplace_invalid(out: Place<Self>) {
168        Self::try_emplace_invalid::<Panic>(out).always_ok();
169    }
170
171    /// Attempts to create a new `RawRelPtr` in-place between the given `from`
172    /// and `to` positions.
173    pub fn try_emplace<E: Source>(
174        to: usize,
175        out: Place<Self>,
176    ) -> Result<(), E> {
177        let offset = O::from_isize(signed_offset(out.pos(), to)?)?;
178        munge!(let Self { offset: out_offset, _phantom: _ } = out);
179        out_offset.write(offset);
180        Ok(())
181    }
182
183    /// Creates a new `RawRelPtr` in-place between the given `from` and `to`
184    /// positions.
185    ///
186    /// # Panics
187    ///
188    /// - If the offset between `out` and `to` does not fit in an `isize`
189    /// - If the offset between `out` and `to` exceeds the offset storage
190    pub fn emplace(to: usize, out: Place<Self>) {
191        Self::try_emplace::<Panic>(to, out).always_ok()
192    }
193
194    /// Gets the base pointer for the pointed-to relative pointer.
195    pub fn base_raw(this: *mut Self) -> *mut u8 {
196        this.cast()
197    }
198
199    /// Gets the offset of the pointed-to relative pointer from its base.
200    ///
201    /// # Safety
202    ///
203    /// `this` must be non-null, properly-aligned, and point to a valid
204    /// `RawRelPtr`.
205    pub unsafe fn offset_raw(this: *mut Self) -> isize {
206        // SAFETY: The caller has guaranteed that `this` is safe to dereference
207        unsafe { addr_of_mut!((*this).offset).read().to_isize() }
208    }
209
210    /// Calculates the memory address being pointed to by the pointed-to
211    /// relative pointer.
212    ///
213    /// # Safety
214    ///
215    /// - `this` must be non-null, properly-aligned, and point to a valid
216    ///   `RawRelPtr`.
217    /// - The offset of this relative pointer, when added to its base, must be
218    ///   located in the same allocated object as it.
219    pub unsafe fn as_ptr_raw(this: *mut Self) -> *mut () {
220        // SAFETY:
221        // - The caller has guaranteed that `this` is safe to dereference.
222        // - The caller has guaranteed that offsetting the base pointer by its
223        //   offset will yield a pointer in the same allocated object.
224        unsafe { Self::base_raw(this).offset(Self::offset_raw(this)).cast() }
225    }
226
227    /// Calculates the memory address being pointed to by the pointed-to
228    /// relative pointer using wrapping methods.
229    ///
230    /// This method is a safer but potentially slower version of `as_ptr_raw`.
231    ///
232    /// # Safety
233    ///
234    /// `this` must be non-null, properly-aligned, and point to a valid
235    /// `RawRelPtr`.
236    pub unsafe fn as_ptr_wrapping_raw(this: *mut Self) -> *mut () {
237        // SAFETY: The safety requirements of `offset_raw` are the same as the
238        // safety requirements for `as_ptr_wrapping_raw`.
239        let offset = unsafe { Self::offset_raw(this) };
240        Self::base_raw(this).wrapping_offset(offset).cast()
241    }
242
243    /// Gets whether the offset of the pointed-to relative pointer is invalid.
244    ///
245    /// # Safety
246    ///
247    /// `this` must be non-null, properly-aligned, and point to a valid
248    /// `RawRelPtr`.
249    pub unsafe fn is_invalid_raw(this: *mut Self) -> bool {
250        // SAFETY: The safety requirements of `offset_raw` are the same as the
251        // safety requirements for `is_invalid_raw`.
252        unsafe { Self::offset_raw(this) == 1 }
253    }
254
255    /// Gets the base pointer for the relative pointer.
256    pub fn base(&self) -> *const u8 {
257        Self::base_raw((self as *const Self).cast_mut()).cast_const()
258    }
259
260    /// Gets the mutable base pointer for the relative pointer.
261    pub fn base_mut(this: Seal<'_, Self>) -> *mut u8 {
262        // SAFETY: The value pointed to by `this` is not moved and no bytes are
263        // written through it.
264        let this = unsafe { Seal::unseal_unchecked(this) };
265        Self::base_raw(this as *mut Self)
266    }
267
268    /// Gets the offset of the relative pointer from its base.
269    pub fn offset(&self) -> isize {
270        let this = self as *const Self;
271        // SAFETY: `self` is a reference, so it's guaranteed to be non-null,
272        // properly-aligned, and point to a valid `RawRelPtr`.
273        unsafe { Self::offset_raw(this.cast_mut()) }
274    }
275
276    /// Gets whether the offset of the relative pointer is invalid.
277    pub fn is_invalid(&self) -> bool {
278        let this = self as *const Self;
279        // SAFETY: `self` is a reference, so it's guaranteed to be non-null,
280        // properly-aligned, and point to a valid `RawRelPtr`.
281        unsafe { Self::is_invalid_raw(this.cast_mut()) }
282    }
283
284    /// Calculates the memory address being pointed to by this relative pointer.
285    ///
286    /// # Safety
287    ///
288    /// The offset of this relative pointer, when added to its base, must be
289    /// located in the same allocated object as it.
290    pub unsafe fn as_ptr(&self) -> *const () {
291        let this = self as *const Self;
292        // SAFETY:
293        // - `self` is a reference, so it's guaranteed to be non-null,
294        //   properly-aligned, and point to a valid `RawRelPtr`.
295        // - The caller has guaranteed that the offset of this relative pointer,
296        //   when added to its base, is located in the same allocated object as
297        //   it.
298        unsafe { Self::as_ptr_raw(this.cast_mut()).cast_const() }
299    }
300
301    /// Calculates the mutable memory address being pointed to by this relative
302    /// pointer.
303    ///
304    /// # Safety
305    ///
306    /// The offset of this relative pointer, when added to its base, must be
307    /// located in the same allocated object as it.
308    pub unsafe fn as_mut_ptr(this: Seal<'_, Self>) -> *mut () {
309        // SAFETY: The value pointed to by `this` is not moved and no bytes are
310        // written through it.
311        let this = unsafe { Seal::unseal_unchecked(this) };
312        // SAFETY:
313        // - `this` is a reference, so it's guaranteed to be non-null,
314        //   properly-aligned, and point to a valid `RawRelPtr`.
315        // - The caller has guaranteed that the offset of this relative pointer,
316        //   when added to its base, is located in the same allocated object as
317        //   it.
318        unsafe { Self::as_ptr_raw(this as *mut Self) }
319    }
320
321    /// Calculates the memory address being pointed to by this relative pointer
322    /// using wrapping methods.
323    ///
324    /// This method is a safer but potentially slower version of `as_ptr`.
325    pub fn as_ptr_wrapping(&self) -> *const () {
326        let this = self as *const Self;
327        // SAFETY: `self` is a reference, so it's guaranteed to be non-null,
328        // properly-aligned, and point to a valid `RawRelPtr`.
329        unsafe { Self::as_ptr_wrapping_raw(this.cast_mut()).cast_const() }
330    }
331
332    /// Calculates the mutable memory address being pointed to by this relative
333    /// pointer using wrapping methods.
334    ///
335    /// This method is a safer but potentially slower version of `as_mut_ptr`.
336    pub fn as_mut_ptr_wrapping(this: Seal<'_, Self>) -> *mut () {
337        // SAFETY: The value pointed to by `this` is not moved and no bytes are
338        // written through it.
339        let this = unsafe { Seal::unseal_unchecked(this) };
340        // SAFETY: `this` is a reference, so it's guaranteed to be non-null,
341        // properly-aligned, and point to a valid `RawRelPtr`.
342        unsafe { Self::as_ptr_wrapping_raw(this as *mut Self) }
343    }
344}
345
346impl<O: fmt::Debug> fmt::Debug for RawRelPtr<O> {
347    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348        f.debug_struct("RawRelPtr")
349            .field("offset", &self.offset)
350            .finish()
351    }
352}
353
354impl<O: Offset> fmt::Pointer for RawRelPtr<O> {
355    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356        fmt::Pointer::fmt(&self.as_ptr_wrapping(), f)
357    }
358}
359
360/// A raw relative pointer that uses an archived `i8` as the underlying offset.
361pub type RawRelPtrI8 = RawRelPtr<i8>;
362/// A raw relative pointer that uses an archived `i16` as the underlying offset.
363pub type RawRelPtrI16 = RawRelPtr<ArchivedI16>;
364/// A raw relative pointer that uses an archived `i32` as the underlying offset.
365pub type RawRelPtrI32 = RawRelPtr<ArchivedI32>;
366/// A raw relative pointer that uses an archived `i64` as the underlying offset.
367pub type RawRelPtrI64 = RawRelPtr<ArchivedI64>;
368
369/// A raw relative pointer that uses an archived `u8` as the underlying offset.
370pub type RawRelPtrU8 = RawRelPtr<u8>;
371/// A raw relative pointer that uses an archived `u16` as the underlying offset.
372pub type RawRelPtrU16 = RawRelPtr<ArchivedU16>;
373/// A raw relative pointer that uses an archived `u32` as the underlying offset.
374pub type RawRelPtrU32 = RawRelPtr<ArchivedU32>;
375/// A raw relative pointer that uses an archived `u64` as the underlying offset.
376pub type RawRelPtrU64 = RawRelPtr<ArchivedU64>;
377
378/// A pointer which resolves to relative to its position in memory.
379///
380/// This is a strongly-typed version of [`RawRelPtr`].
381///
382/// See [`Archive`](crate::Archive) for an example of creating one.
383#[derive(Portable)]
384#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
385#[rkyv(crate)]
386#[repr(C)]
387pub struct RelPtr<T: ArchivePointee + ?Sized, O> {
388    raw_ptr: RawRelPtr<O>,
389    metadata: T::ArchivedMetadata,
390    _phantom: PhantomData<T>,
391}
392
393impl<T, O: Offset> RelPtr<T, O> {
394    /// Attempts to create a relative pointer from one position to another.
395    pub fn try_emplace<E: Source>(
396        to: usize,
397        out: Place<Self>,
398    ) -> Result<(), E> {
399        munge!(let RelPtr { raw_ptr, metadata: _, _phantom: _ } = out);
400        // Skip metadata since sized T is guaranteed to be ()
401        RawRelPtr::try_emplace(to, raw_ptr)
402    }
403
404    /// Creates a relative pointer from one position to another.
405    ///
406    /// # Panics
407    ///
408    /// - If the offset between `from` and `to` does not fit in an `isize`
409    /// - If the offset between `from` and `to` exceeds the offset storage
410    pub fn emplace(to: usize, out: Place<Self>) {
411        Self::try_emplace::<Panic>(to, out).always_ok()
412    }
413}
414
415impl<T: ArchivePointee + ?Sized, O: Offset> RelPtr<T, O> {
416    /// Attempts to create an invalid relative pointer with default metadata.
417    pub fn try_emplace_invalid<E: Source>(out: Place<Self>) -> Result<(), E> {
418        munge!(let RelPtr { raw_ptr, metadata, _phantom: _ } = out);
419        RawRelPtr::try_emplace_invalid(raw_ptr)?;
420        metadata.write(Default::default());
421        Ok(())
422    }
423
424    /// Creates an invalid relative pointer with default metadata.
425    ///
426    /// # Panics
427    ///
428    /// - If an offset of `1` does not fit in an `isize`
429    /// - If an offset of `1` exceeds the offset storage
430    pub fn emplace_invalid(out: Place<Self>) {
431        Self::try_emplace_invalid::<Panic>(out).always_ok()
432    }
433
434    /// Attempts to create a relative pointer from one position to another.
435    pub fn try_emplace_unsized<E: Source>(
436        to: usize,
437        metadata: T::ArchivedMetadata,
438        out: Place<Self>,
439    ) -> Result<(), E> {
440        munge!(let RelPtr { raw_ptr, metadata: out_meta, _phantom: _ } = out);
441        RawRelPtr::try_emplace(to, raw_ptr)?;
442        out_meta.write(metadata);
443        Ok(())
444    }
445
446    /// Creates a relative pointer from one position to another.
447    ///
448    /// # Panics
449    ///
450    /// - If the offset between `from` and `to` does not fit in an `isize`
451    /// - If the offset between `from` and `to` exceeds the offset storage
452    pub fn emplace_unsized(
453        to: usize,
454        metadata: T::ArchivedMetadata,
455        out: Place<Self>,
456    ) {
457        Self::try_emplace_unsized::<Panic>(to, metadata, out).always_ok()
458    }
459
460    /// Gets the base pointer for the pointed-to relative pointer.
461    pub fn base_raw(this: *mut Self) -> *mut u8 {
462        RawRelPtr::<O>::base_raw(this.cast())
463    }
464
465    /// Gets the offset of the pointed-to relative pointer from its base.
466    ///
467    /// # Safety
468    ///
469    /// `this` must be non-null, properly-aligned, and point to a valid
470    /// `RelPtr`.
471    pub unsafe fn offset_raw(this: *mut Self) -> isize {
472        // SAFETY: `RelPtr` is `#[repr(C)]`, so the `RawRelPtr` member of the
473        // `RelPtr` will have the same address as the `RelPtr`. Because `this`
474        // is non-null, properly-aligned, and points to a valid `RelPtr`, a
475        // pointer to its first field will also be non-null, properly-aligned,
476        // and point to a valid `RawRelPtr`.
477        unsafe { RawRelPtr::<O>::offset_raw(this.cast()) }
478    }
479
480    /// Calculates the memory address being pointed to by the pointed-to
481    /// relative pointer.
482    ///
483    /// # Safety
484    ///
485    /// - `this` must be non-null, properly-aligned, and point to a valid
486    ///   `RelPtr`.
487    /// - The offset of this relative pointer, when added to its base, must be
488    ///   located in the same allocated object as it.
489    pub unsafe fn as_ptr_raw(this: *mut Self) -> *mut T {
490        // SAFETY:
491        // - `RelPtr` is `#[repr(C)]`, so the `RawRelPtr` member of the `RelPtr`
492        //   will have the same address as the `RelPtr`. Because `this` is
493        //   non-null, properly-aligned, and points to a valid `RelPtr`, a
494        //   pointer to its first field will also be non-null, properly-aligned,
495        //   and point to a valid `RawRelPtr`.
496        // - The base and offset of the `RawRelPtr` are guaranteed to be the
497        //   same as the base and offset of the `RelPtr`.
498        let data_address = unsafe { RawRelPtr::<O>::as_ptr_raw(this.cast()) };
499        // SAFETY: The caller has guaranteed that `this` points to a valid
500        // `RelPtr`.
501        let metadata = unsafe { T::pointer_metadata(&(*this).metadata) };
502        ptr_meta::from_raw_parts_mut(data_address, metadata)
503    }
504
505    /// Calculates the memory address being pointed to by the pointed-to
506    /// relative pointer using wrapping methods.
507    ///
508    /// This method is a safer but potentially slower version of `as_ptr_raw`.
509    ///
510    /// # Safety
511    ///
512    /// `this` must be non-null, properly-aligned, and point to a valid
513    /// `RelPtr`.
514    pub unsafe fn as_ptr_wrapping_raw(this: *mut Self) -> *mut T {
515        // SAFETY: `RelPtr` is `#[repr(C)]`, so the `RawRelPtr` member of the
516        // `RelPtr` will have the same address as the `RelPtr`. Because `this`
517        // is non-null, properly-aligned, and points to a valid `RelPtr`, a
518        // pointer to its first field will also be non-null, properly-aligned,
519        // and point to a valid `RawRelPtr`.
520        let data_address =
521            unsafe { RawRelPtr::<O>::as_ptr_wrapping_raw(this.cast()) };
522        // SAFETY: The caller has guaranteed that `this` points to a valid
523        // `RelPtr`.
524        let metadata = unsafe { T::pointer_metadata(&(*this).metadata) };
525        ptr_meta::from_raw_parts_mut(data_address, metadata)
526    }
527
528    /// Gets whether the offset of the pointed-to relative pointer is invalid.
529    ///
530    /// # Safety
531    ///
532    /// `this` must be non-null, properly-aligned, and point to a valid
533    /// `RawRelPtr`.
534    pub unsafe fn is_invalid_raw(this: *mut Self) -> bool {
535        // SAFETY: `RelPtr` is `#[repr(C)]`, so the `RawRelPtr` member of the
536        // `RelPtr` will have the same address as the `RelPtr`. Because `this`
537        // is non-null, properly-aligned, and points to a valid `RelPtr`, a
538        // pointer to its first field will also be non-null, properly-aligned,
539        // and point to a valid `RawRelPtr`.
540        unsafe { RawRelPtr::<O>::is_invalid_raw(this.cast()) }
541    }
542
543    /// Gets the base pointer for the relative pointer.
544    pub fn base(&self) -> *const u8 {
545        self.raw_ptr.base()
546    }
547
548    /// Gets the mutable base pointer for this relative pointer.
549    pub fn base_mut(this: Seal<'_, Self>) -> *mut u8 {
550        munge!(let Self { raw_ptr, .. } = this);
551        RawRelPtr::base_mut(raw_ptr)
552    }
553
554    /// Gets the offset of the relative pointer from its base.
555    pub fn offset(&self) -> isize {
556        self.raw_ptr.offset()
557    }
558
559    /// Gets whether the offset of the relative pointer is 0.
560    pub fn is_invalid(&self) -> bool {
561        self.raw_ptr.is_invalid()
562    }
563
564    /// Gets the metadata of the relative pointer.
565    pub fn metadata(&self) -> &T::ArchivedMetadata {
566        &self.metadata
567    }
568
569    /// Calculates the memory address being pointed to by this relative pointer.
570    ///
571    /// # Safety
572    ///
573    /// The offset of this relative pointer, when added to its base, must be
574    /// located in the same allocated object as it.
575    pub unsafe fn as_ptr(&self) -> *const T {
576        ptr_meta::from_raw_parts(
577            // SAFETY: The safety requirements for `RawRelPtr::as_ptr` are the
578            // same as those for `RelPtr::as_ptr``.
579            unsafe { self.raw_ptr.as_ptr() },
580            T::pointer_metadata(&self.metadata),
581        )
582    }
583
584    /// Calculates the mutable memory address being pointed to by this relative
585    /// pointer.
586    ///
587    /// # Safety
588    ///
589    /// The offset of this relative pointer, when added to its base, must be
590    /// located in the same allocated object as it.
591    pub unsafe fn as_mut_ptr(this: Seal<'_, Self>) -> *mut T {
592        munge!(let Self { raw_ptr, metadata, _phantom: _ } = this);
593        let metadata = T::pointer_metadata(&*metadata);
594        ptr_meta::from_raw_parts_mut(
595            // SAFETY: The safety requirements for `RawRelPtr::as_mut_ptr` are
596            // the same as those for `RelPtr::as_mut_ptr``.
597            unsafe { RawRelPtr::as_mut_ptr(raw_ptr) },
598            metadata,
599        )
600    }
601
602    /// Calculates the memory address being pointed to by this relative pointer
603    /// using wrapping methods.
604    ///
605    /// This method is a safer but potentially slower version of `as_ptr`.
606    pub fn as_ptr_wrapping(&self) -> *const T {
607        ptr_meta::from_raw_parts(
608            self.raw_ptr.as_ptr_wrapping(),
609            T::pointer_metadata(&self.metadata),
610        )
611    }
612
613    /// Calculates the mutable memory address being pointed to by this relative
614    /// pointer using wrapping methods.
615    ///
616    /// This method is a safer but potentially slower version of `as_ptr`.
617    pub fn as_mut_ptr_wrapping(this: Seal<'_, Self>) -> *mut T {
618        munge!(let Self { raw_ptr, metadata, _phantom: _ } = this);
619        let metadata = T::pointer_metadata(&*metadata);
620        ptr_meta::from_raw_parts_mut(
621            RawRelPtr::as_mut_ptr_wrapping(raw_ptr),
622            metadata,
623        )
624    }
625}
626
627impl<T: ArchivePointee + ?Sized, O: fmt::Debug> fmt::Debug for RelPtr<T, O>
628where
629    T::ArchivedMetadata: fmt::Debug,
630{
631    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632        f.debug_struct("RelPtr")
633            .field("raw_ptr", &self.raw_ptr)
634            .field("metadata", &self.metadata)
635            .finish()
636    }
637}
638
639impl<T: ArchivePointee + ?Sized, O: Offset> fmt::Pointer for RelPtr<T, O> {
640    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
641        fmt::Pointer::fmt(&self.as_ptr_wrapping(), f)
642    }
643}