From 8b2108c6cb6b60f01b2ff01ef81861dcbc02fec7 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Wed, 26 Oct 2016 23:05:06 +0200 Subject: [PATCH 1/2] core::ptr: Add .wrapping_offset() methods .wrapping_offset() exposes the arith_offset intrinsic in the core module. This is the first step in making it possible to stabilize the interface later. `arith_offset` is a useful tool for developing iterators for two reasons: 1. `arith_offset` is used by the slice's iterator, the most important iterator in libcore, and it is natural that Rust users need the same power available to implement similar iterators. 2. It is a good way to implement raw pointer iterations with step greater than one. The name seems to fit the style of methods like "wrapping_add". --- src/libcore/ptr.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f0510422a07d7..befab1b3669b3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -344,6 +344,46 @@ impl *const T { pub unsafe fn offset(self, count: isize) -> *const T where T: Sized { intrinsics::offset(self, count) } + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The resulting pointer does not need to be in bounds, but it is + /// potentially hazardous to dereference (which requires `unsafe`). + /// + /// Always use `.offset(count)` instead when possible, because `offset` + /// allows the compiler to optimize better. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_wrapping_offset)] + /// // Iterate using a raw pointer in increments of two elements + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_offset(6); + /// + /// // This loop prints "1, 3, 5, " + /// while ptr != end_rounded_up { + /// unsafe { + /// print!("{}, ", *ptr); + /// } + /// ptr = ptr.wrapping_offset(step); + /// } + /// ``` + #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[inline] + pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized { + unsafe { + intrinsics::arith_offset(self, count) + } + } } #[lang = "mut_ptr"] @@ -429,6 +469,46 @@ impl *mut T { intrinsics::offset(self, count) as *mut T } + /// Calculates the offset from a pointer using wrapping arithmetic. + /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The resulting pointer does not need to be in bounds, but it is + /// potentially hazardous to dereference (which requires `unsafe`). + /// + /// Always use `.offset(count)` instead when possible, because `offset` + /// allows the compiler to optimize better. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_wrapping_offset)] + /// // Iterate using a raw pointer in increments of two elements + /// let mut data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *mut u8 = data.as_mut_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_offset(6); + /// + /// while ptr != end_rounded_up { + /// unsafe { + /// *ptr = 0; + /// } + /// ptr = ptr.wrapping_offset(step); + /// } + /// assert_eq!(&data, &[0, 2, 0, 4, 0]); + /// ``` + #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[inline] + pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized { + unsafe { + intrinsics::arith_offset(self, count) as *mut T + } + } + /// Returns `None` if the pointer is null, or else returns a mutable /// reference to the value wrapped in `Some`. /// From 67626e0cc30e07fe8763d344e855d7b4750b0b33 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Fri, 4 Nov 2016 00:16:04 +0100 Subject: [PATCH 2/2] core::ptr: Specify issue for ptr_wrapping_offset feature --- src/libcore/ptr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index befab1b3669b3..2ad38de72b1b9 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -377,7 +377,7 @@ impl *const T { /// ptr = ptr.wrapping_offset(step); /// } /// ``` - #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[unstable(feature = "ptr_wrapping_offset", issue = "37570")] #[inline] pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized { unsafe { @@ -501,7 +501,7 @@ impl *mut T { /// } /// assert_eq!(&data, &[0, 2, 0, 4, 0]); /// ``` - #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[unstable(feature = "ptr_wrapping_offset", issue = "37570")] #[inline] pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized { unsafe {