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}