mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Add slice::check_range
This commit is contained in:
parent
22ee68dc58
commit
bb70e52f5f
@ -30,7 +30,7 @@ use crate::intrinsics::{assume, exact_div, is_aligned_and_not_null, unchecked_su
|
||||
use crate::iter::*;
|
||||
use crate::marker::{self, Copy, Send, Sized, Sync};
|
||||
use crate::mem;
|
||||
use crate::ops::{self, FnMut, Range};
|
||||
use crate::ops::{self, Bound, FnMut, Range, RangeBounds};
|
||||
use crate::option::Option;
|
||||
use crate::option::Option::{None, Some};
|
||||
use crate::ptr::{self, NonNull};
|
||||
@ -350,6 +350,80 @@ impl<T> [T] {
|
||||
unsafe { &mut *index.get_unchecked_mut(self) }
|
||||
}
|
||||
|
||||
/// Converts a range over this slice to [`Range`].
|
||||
///
|
||||
/// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
|
||||
///
|
||||
/// [`get_unchecked`]: #method.get_unchecked
|
||||
/// [`get_unchecked_mut`]: #method.get_unchecked_mut
|
||||
/// [`Range`]: ../ops/struct.Range.html
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the range is out of bounds.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_check_range)]
|
||||
///
|
||||
/// let v = [10, 40, 30];
|
||||
/// assert_eq!(1..2, v.check_range(1..2));
|
||||
/// assert_eq!(0..2, v.check_range(..2));
|
||||
/// assert_eq!(1..3, v.check_range(1..));
|
||||
/// ```
|
||||
///
|
||||
/// Panics when [`Index::index`] would panic:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(slice_check_range)]
|
||||
///
|
||||
/// [10, 40, 30].check_range(2..1);
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(slice_check_range)]
|
||||
///
|
||||
/// [10, 40, 30].check_range(1..4);
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(slice_check_range)]
|
||||
///
|
||||
/// [10, 40, 30].check_range(1..=usize::MAX);
|
||||
/// ```
|
||||
///
|
||||
/// [`Index::index`]: ../ops/trait.Index.html#tymethod.index
|
||||
#[track_caller]
|
||||
#[unstable(feature = "slice_check_range", issue = "none")]
|
||||
pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
|
||||
let start = match range.start_bound() {
|
||||
Bound::Included(&start) => start,
|
||||
Bound::Excluded(start) => {
|
||||
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
|
||||
}
|
||||
Bound::Unbounded => 0,
|
||||
};
|
||||
|
||||
let len = self.len();
|
||||
let end = match range.end_bound() {
|
||||
Bound::Included(end) => {
|
||||
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
|
||||
}
|
||||
Bound::Excluded(&end) => end,
|
||||
Bound::Unbounded => len,
|
||||
};
|
||||
|
||||
if start > end {
|
||||
slice_index_order_fail(start, end);
|
||||
}
|
||||
if end > len {
|
||||
slice_end_index_len_fail(end, len);
|
||||
}
|
||||
|
||||
Range { start, end }
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the slice's buffer.
|
||||
///
|
||||
/// The caller must ensure that the slice outlives the pointer this
|
||||
@ -2445,13 +2519,13 @@ impl<T> [T] {
|
||||
let src_start = match src.start_bound() {
|
||||
ops::Bound::Included(&n) => n,
|
||||
ops::Bound::Excluded(&n) => {
|
||||
n.checked_add(1).unwrap_or_else(|| slice_index_overflow_fail())
|
||||
n.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
|
||||
}
|
||||
ops::Bound::Unbounded => 0,
|
||||
};
|
||||
let src_end = match src.end_bound() {
|
||||
ops::Bound::Included(&n) => {
|
||||
n.checked_add(1).unwrap_or_else(|| slice_index_overflow_fail())
|
||||
n.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
|
||||
}
|
||||
ops::Bound::Excluded(&n) => n,
|
||||
ops::Bound::Unbounded => self.len(),
|
||||
@ -3034,7 +3108,14 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
fn slice_index_overflow_fail() -> ! {
|
||||
fn slice_start_index_overflow_fail() -> ! {
|
||||
panic!("attempted to index slice from after maximum usize");
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
fn slice_end_index_overflow_fail() -> ! {
|
||||
panic!("attempted to index slice up to maximum usize");
|
||||
}
|
||||
|
||||
@ -3370,7 +3451,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
|
||||
#[inline]
|
||||
fn index(self, slice: &[T]) -> &[T] {
|
||||
if *self.end() == usize::MAX {
|
||||
slice_index_overflow_fail();
|
||||
slice_end_index_overflow_fail();
|
||||
}
|
||||
(*self.start()..self.end() + 1).index(slice)
|
||||
}
|
||||
@ -3378,7 +3459,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||
if *self.end() == usize::MAX {
|
||||
slice_index_overflow_fail();
|
||||
slice_end_index_overflow_fail();
|
||||
}
|
||||
(*self.start()..self.end() + 1).index_mut(slice)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user