Skip to content

Commit 2e64a71

Browse files
authored
Rollup merge of rust-lang#65806 - fusion-engineering-forks:slice-ptr-range, r=Centril
Add [T]::as_ptr_range() and [T]::as_mut_ptr_range(). Implementation of rust-lang/rfcs#2791
2 parents 4cc0226 + de9b660 commit 2e64a71

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

src/libcore/slice/mod.rs

+78-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::fmt;
2828
use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null};
2929
use crate::isize;
3030
use crate::iter::*;
31-
use crate::ops::{FnMut, self};
31+
use crate::ops::{FnMut, Range, self};
3232
use crate::option::Option;
3333
use crate::option::Option::{None, Some};
3434
use crate::result::Result;
@@ -407,6 +407,83 @@ impl<T> [T] {
407407
self as *mut [T] as *mut T
408408
}
409409

410+
/// Returns the two raw pointers spanning the slice.
411+
///
412+
/// The returned range is half-open, which means that the end pointer
413+
/// points *one past* the last element of the slice. This way, an empty
414+
/// slice is represented by two equal pointers, and the difference between
415+
/// the two pointers represents the size of the size.
416+
///
417+
/// See [`as_ptr`] for warnings on using these pointers. The end pointer
418+
/// requires extra caution, as it does not point to a valid element in the
419+
/// slice.
420+
///
421+
/// This function is useful for interacting with foreign interfaces which
422+
/// use two pointers to refer to a range of elements in memory, as is
423+
/// common in C++.
424+
///
425+
/// It can also be useful to check if a reference or pointer to an element
426+
/// refers to an element of this slice:
427+
///
428+
/// ```
429+
/// let a = [1,2,3];
430+
/// let x = &a[1];
431+
/// let y = &5;
432+
/// assert!(a.as_ptr_range().contains(x));
433+
/// assert!(!a.as_ptr_range().contains(y));
434+
/// ```
435+
///
436+
/// [`as_ptr`]: #method.as_ptr
437+
#[unstable(feature = "slice_ptr_range", issue = "65807")]
438+
#[inline]
439+
pub fn as_ptr_range(&self) -> Range<*const T> {
440+
// The `add` here is safe, because:
441+
//
442+
// - Both pointers are part of the same object, as pointing directly
443+
// past the object also counts.
444+
//
445+
// - The size of the slice is never larger than isize::MAX bytes, as
446+
// noted here:
447+
// - https://github.com/rust-lang/unsafe-code-guidelines/issues/102#issuecomment-473340447
448+
// - https://doc.rust-lang.org/reference/behavior-considered-undefined.html
449+
// - https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html#safety
450+
// (This doesn't seem normative yet, but the very same assumption is
451+
// made in many places, including the Index implementation of slices.)
452+
//
453+
// - There is no wrapping around involved, as slices do not wrap past
454+
// the end of the address space.
455+
//
456+
// See the documentation of pointer::add.
457+
let start = self.as_ptr();
458+
let end = unsafe { start.add(self.len()) };
459+
start..end
460+
}
461+
462+
/// Returns the two unsafe mutable pointers spanning the slice.
463+
///
464+
/// The returned range is half-open, which means that the end pointer
465+
/// points *one past* the last element of the slice. This way, an empty
466+
/// slice is represented by two equal pointers, and the difference between
467+
/// the two pointers represents the size of the size.
468+
///
469+
/// See [`as_mut_ptr`] for warnings on using these pointers. The end
470+
/// pointer requires extra caution, as it does not point to a valid element
471+
/// in the slice.
472+
///
473+
/// This function is useful for interacting with foreign interfaces which
474+
/// use two pointers to refer to a range of elements in memory, as is
475+
/// common in C++.
476+
///
477+
/// [`as_mut_ptr`]: #method.as_mut_ptr
478+
#[unstable(feature = "slice_ptr_range", issue = "65807")]
479+
#[inline]
480+
pub fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
481+
// See as_ptr_range() above for why `add` here is safe.
482+
let start = self.as_mut_ptr();
483+
let end = unsafe { start.add(self.len()) };
484+
start..end
485+
}
486+
410487
/// Swaps two elements in the slice.
411488
///
412489
/// # Arguments

0 commit comments

Comments
 (0)