bump_scope/polyfill/
non_null.rs

1use core::{
2    num::NonZeroUsize,
3    ops::Range,
4    ptr::{self, NonNull},
5};
6
7use crate::polyfill::pointer;
8
9/// See [`std::ptr::NonNull::offset_from_unsigned`].
10#[must_use]
11#[inline(always)]
12pub(crate) unsafe fn offset_from_unsigned<T>(this: NonNull<T>, origin: NonNull<T>) -> usize {
13    unsafe { pointer::offset_from_unsigned(this.as_ptr(), origin.as_ptr()) }
14}
15
16/// See [`std::ptr::NonNull::byte_offset_from_unsigned`].
17#[must_use]
18#[inline(always)]
19pub(crate) unsafe fn byte_offset_from_unsigned<T>(this: NonNull<T>, origin: NonNull<T>) -> usize {
20    unsafe { offset_from_unsigned::<u8>(this.cast(), origin.cast()) }
21}
22
23/// See [`std::ptr::NonNull::is_aligned_to`].
24#[inline(always)]
25pub(crate) fn is_aligned_to(ptr: NonNull<u8>, align: usize) -> bool {
26    debug_assert!(align.is_power_of_two());
27    ptr.addr().get() & (align - 1) == 0
28}
29
30/// See [`core::ptr::NonNull::as_non_null_ptr`].
31#[inline(always)]
32pub(crate) const fn as_non_null_ptr<T>(ptr: NonNull<[T]>) -> NonNull<T> {
33    ptr.cast()
34}
35
36/// See [`std::ptr::NonNull::from_ref`].
37pub(crate) const fn from_ref<T>(r: &T) -> NonNull<T> {
38    unsafe { NonNull::new_unchecked(r as *const T as *mut T) }
39}
40
41/// See [`std::ptr::NonNull::without_provenance`].
42#[must_use]
43#[inline]
44pub(crate) const fn without_provenance<T>(addr: NonZeroUsize) -> NonNull<T> {
45    let pointer = ptr::without_provenance_mut(addr.get());
46    // SAFETY: we know `addr` is non-zero.
47    unsafe { NonNull::new_unchecked(pointer) }
48}
49
50/// Not part of std, but for context see [`std::vec::Vec::truncate`].
51///
52/// # Safety
53///
54/// `ptr` must point to a valid slice.
55pub(crate) unsafe fn truncate<T>(slice: &mut NonNull<[T]>, len: usize) {
56    unsafe {
57        // This is safe because:
58        //
59        // * the slice passed to `drop_in_place` is valid; the `len > self.len`
60        //   case avoids creating an invalid slice, and
61        // * the `len` of the slice is shrunk before calling `drop_in_place`,
62        //   such that no value will be dropped twice in case `drop_in_place`
63        //   were to panic once (if it panics twice, the program aborts).
64
65        // Unlike std this is `>=`. Std uses `>` because when a call is inlined with `len` of `0` that optimizes better.
66        // But this was likely only motivated because `clear` used to be implemented as `truncate(0)`.
67        // See <https://github.com/rust-lang/rust/issues/76089#issuecomment-1889416842>.
68        if len >= slice.len() {
69            return;
70        }
71
72        let remaining_len = slice.len() - len;
73
74        let to_drop_start = as_non_null_ptr(*slice).add(len);
75        let to_drop = NonNull::slice_from_raw_parts(to_drop_start, remaining_len);
76
77        set_len::<T>(slice, len);
78        to_drop.drop_in_place();
79    }
80}
81
82/// Not part of std, but for context see `<*mut T>::wrapping_add`.
83#[inline(always)]
84pub(crate) unsafe fn wrapping_byte_add<T>(ptr: NonNull<T>, count: usize) -> NonNull<T> {
85    unsafe { NonNull::new_unchecked(ptr.as_ptr().cast::<u8>().wrapping_add(count).cast()) }
86}
87
88/// Not part of std, but for context see `<*mut T>::wrapping_sub`.
89#[inline(always)]
90pub(crate) unsafe fn wrapping_byte_sub<T>(ptr: NonNull<T>, count: usize) -> NonNull<T> {
91    unsafe { NonNull::new_unchecked(ptr.as_ptr().cast::<u8>().wrapping_sub(count).cast()) }
92}
93
94/// Not part of std.
95#[inline(always)]
96pub(crate) fn set_ptr<T>(ptr: &mut NonNull<[T]>, new_ptr: NonNull<T>) {
97    let len = ptr.len();
98    *ptr = NonNull::slice_from_raw_parts(new_ptr, len);
99}
100
101/// Not part of std.
102#[inline(always)]
103pub(crate) fn set_len<T>(ptr: &mut NonNull<[T]>, new_len: usize) {
104    let elem_ptr = as_non_null_ptr(*ptr);
105    *ptr = NonNull::slice_from_raw_parts(elem_ptr, new_len);
106}
107
108/// Not part of std.
109#[inline(always)]
110pub(crate) unsafe fn result<T, E>(mut ptr: NonNull<Result<T, E>>) -> Result<NonNull<T>, NonNull<E>> {
111    unsafe {
112        match ptr.as_mut() {
113            Ok(ok) => Ok(ok.into()),
114            Err(err) => Err(err.into()),
115        }
116    }
117}
118
119#[inline(always)]
120pub(crate) unsafe fn cast_range<T, U>(ptr: Range<NonNull<T>>) -> Range<NonNull<U>> {
121    ptr.start.cast()..ptr.end.cast()
122}
123
124/// Not part of std.
125#[must_use]
126#[inline(always)]
127pub(crate) const fn str_from_utf8(bytes: NonNull<[u8]>) -> NonNull<str> {
128    unsafe { NonNull::new_unchecked(bytes.as_ptr() as *mut str) }
129}
130
131/// Not part of std.
132#[must_use]
133#[inline(always)]
134pub(crate) const fn str_bytes(str: NonNull<str>) -> NonNull<[u8]> {
135    unsafe { NonNull::new_unchecked(str.as_ptr() as *mut [u8]) }
136}
137
138/// Not part of std.
139#[must_use]
140#[inline(always)]
141pub(crate) const fn str_len(str: NonNull<str>) -> usize {
142    str_bytes(str).len()
143}
144
145/// Not part of std.
146///
147/// Putting the expression in a function helps llvm to realize that it can initialize the value
148/// at this pointer instead of allocating it on the stack and then copying it over.
149#[inline(always)]
150pub(crate) unsafe fn write_with<T>(ptr: NonNull<T>, f: impl FnOnce() -> T) {
151    unsafe { ptr.write(f()) };
152}