]> git.lizzy.rs Git - rust.git/commitdiff
Add ptr::offset_to
authorAmanieu d'Antras <amanieu@gmail.com>
Fri, 31 Mar 2017 12:52:46 +0000 (13:52 +0100)
committerAmanieu d'Antras <amanieu@gmail.com>
Mon, 3 Apr 2017 00:36:56 +0000 (01:36 +0100)
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/offset-to.md [new file with mode: 0644]
src/libcollections/lib.rs
src/libcollections/vec.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs

index fe491d7f9018ef5fff1d0c2cd78a5d55744be79f..0c3b7990c93b86163159b705243a5941dfde9f32 100644 (file)
 - [no_debug](no-debug.md)
 - [non_ascii_idents](non-ascii-idents.md)
 - [nonzero](nonzero.md)
+- [offset_to](offset-to.md)
 - [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md)
 - [on_unimplemented](on-unimplemented.md)
 - [once_poison](once-poison.md)
diff --git a/src/doc/unstable-book/src/offset-to.md b/src/doc/unstable-book/src/offset-to.md
new file mode 100644 (file)
index 0000000..376f3ff
--- /dev/null
@@ -0,0 +1,7 @@
+# `offset_to`
+
+The tracking issue for this feature is: [#0]
+
+[#0]: https://github.com/rust-lang/rust/issues/0
+
+------------------------
index 72e950bc91fa978a37b6a927f8fd0208579a8984..2b345e3d0a59ffb632bbafa862c23aa33c4c3780 100644 (file)
@@ -61,6 +61,7 @@
 #![feature(unique)]
 #![feature(untagged_unions)]
 #![cfg_attr(test, feature(rand, test))]
+#![feature(offset_to)]
 
 #![no_std]
 
index 56b60a3e00341b6b4eb6605b65d16d3350e0c2b5..f12380a9ea535f57729d474198bcb1e393c0e4d0 100644 (file)
@@ -2073,14 +2073,10 @@ fn next(&mut self) -> Option<T> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let diff = (self.end as usize) - (self.ptr as usize);
-        let size = mem::size_of::<T>();
-        let exact = diff /
-                    (if size == 0 {
-                         1
-                     } else {
-                         size
-                     });
+        let exact = match self.ptr.offset_to(self.end) {
+            Some(x) => x as usize,
+            None => (self.end as usize).wrapping_sub(self.ptr as usize),
+        };
         (exact, Some(exact))
     }
 
index d2830a6d00cec149ba22e64c98db7de2ce23d63c..6bcce76af04e39e9a91a36062ff8729a3a5ffcd4 100644 (file)
@@ -500,6 +500,44 @@ pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
             intrinsics::arith_offset(self, count)
         }
     }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// If the address different between the two pointers ia not a multiple of
+    /// `mem::size_of::<T>()` then the result of the division is rounded towards
+    /// zero.
+    ///
+    /// This function returns `None` if `T` is a zero-sized typed.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(offset_to)]
+    ///
+    /// fn main() {
+    ///     let a = [0; 5];
+    ///     let ptr1: *const i32 = &a[1];
+    ///     let ptr2: *const i32 = &a[3];
+    ///     assert_eq!(ptr1.offset_to(ptr2), Some(2));
+    ///     assert_eq!(ptr2.offset_to(ptr1), Some(-2));
+    ///     assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
+    ///     assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
+    /// }
+    /// ```
+    #[unstable(feature = "offset_to", issue = "0")]
+    #[inline]
+    pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            None
+        } else {
+            let diff = (other as isize).wrapping_sub(self as isize);
+            Some(diff / size as isize)
+        }
+    }
 }
 
 #[lang = "mut_ptr"]
@@ -653,6 +691,44 @@ pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized {
             Some(&mut *self)
         }
     }
+
+    /// Calculates the distance between two pointers. The returned value is in
+    /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+    ///
+    /// If the address different between the two pointers ia not a multiple of
+    /// `mem::size_of::<T>()` then the result of the division is rounded towards
+    /// zero.
+    ///
+    /// This function returns `None` if `T` is a zero-sized typed.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(offset_to)]
+    ///
+    /// fn main() {
+    ///     let mut a = [0; 5];
+    ///     let ptr1: *mut i32 = &mut a[1];
+    ///     let ptr2: *mut i32 = &mut a[3];
+    ///     assert_eq!(ptr1.offset_to(ptr2), Some(2));
+    ///     assert_eq!(ptr2.offset_to(ptr1), Some(-2));
+    ///     assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
+    ///     assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
+    /// }
+    /// ```
+    #[unstable(feature = "offset_to", issue = "0")]
+    #[inline]
+    pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            None
+        } else {
+            let diff = (other as isize).wrapping_sub(self as isize);
+            Some(diff / size as isize)
+        }
+    }
 }
 
 // Equality for pointers
index af492b3c63976089744aade562e703545c5b2e1b..5a978ccc74153777762c775eec57065cc5c7b1eb 100644 (file)
@@ -1502,9 +1502,10 @@ unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
 // Return the arithmetic difference if `T` is zero size.
 #[inline(always)]
 fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
-    let diff = (end as usize).wrapping_sub(start as usize);
-    let size = mem::size_of::<T>();
-    diff / (if size == 0 { 1 } else { size })
+    match start.offset_to(end) {
+        Some(x) => x as usize,
+        None => (end as usize).wrapping_sub(start as usize),
+    }
 }
 
 // Extension methods for raw pointers, used by the iterators