Skip to content

Commit da7a8b8

Browse files
authored
Rollup merge of #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 8c39b00 + 381c442 commit da7a8b8

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

src/libcore/slice/mod.rs

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

0 commit comments

Comments
 (0)