From c710fa7d282424db10e58a991ad12208d350e7a7 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 13 Feb 2022 14:43:57 -0800 Subject: [PATCH] Add `to_bits` and `from_bits` to `ptr::NonNull` as well These also make sense on `NonNull`, especially for the future when it'll be able to use `T: Thin` instead of `T: Sized`. --- library/core/src/ptr/non_null.rs | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 3f5d3f62c9604..ffb884e22c1ca 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -4,6 +4,7 @@ use crate::fmt; use crate::hash; use crate::marker::Unsize; use crate::mem::{self, MaybeUninit}; +use crate::num::NonZeroUsize; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ptr::Unique; use crate::slice::{self, SliceIndex}; @@ -401,6 +402,66 @@ impl NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } } + + /// Casts a pointer to its raw (non-zero) bits. + /// + /// This is basically the same as `as` casting the underlying pointer, but + /// stays in non-null and non-zero land to avoid losing information. + /// + /// The inverse method is [`from_bits`](#method.from_bits). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// use std::num::NonZeroUsize; + /// use std::ptr::NonNull; + /// + /// let dangling: NonNull = NonNull::dangling(); + /// assert_eq!(dangling.to_bits(), NonZeroUsize::new(1).unwrap()); + /// + /// let misaligned: NonNull = NonNull::new(12345 as _).unwrap(); + /// assert_eq!(misaligned.to_bits(), NonZeroUsize::new(12345).unwrap()); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn to_bits(self) -> NonZeroUsize + where + T: Sized, + { + // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null + unsafe { NonZeroUsize::new_unchecked(self.as_ptr().to_bits()) } + } + + /// Creates a pointer from its raw (non-zero) bits. + /// + /// This is basically the same as `as` casting to get the pointer, but + /// stays in non-null and non-zero land to avoid losing information. + /// + /// The inverse method is [`to_bits`](#method.to_bits). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// use std::num::NonZeroUsize; + /// use std::ptr::NonNull; + /// + /// let dangling: NonNull = NonNull::dangling(); + /// assert_eq!(dangling, NonNull::from_bits(NonZeroUsize::new(1).unwrap())); + /// + /// assert_eq!( + /// NonNull::::from_bits(NonZeroUsize::new(12345).unwrap()), + /// NonNull::::new(12345 as _).unwrap(), + /// ); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn from_bits(bits: NonZeroUsize) -> Self + where + T: Sized, + { + // SAFETY: `bits` is `NonZeroUsize`, so this always makes a non-null pointer + unsafe { Self::new_unchecked(<*mut T>::from_bits(bits.get())) } + } } impl NonNull<[T]> {