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