Add ptr::offset_to
This commit is contained in:
parent
c82f1325cf
commit
7b89bd7cca
6 changed files with 93 additions and 11 deletions
|
@ -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)
|
||||
|
|
7
src/doc/unstable-book/src/offset-to.md
Normal file
7
src/doc/unstable-book/src/offset-to.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# `offset_to`
|
||||
|
||||
The tracking issue for this feature is: [#0]
|
||||
|
||||
[#0]: https://github.com/rust-lang/rust/issues/0
|
||||
|
||||
------------------------
|
|
@ -61,6 +61,7 @@
|
|||
#![feature(unique)]
|
||||
#![feature(untagged_unions)]
|
||||
#![cfg_attr(test, feature(rand, test))]
|
||||
#![feature(offset_to)]
|
||||
|
||||
#![no_std]
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue