about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2016-11-04 16:49:29 -0700
committerAlex Crichton <alex@alexcrichton.com>2016-11-05 10:50:22 -0700
commit041f890cfe943741112232d394875f37a1659a07 (patch)
tree1644f5a320f548f049f1b872c9d97122ea5932a5
parent1a0963292aa6d78a4de05dbee853d0efe6cefe8a (diff)
parent67626e0cc30e07fe8763d344e855d7b4750b0b33 (diff)
downloadrust-041f890cfe943741112232d394875f37a1659a07.tar.gz
rust-041f890cfe943741112232d394875f37a1659a07.zip
Rollup merge of #37422 - bluss:wrapping-offset, r=alexcrichton
Add .wrapping_offset() methods

.wrapping_offset() exposes the arith_offset intrinsic in the core
module (as methods on raw pointers, next to offset). 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".
-rw-r--r--src/libcore/ptr.rs80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index f0510422a07..2ad38de72b1 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 = "37570")]
+    #[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 = "37570")]
+    #[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`.
     ///