From 6c81556a36ac5507fe1f9cd8ee699e6fa2b11077 Mon Sep 17 00:00:00 2001 From: oliver-giersch Date: Fri, 31 Jul 2020 10:07:18 +0200 Subject: [PATCH] adds [*mut|*const] ptr::set_ptr_value --- library/core/src/ptr/const_ptr.rs | 32 +++++++++++++++++++++++++++++++ library/core/src/ptr/mut_ptr.rs | 32 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) 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 @@ pub const fn wrapping_sub(self, count: usize) -> Self 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 @@ pub const fn wrapping_sub(self, count: usize) -> Self 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. ///