From d0c08874982c3241425739f13ba6ce19d20bc97d Mon Sep 17 00:00:00 2001
From: Yotam Ofek <yotam.ofek@gmail.com>
Date: Fri, 29 Dec 2023 15:32:09 +0000
Subject: [PATCH] Add as_(mut_)ptr and as_(mut_)slice to raw array pointers

---
 library/core/src/lib.rs           |  1 +
 library/core/src/ptr/const_ptr.rs | 40 ++++++++++++++++++++++++++++
 library/core/src/ptr/mut_ptr.rs   | 43 +++++++++++++++++++++++++++++++
 library/core/tests/lib.rs         |  2 ++
 library/core/tests/ptr.rs         | 13 ++++++++++
 5 files changed, 99 insertions(+)

diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 9b786feba8988..6473f772e304b 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -112,6 +112,7 @@
 //
 // Library features:
 // tidy-alphabetical-start
+#![feature(array_ptr_get)]
 #![feature(char_indices_offset)]
 #![feature(const_align_of_val)]
 #![feature(const_align_of_val_raw)]
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index a0c04d3f65dfd..979fd1e4b4a2a 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1798,6 +1798,46 @@ impl<T> *const [T] {
     }
 }
 
+impl<T, const N: usize> *const [T; N] {
+    /// Returns a raw pointer to the array's buffer.
+    ///
+    /// This is equivalent to casting `self` to `*const T`, but more type-safe.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(array_ptr_get)]
+    /// use std::ptr;
+    ///
+    /// let arr: *const [i8; 3] = ptr::null();
+    /// assert_eq!(arr.as_ptr(), ptr::null());
+    /// ```
+    #[inline]
+    #[unstable(feature = "array_ptr_get", issue = "119834")]
+    #[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+
+    /// Returns a raw pointer to a slice containing the entire array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(array_ptr_get, slice_ptr_len)]
+    ///
+    /// let arr: *const [i32; 3] = &[1, 2, 4] as *const [i32; 3];
+    /// let slice: *const [i32] = arr.as_slice();
+    /// assert_eq!(slice.len(), 3);
+    /// ```
+    #[inline]
+    #[unstable(feature = "array_ptr_get", issue = "119834")]
+    #[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
+    pub const fn as_slice(self) -> *const [T] {
+        self
+    }
+}
+
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *const T {
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 6a9033a144deb..bfdd9dba320d3 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -2209,6 +2209,49 @@ impl<T> *mut [T] {
     }
 }
 
+impl<T, const N: usize> *mut [T; N] {
+    /// Returns a raw pointer to the array's buffer.
+    ///
+    /// This is equivalent to casting `self` to `*mut T`, but more type-safe.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(array_ptr_get)]
+    /// use std::ptr;
+    ///
+    /// let arr: *mut [i8; 3] = ptr::null_mut();
+    /// assert_eq!(arr.as_mut_ptr(), ptr::null_mut());
+    /// ```
+    #[inline]
+    #[unstable(feature = "array_ptr_get", issue = "119834")]
+    #[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
+    pub const fn as_mut_ptr(self) -> *mut T {
+        self as *mut T
+    }
+
+    /// Returns a raw pointer to a mutable slice containing the entire array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(array_ptr_get)]
+    ///
+    /// let mut arr = [1, 2, 5];
+    /// let ptr: *mut [i32; 3] = &mut arr;
+    /// unsafe {
+    ///     (&mut *ptr.as_mut_slice())[..2].copy_from_slice(&[3, 4]);
+    /// }
+    /// assert_eq!(arr, [3, 4, 5]);
+    /// ```
+    #[inline]
+    #[unstable(feature = "array_ptr_get", issue = "119834")]
+    #[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
+    pub const fn as_mut_slice(self) -> *mut [T] {
+        self
+    }
+}
+
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *mut T {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index c5a7e87c4aa4f..421062f5873cd 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,5 +1,6 @@
 #![feature(alloc_layout_extra)]
 #![feature(array_chunks)]
+#![feature(array_ptr_get)]
 #![feature(array_windows)]
 #![feature(ascii_char)]
 #![feature(ascii_char_variants)]
@@ -52,6 +53,7 @@
 #![feature(sort_internals)]
 #![feature(slice_take)]
 #![feature(slice_from_ptr_range)]
+#![feature(slice_ptr_len)]
 #![feature(slice_split_once)]
 #![feature(split_as_slice)]
 #![feature(maybe_uninit_fill)]
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 659fbd255c168..5c518e2d59340 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -1141,3 +1141,16 @@ fn test_const_copy() {
         assert!(*ptr2 == 1);
     };
 }
+
+#[test]
+fn test_null_array_as_slice() {
+    let arr: *mut [u8; 4] = null_mut();
+    let ptr: *mut [u8] = arr.as_mut_slice();
+    assert!(ptr.is_null());
+    assert_eq!(ptr.len(), 4);
+
+    let arr: *const [u8; 4] = null();
+    let ptr: *const [u8] = arr.as_slice();
+    assert!(ptr.is_null());
+    assert_eq!(ptr.len(), 4);
+}