Rollup merge of #89793 - ibraheemdev:from_ptr_range, r=m-ou-se
Add `slice::{from_ptr_range, from_mut_ptr_range} ` Adds `slice::{from_ptr_range, from_mut_ptr_range}` as counterparts to `slice::{as_ptr_range, as_mut_ptr_range}`.
This commit is contained in:
commit
770ee32b34
@ -71,6 +71,9 @@ pub use raw::{from_raw_parts, from_raw_parts_mut};
|
|||||||
#[stable(feature = "from_ref", since = "1.28.0")]
|
#[stable(feature = "from_ref", since = "1.28.0")]
|
||||||
pub use raw::{from_mut, from_ref};
|
pub use raw::{from_mut, from_ref};
|
||||||
|
|
||||||
|
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
|
||||||
|
pub use raw::{from_mut_ptr_range, from_ptr_range};
|
||||||
|
|
||||||
// This function is public only because there is no other way to unit test heapsort.
|
// This function is public only because there is no other way to unit test heapsort.
|
||||||
#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
|
#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
|
||||||
pub use sort::heapsort;
|
pub use sort::heapsort;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Free functions to create `&[T]` and `&mut [T]`.
|
//! Free functions to create `&[T]` and `&mut [T]`.
|
||||||
|
|
||||||
use crate::array;
|
use crate::array;
|
||||||
|
use crate::ops::Range;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
|
||||||
/// Forms a slice from a pointer and a length.
|
/// Forms a slice from a pointer and a length.
|
||||||
@ -177,3 +178,113 @@ pub const fn from_ref<T>(s: &T) -> &[T] {
|
|||||||
pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
|
pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
|
||||||
array::from_mut(s)
|
array::from_mut(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Forms a slice from a pointer range.
|
||||||
|
///
|
||||||
|
/// This function is useful for interacting with foreign interfaces which
|
||||||
|
/// use two pointers to refer to a range of elements in memory, as is
|
||||||
|
/// common in C++.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Behavior is undefined if any of the following conditions are violated:
|
||||||
|
///
|
||||||
|
/// * The `start` pointer of the range must be a [valid] and properly aligned pointer
|
||||||
|
/// to the first element of a slice.
|
||||||
|
///
|
||||||
|
/// * The `end` pointer must be a [valid] and properly aligned pointer to *one past*
|
||||||
|
/// the last element, such that the offset from the end to the start pointer is
|
||||||
|
/// the length of the slice.
|
||||||
|
///
|
||||||
|
/// * The range must contain `N` consecutive properly initialized values of type `T`:
|
||||||
|
///
|
||||||
|
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||||
|
/// Slices can never span across multiple allocated objects.
|
||||||
|
///
|
||||||
|
/// * The memory referenced by the returned slice must not be mutated for the duration
|
||||||
|
/// of lifetime `'a`, except inside an `UnsafeCell`.
|
||||||
|
///
|
||||||
|
/// * The total length of the range must be no larger than `isize::MAX`.
|
||||||
|
/// See the safety documentation of [`pointer::offset`].
|
||||||
|
///
|
||||||
|
/// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements.
|
||||||
|
///
|
||||||
|
/// # Caveat
|
||||||
|
///
|
||||||
|
/// The lifetime for the returned slice is inferred from its usage. To
|
||||||
|
/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
|
||||||
|
/// source lifetime is safe in the context, such as by providing a helper
|
||||||
|
/// function taking the lifetime of a host value for the slice, or by explicit
|
||||||
|
/// annotation.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(slice_from_ptr_range)]
|
||||||
|
///
|
||||||
|
/// use core::slice;
|
||||||
|
///
|
||||||
|
/// let x = [1, 2, 3];
|
||||||
|
/// let range = x.as_ptr_range();
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// assert_eq!(slice::from_ptr_range(range), &x);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [valid]: ptr#safety
|
||||||
|
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
|
||||||
|
pub unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
|
||||||
|
// SAFETY: the caller must uphold the safety contract for `from_ptr_range`.
|
||||||
|
unsafe { from_raw_parts(range.start, range.end.offset_from(range.start) as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs the same functionality as [`from_ptr_range`], except that a
|
||||||
|
/// mutable slice is returned.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Behavior is undefined if any of the following conditions are violated:
|
||||||
|
///
|
||||||
|
/// * The `start` pointer of the range must be a [valid] and properly aligned pointer
|
||||||
|
/// to the first element of a slice.
|
||||||
|
///
|
||||||
|
/// * The `end` pointer must be a [valid] and properly aligned pointer to *one past*
|
||||||
|
/// the last element, such that the offset from the end to the start pointer is
|
||||||
|
/// the length of the slice.
|
||||||
|
///
|
||||||
|
/// * The range must contain `N` consecutive properly initialized values of type `T`:
|
||||||
|
///
|
||||||
|
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||||
|
/// Slices can never span across multiple allocated objects.
|
||||||
|
///
|
||||||
|
/// * The memory referenced by the returned slice must not be accessed through any other pointer
|
||||||
|
/// (not derived from the return value) for the duration of lifetime `'a`.
|
||||||
|
/// Both read and write accesses are forbidden.
|
||||||
|
///
|
||||||
|
/// * The total length of the range must be no larger than `isize::MAX`.
|
||||||
|
/// See the safety documentation of [`pointer::offset`].
|
||||||
|
///
|
||||||
|
/// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(slice_from_ptr_range)]
|
||||||
|
///
|
||||||
|
/// use core::slice;
|
||||||
|
///
|
||||||
|
/// let mut x = [1, 2, 3];
|
||||||
|
/// let range = x.as_mut_ptr_range();
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// assert_eq!(slice::from_mut_ptr_range(range), &mut [1, 2, 3]);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [valid]: ptr#safety
|
||||||
|
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
|
||||||
|
pub unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] {
|
||||||
|
// SAFETY: the caller must uphold the safety contract for `from_mut_ptr_range`.
|
||||||
|
unsafe { from_raw_parts_mut(range.start, range.end.offset_from(range.start) as usize) }
|
||||||
|
}
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#![feature(pin_macro)]
|
#![feature(pin_macro)]
|
||||||
#![feature(sort_internals)]
|
#![feature(sort_internals)]
|
||||||
#![feature(slice_take)]
|
#![feature(slice_take)]
|
||||||
|
#![feature(slice_from_ptr_range)]
|
||||||
#![feature(maybe_uninit_uninit_array)]
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
#![feature(maybe_uninit_array_assume_init)]
|
#![feature(maybe_uninit_array_assume_init)]
|
||||||
#![feature(maybe_uninit_write_slice)]
|
#![feature(maybe_uninit_write_slice)]
|
||||||
|
@ -2,6 +2,7 @@ use core::cell::Cell;
|
|||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
use core::result::Result::{Err, Ok};
|
use core::result::Result::{Err, Ok};
|
||||||
|
use core::slice;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_position() {
|
fn test_position() {
|
||||||
@ -2480,3 +2481,24 @@ take_tests! {
|
|||||||
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||||
(take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
(take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_slice_from_ptr_range() {
|
||||||
|
let arr = ["foo".to_owned(), "bar".to_owned()];
|
||||||
|
let range = arr.as_ptr_range();
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(slice::from_ptr_range(range), &arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut arr = [1, 2, 3];
|
||||||
|
let range = arr.as_mut_ptr_range();
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(slice::from_mut_ptr_range(range), &mut [1, 2, 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let arr: [Vec<String>; 0] = [];
|
||||||
|
let range = arr.as_ptr_range();
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(slice::from_ptr_range(range), &arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user