diff options
| author | Ulrik Sverdrup <bluss@users.noreply.github.com> | 2016-10-26 23:05:06 +0200 |
|---|---|---|
| committer | Ulrik Sverdrup <bluss@users.noreply.github.com> | 2016-10-27 00:07:26 +0200 |
| commit | 8b2108c6cb6b60f01b2ff01ef81861dcbc02fec7 (patch) | |
| tree | 12016be1a4aa99efc248e16759fec3b0dca9c816 /src/libcore | |
| parent | 0c429872a32c3005cf2b347025163361218634a4 (diff) | |
| download | rust-8b2108c6cb6b60f01b2ff01ef81861dcbc02fec7.tar.gz rust-8b2108c6cb6b60f01b2ff01ef81861dcbc02fec7.zip | |
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".
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/ptr.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f0510422a07..befab1b3669 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -344,6 +344,46 @@ impl<T: ?Sized> *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::<T>()` 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<T: ?Sized> *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::<T>()` 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`. /// |
