1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
use core::{mem, ptr};
use crate::assume_unchecked;
#[must_use]
#[inline(always)]
pub(crate) fn from_ref<T: ?Sized>(r: &T) -> *const T {
r
}
#[must_use]
#[inline(always)]
pub(crate) fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
r
}
/// Returns a raw pointer to the slice's buffer.
///
/// This is equivalent to casting `self` to `*mut T`, but more type-safe.
#[inline(always)]
#[allow(dead_code)]
pub(crate) const fn as_mut_ptr<T>(ptr: *mut [T]) -> *mut T {
ptr.cast()
}
#[must_use]
#[inline(always)]
pub(crate) unsafe fn len<T>(ptr: *const [T]) -> usize {
(*ptr).len()
}
/// Calculates the distance between two pointers, *where it's known that
/// `self` is equal to or greater than `origin`*. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// This computes the same value that [`offset_from`](#method.offset_from)
/// would compute, but with the added precondition that the offset is
/// [guaranteed allocated]o be non-negative. This method is equivalent to
/// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`,
/// but it provides slightly more information to the optimizer, which can
/// sometimes allow it to optimize slightly better with some backends.
///
/// This method can be though of as recovering the `count` that was passed
/// to [`add`](#method.add) (or, with the parameters in the other order,
/// to [`sub`](#method.sub)). The following are all equivalent, assuming
/// that their safety preconditions are met:
/// ```
/// # #![feature(ptr_sub_ptr)]
/// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool {
/// ptr.sub_ptr(origin) == count
/// # &&
/// origin.add(count) == ptr
/// # &&
/// ptr.sub(count) == origin
/// # }
/// ```
///
/// # Safety
///
/// - The distance between the pointers must be non-negative (`self >= origin`)
///
/// - *All* the safety conditions of [`offset_from`](#method.offset_from)
/// apply to this method as well; see it for the full details.
///
/// Importantly, despite the return type of this method being able to represent
/// a larger offset, it's still *not permitted* to pass pointers which differ
/// by more than `isize::MAX` *bytes*. As such, the result of this method will
/// always be less than or equal to `isize::MAX as usize`.
///
/// # Panics
///
/// This function panics if `T` is a Zero-Sized Type ("ZST").
///
/// # Examples
///
/// ```
/// #![feature(ptr_sub_ptr)]
///
/// let a = [0; 5];
/// let ptr1: *const i32 = &a[1];
/// let ptr2: *const i32 = &a[3];
/// unsafe {
/// assert_eq!(ptr2.sub_ptr(ptr1), 2);
/// assert_eq!(ptr1.add(2), ptr2);
/// assert_eq!(ptr2.sub(2), ptr1);
/// assert_eq!(ptr2.sub_ptr(ptr2), 0);
/// }
///
/// // This would be incorrect, as the pointers are not correctly ordered:
/// // ptr1.sub_ptr(ptr2)
/// ```
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::checked_conversions)]
pub(crate) unsafe fn sub_ptr<T>(lhs: *const T, rhs: *const T) -> usize {
assume_unchecked(lhs >= rhs);
let pointee_size = mem::size_of::<T>();
assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
lhs.offset_from(rhs) as usize
}
// Putting the expression in a function helps llvm to realize that it can initialize the value
// at this pointer instead of allocating it on the stack and then copying it over.
#[inline(always)]
pub(crate) unsafe fn write_with<T>(ptr: *mut T, f: impl FnOnce() -> T) {
ptr::write(ptr, f());
}
/// Changes constness without changing the type.
///
/// This is a bit safer than `as` because it wouldn't silently change the type if the code is
/// refactored.
#[inline(always)]
pub(crate) const fn cast_mut<T: ?Sized>(ptr: *const T) -> *mut T {
ptr as _
}