Skip to content

Commit 041f890

Browse files
committed
Rollup merge of rust-lang#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".
2 parents 1a09632 + 67626e0 commit 041f890

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

src/libcore/ptr.rs

+80
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,46 @@ impl<T: ?Sized> *const T {
344344
pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {
345345
intrinsics::offset(self, count)
346346
}
347+
348+
/// Calculates the offset from a pointer using wrapping arithmetic.
349+
/// `count` is in units of T; e.g. a `count` of 3 represents a pointer
350+
/// offset of `3 * sizeof::<T>()` bytes.
351+
///
352+
/// # Safety
353+
///
354+
/// The resulting pointer does not need to be in bounds, but it is
355+
/// potentially hazardous to dereference (which requires `unsafe`).
356+
///
357+
/// Always use `.offset(count)` instead when possible, because `offset`
358+
/// allows the compiler to optimize better.
359+
///
360+
/// # Examples
361+
///
362+
/// Basic usage:
363+
///
364+
/// ```
365+
/// #![feature(ptr_wrapping_offset)]
366+
/// // Iterate using a raw pointer in increments of two elements
367+
/// let data = [1u8, 2, 3, 4, 5];
368+
/// let mut ptr: *const u8 = data.as_ptr();
369+
/// let step = 2;
370+
/// let end_rounded_up = ptr.wrapping_offset(6);
371+
///
372+
/// // This loop prints "1, 3, 5, "
373+
/// while ptr != end_rounded_up {
374+
/// unsafe {
375+
/// print!("{}, ", *ptr);
376+
/// }
377+
/// ptr = ptr.wrapping_offset(step);
378+
/// }
379+
/// ```
380+
#[unstable(feature = "ptr_wrapping_offset", issue = "37570")]
381+
#[inline]
382+
pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
383+
unsafe {
384+
intrinsics::arith_offset(self, count)
385+
}
386+
}
347387
}
348388

349389
#[lang = "mut_ptr"]
@@ -429,6 +469,46 @@ impl<T: ?Sized> *mut T {
429469
intrinsics::offset(self, count) as *mut T
430470
}
431471

472+
/// Calculates the offset from a pointer using wrapping arithmetic.
473+
/// `count` is in units of T; e.g. a `count` of 3 represents a pointer
474+
/// offset of `3 * sizeof::<T>()` bytes.
475+
///
476+
/// # Safety
477+
///
478+
/// The resulting pointer does not need to be in bounds, but it is
479+
/// potentially hazardous to dereference (which requires `unsafe`).
480+
///
481+
/// Always use `.offset(count)` instead when possible, because `offset`
482+
/// allows the compiler to optimize better.
483+
///
484+
/// # Examples
485+
///
486+
/// Basic usage:
487+
///
488+
/// ```
489+
/// #![feature(ptr_wrapping_offset)]
490+
/// // Iterate using a raw pointer in increments of two elements
491+
/// let mut data = [1u8, 2, 3, 4, 5];
492+
/// let mut ptr: *mut u8 = data.as_mut_ptr();
493+
/// let step = 2;
494+
/// let end_rounded_up = ptr.wrapping_offset(6);
495+
///
496+
/// while ptr != end_rounded_up {
497+
/// unsafe {
498+
/// *ptr = 0;
499+
/// }
500+
/// ptr = ptr.wrapping_offset(step);
501+
/// }
502+
/// assert_eq!(&data, &[0, 2, 0, 4, 0]);
503+
/// ```
504+
#[unstable(feature = "ptr_wrapping_offset", issue = "37570")]
505+
#[inline]
506+
pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized {
507+
unsafe {
508+
intrinsics::arith_offset(self, count) as *mut T
509+
}
510+
}
511+
432512
/// Returns `None` if the pointer is null, or else returns a mutable
433513
/// reference to the value wrapped in `Some`.
434514
///

0 commit comments

Comments
 (0)