about summary refs log tree commit diff
diff options
context:
space:
mode:
authoroliver-giersch <oliver.giersch@gmail.com>2020-07-31 10:07:18 +0200
committerDavid Tolnay <dtolnay@gmail.com>2020-08-03 04:17:45 -0700
commit6c81556a36ac5507fe1f9cd8ee699e6fa2b11077 (patch)
tree4682d764a6627fc03ce611e926fc44c14e205722
parent66b97dca3c8ab51f8af7b2db7ae4c8061fbf5e9b (diff)
downloadrust-6c81556a36ac5507fe1f9cd8ee699e6fa2b11077.tar.gz
rust-6c81556a36ac5507fe1f9cd8ee699e6fa2b11077.zip
adds [*mut|*const] ptr::set_ptr_value
-rw-r--r--library/core/src/ptr/const_ptr.rs32
-rw-r--r--library/core/src/ptr/mut_ptr.rs32
2 files changed, 64 insertions, 0 deletions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index a2acc239bd3..a16970e9fd1 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -656,6 +656,38 @@ impl<T: ?Sized> *const T {
         self.wrapping_offset((count as isize).wrapping_neg())
     }
 
+    /// Sets the pointer value to `ptr`.
+    ///
+    /// In case `self` is a (fat) pointer to an unsized type, this operation
+    /// will only affect the pointer part, whereas for (thin) pointers to
+    /// sized types, this has the same effect as a simple assignment.
+    ///
+    /// # Examples
+    ///
+    /// This function is primarily useful for allowing byte-wise pointer
+    /// arithmetic on potentially fat pointers:
+    ///
+    /// ```
+    /// #![feature(set_ptr_value)]
+    /// # use core::fmt::Debug;
+    /// let arr: [i32; 3] = [1, 2, 3];
+    /// let mut ptr = &arr[0] as *const dyn Debug;
+    /// let thin = ptr as *const u8;
+    /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() });
+    /// assert_eq!(unsafe { *(ptr as *const i32) }, 3);
+    /// ```
+    #[unstable(feature = "set_ptr_value", issue = "75091")]
+    #[inline]
+    pub fn set_ptr_value(mut self, val: *const ()) -> Self {
+        let thin = &mut self as *mut *const T as *mut *const ();
+        // SAFETY: In case of a thin pointer, this operations is identical
+        // to a simple assignment. In case of a fat pointer, with the current
+        // fat pointer layout implementation, the first field of such a
+        // pointer is always the data pointer, which is likewise assigned.
+        unsafe { *thin = val };
+        self
+    }
+
     /// Reads the value from `self` without moving it. This leaves the
     /// memory in `self` unchanged.
     ///
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 17fa90ecc08..b47f90c5996 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -712,6 +712,38 @@ impl<T: ?Sized> *mut T {
         self.wrapping_offset((count as isize).wrapping_neg())
     }
 
+    /// Sets the pointer value to `ptr`.
+    ///
+    /// In case `self` is a (fat) pointer to an unsized type, this operation
+    /// will only affect the pointer part, whereas for (thin) pointers to
+    /// sized types, this has the same effect as a simple assignment.
+    ///
+    /// # Examples
+    ///
+    /// This function is primarily useful for allowing byte-wise pointer
+    /// arithmetic on potentially fat pointers:
+    ///
+    /// ```
+    /// #![feature(set_ptr_value)]
+    /// # use core::fmt::Debug;
+    /// let mut arr: [i32; 3] = [1, 2, 3];
+    /// let mut ptr = &mut arr[0] as *mut dyn Debug;
+    /// let thin = ptr as *mut u8;
+    /// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() });
+    /// assert_eq!(unsafe { *(ptr as *mut i32) }, 3);
+    /// ```
+    #[unstable(feature = "set_ptr_value", issue = "75091")]
+    #[inline]
+    pub fn set_ptr_value(mut self, val: *mut ()) -> Self {
+        let thin = &mut self as *mut *mut T as *mut *mut ();
+        // SAFETY: In case of a thin pointer, this operations is identical
+        // to a simple assignment. In case of a fat pointer, with the current
+        // fat pointer layout implementation, the first field of such a
+        // pointer is always the data pointer, which is likewise assigned.
+        unsafe { *thin = val };
+        self
+    }
+
     /// Reads the value from `self` without moving it. This leaves the
     /// memory in `self` unchanged.
     ///