Skip to content

Commit

Permalink
feat(byte_sub_ptr): add ptr::byte_sub_ptr
Browse files Browse the repository at this point in the history
This is an API that naturally should exist as a combination of byte_offset_from and sub_ptr
both existing (they showed up at similar times so this union was never made). Adding these
is a logical (and perhaps final) precondition of stabilizing ptr_sub_ptr (rust-lang#95892).
  • Loading branch information
Gankra committed Mar 3, 2024
1 parent 5119208 commit d42d678
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
19 changes: 19 additions & 0 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,25 @@ impl<T: ?Sized> *const T {
unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
}

/// 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 **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
/// using [`sub_ptr`][pointer::sub_ptr] on it. See that method for
/// documentation and safety requirements.
///
/// For non-`Sized` pointees this operation considers only the data pointers,
/// ignoring the metadata.
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: *const U) -> usize {
// SAFETY: the caller must uphold the safety contract for `sub_ptr`.
unsafe { self.cast::<u8>().sub_ptr(origin.cast::<u8>()) }
}

/// Returns whether two pointers are guaranteed to be equal.
///
/// At runtime this function behaves like `Some(self == other)`.
Expand Down
19 changes: 19 additions & 0 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,25 @@ impl<T: ?Sized> *mut T {
unsafe { (self as *const T).sub_ptr(origin) }
}

/// 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 **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
/// using [`sub_ptr`][pointer::sub_ptr] on it. See that method for
/// documentation and safety requirements.
///
/// For non-`Sized` pointees this operation considers only the data pointers,
/// ignoring the metadata.
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: *mut U) -> usize {
// SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
unsafe { (self as *const T).byte_sub_ptr(origin) }
}

/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
Expand Down
19 changes: 19 additions & 0 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,25 @@ impl<T: ?Sized> NonNull<T> {
unsafe { self.pointer.sub_ptr(subtracted.pointer) }
}

/// 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 **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
/// using [`sub_ptr`][NonNull::sub_ptr] on it. See that method for
/// documentation and safety requirements.
///
/// For non-`Sized` pointees this operation considers only the data pointers,
/// ignoring the metadata.
#[unstable(feature = "non_null_convenience", issue = "117691")]
#[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: NonNull<U>) -> usize {
// SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
unsafe { self.pointer.byte_sub_ptr(origin.pointer) }
}

/// Reads the value from `self` without moving it. This leaves the
/// memory in `self` unchanged.
///
Expand Down

0 comments on commit d42d678

Please sign in to comment.