diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2017-03-31 13:52:46 +0100 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2017-04-03 01:36:56 +0100 |
| commit | 7b89bd7ccacd0908d7e22a5cf383c8cc147bc3d5 (patch) | |
| tree | f07ae40b18015742cbd15859b22ec37f5b4d9aa3 /src | |
| parent | c82f1325cfb5f3fd5028225f692cb134517016f1 (diff) | |
| download | rust-7b89bd7ccacd0908d7e22a5cf383c8cc147bc3d5.tar.gz rust-7b89bd7ccacd0908d7e22a5cf383c8cc147bc3d5.zip | |
Add ptr::offset_to
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc/unstable-book/src/SUMMARY.md | 1 | ||||
| -rw-r--r-- | src/doc/unstable-book/src/offset-to.md | 7 | ||||
| -rw-r--r-- | src/libcollections/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcollections/vec.rs | 12 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 76 | ||||
| -rw-r--r-- | src/libcore/slice/mod.rs | 7 |
6 files changed, 93 insertions, 11 deletions
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index fe491d7f901..0c3b7990c93 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -123,6 +123,7 @@ - [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 index 00000000000..376f3ff5d21 --- /dev/null +++ b/src/doc/unstable-book/src/offset-to.md @@ -0,0 +1,7 @@ +# `offset_to` + +The tracking issue for this feature is: [#0] + +[#0]: https://github.com/rust-lang/rust/issues/0 + +------------------------ diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 72e950bc91f..2b345e3d0a5 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -61,6 +61,7 @@ #![feature(unique)] #![feature(untagged_unions)] #![cfg_attr(test, feature(rand, test))] +#![feature(offset_to)] #![no_std] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 56b60a3e003..f12380a9ea5 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -2073,14 +2073,10 @@ impl<T> Iterator for IntoIter<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)) } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index d2830a6d00c..6bcce76af04 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -500,6 +500,44 @@ impl<T: ?Sized> *const T { 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 @@ impl<T: ?Sized> *mut T { 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 diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index af492b3c639..5a978ccc741 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -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 |
