Skip to content

Commit 290cbdf

Browse files
committed
Add slice::try_range
1 parent fa9f77f commit 290cbdf

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

library/alloc/src/slice.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ use crate::vec::Vec;
3333
#[cfg(test)]
3434
mod tests;
3535

36-
#[unstable(feature = "slice_range", issue = "76393")]
37-
pub use core::slice::range;
3836
#[unstable(feature = "array_chunks", issue = "74985")]
3937
pub use core::slice::ArrayChunks;
4038
#[unstable(feature = "array_chunks", issue = "74985")]
@@ -51,6 +49,8 @@ pub use core::slice::{from_mut, from_ref};
5149
pub use core::slice::{from_mut_ptr_range, from_ptr_range};
5250
#[stable(feature = "rust1", since = "1.0.0")]
5351
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
52+
#[unstable(feature = "slice_range", issue = "76393")]
53+
pub use core::slice::{range, try_range};
5454
#[stable(feature = "slice_group_by", since = "1.77.0")]
5555
pub use core::slice::{ChunkBy, ChunkByMut};
5656
#[stable(feature = "rust1", since = "1.0.0")]

library/core/src/slice/index.rs

+55-4
Original file line numberDiff line numberDiff line change
@@ -681,17 +681,15 @@ where
681681
{
682682
let len = bounds.end;
683683

684-
let start: ops::Bound<&usize> = range.start_bound();
685-
let start = match start {
684+
let start = match range.start_bound() {
686685
ops::Bound::Included(&start) => start,
687686
ops::Bound::Excluded(start) => {
688687
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
689688
}
690689
ops::Bound::Unbounded => 0,
691690
};
692691

693-
let end: ops::Bound<&usize> = range.end_bound();
694-
let end = match end {
692+
let end = match range.end_bound() {
695693
ops::Bound::Included(end) => {
696694
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
697695
}
@@ -709,6 +707,59 @@ where
709707
ops::Range { start, end }
710708
}
711709

710+
/// Performs bounds-checking of a range without panicking.
711+
///
712+
/// This is a version of [`range`] that returns [`None`] instead of panicking.
713+
///
714+
/// # Examples
715+
///
716+
/// ```
717+
/// #![feature(slice_range)]
718+
///
719+
/// use std::slice;
720+
///
721+
/// let v = [10, 40, 30];
722+
/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len()));
723+
/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len()));
724+
/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len()));
725+
/// ```
726+
///
727+
/// Returns [`None`] when [`Index::index`] would panic:
728+
///
729+
/// ```
730+
/// #![feature(slice_range)]
731+
///
732+
/// use std::slice;
733+
///
734+
/// assert_eq!(None, slice::try_range(2..1, ..3));
735+
/// assert_eq!(None, slice::try_range(1..4, ..3));
736+
/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3));
737+
/// ```
738+
///
739+
/// [`Index::index`]: ops::Index::index
740+
#[unstable(feature = "slice_range", issue = "76393")]
741+
#[must_use]
742+
pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
743+
where
744+
R: ops::RangeBounds<usize>,
745+
{
746+
let len = bounds.end;
747+
748+
let start = match range.start_bound() {
749+
ops::Bound::Included(&start) => start,
750+
ops::Bound::Excluded(start) => start.checked_add(1)?,
751+
ops::Bound::Unbounded => 0,
752+
};
753+
754+
let end = match range.end_bound() {
755+
ops::Bound::Included(end) => end.checked_add(1)?,
756+
ops::Bound::Excluded(&end) => end,
757+
ops::Bound::Unbounded => len,
758+
};
759+
760+
if start > end || end > len { None } else { Some(ops::Range { start, end }) }
761+
}
762+
712763
/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
713764
pub(crate) fn into_range_unchecked(
714765
len: usize,

library/core/src/slice/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub use sort::heapsort;
9191
pub use index::SliceIndex;
9292

9393
#[unstable(feature = "slice_range", issue = "76393")]
94-
pub use index::range;
94+
pub use index::{range, try_range};
9595

9696
#[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
9797
pub use ascii::EscapeAscii;

0 commit comments

Comments
 (0)