1//! This module contains (hopefully sound) re-implementations of unstable
2//! `core::ptr` APIs.
34pub(crate) use self::unique::Unique;
5mod unique;
67use core::mem;
8pub(crate) use core::ptr::NonNull;
910// Stable re-exports.
11pub(crate) use core::ptr::{
12 addr_of, addr_of_mut, copy, copy_nonoverlapping, drop_in_place, read, slice_from_raw_parts_mut,
13 write,
14};
1516pub(crate) const unsafe fn nonnull_add<T>(this: NonNull<T>, delta: usize) -> NonNull<T>
17where
18T: Sized,
19{
20// SAFETY: We require that the delta stays in-bounds of the object, and
21 // thus it cannot become null, as that would require wrapping the
22 // address space, which no legal objects are allowed to do.
23 // And the caller promised the `delta` is sound to add.
24let pointer = this.as_ptr();
25unsafe { NonNull::new_unchecked(pointer.add(delta)) }
26}
2728pub(crate) const unsafe fn nonnull_sub<T>(this: NonNull<T>, delta: usize) -> NonNull<T>
29where
30T: Sized,
31{
32// SAFETY: We require that the delta stays in-bounds of the object, and
33 // thus it cannot become null, as that would require wrapping the
34 // address space, which no legal objects are allowed to do.
35 // And the caller promised the `delta` is sound to add.
36let pointer = this.as_ptr();
37unsafe { NonNull::new_unchecked(pointer.sub(delta)) }
38}
3940#[inline(always)]
41#[allow(clippy::useless_transmute)]
42pub const fn invalid<T>(addr: usize) -> *const T {
43// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
44 // We use transmute rather than a cast so tools like Miri can tell that this
45 // is *not* the same as from_exposed_addr.
46 // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
47 // pointer).
48unsafe { mem::transmute(addr) }
49}
5051#[inline(always)]
52#[allow(clippy::useless_transmute)]
53pub const fn invalid_mut<T>(addr: usize) -> *mut T {
54// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
55 // We use transmute rather than a cast so tools like Miri can tell that this
56 // is *not* the same as from_exposed_addr.
57 // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
58 // pointer).
59unsafe { mem::transmute(addr) }
60}
6162cfg_if! {
63if #[cfg(rune_nightly)] {
64#[inline(always)]
65pub(crate) unsafe fn sub_ptr<T>(from: *const T, to: *const T) -> usize {
66 from.offset_from_unsigned(to)
67 }
68 } else {
69#[inline(always)]
70pub(crate) unsafe fn sub_ptr<T>(from: *const T, to: *const T) -> usize {
71const {
72let pointee_size = mem::size_of::<T>();
73assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
74 }
7576debug_assert!(addr(from) >= addr(to));
77 addr(from).wrapping_sub(addr(to)).saturating_div(mem::size_of::<T>())
78 }
79 }
80}
8182cfg_if! {
83if #[cfg(rune_nightly)] {
84#[inline(always)]
85pub(crate) fn addr<T>(from: *const T) -> usize {
86 from.addr()
87 }
88 } else {
89#[inline(always)]
90pub(crate) fn addr<T>(from: *const T) -> usize {
91 from as usize
92 }
93 }
94}
9596cfg_if! {
97if #[cfg(rune_nightly)] {
98#[inline(always)]
99pub(crate) fn slice_len<T>(from: *const [T]) -> usize {
100 from.len()
101 }
102 } else {
103#[inline(always)]
104pub(crate) fn slice_len<T>(from: *const [T]) -> usize {
105// SAFETY: This is *a bit* tricky, but the raw pointer contains the
106 // length and *should* be safe to dereference like this. However,
107 // walking through the dereferenced `[T]` is not necessarily
108 // correct.
109unsafe { (*from).len() }
110 }
111 }
112}