Skip to content
/ rust Public
forked from rust-lang/rust
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4374058

Browse files
authoredMar 11, 2024
Rollup merge of rust-lang#121148 - clarfonthey:try-range, r=dtolnay
Add slice::try_range This adds a fallible version of the unstable `slice::range` (tracking: rust-lang#76393) which is highly requested in the tracking issue. Hoping this can slide by without an ACP (since the feature is already being tracked), but let me know otherwise.
2 parents c69fda7 + 290cbdf commit 4374058

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
@@ -704,17 +704,15 @@ where
704704
{
705705
let len = bounds.end;
706706

707-
let start: ops::Bound<&usize> = range.start_bound();
708-
let start = match start {
707+
let start = match range.start_bound() {
709708
ops::Bound::Included(&start) => start,
710709
ops::Bound::Excluded(start) => {
711710
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
712711
}
713712
ops::Bound::Unbounded => 0,
714713
};
715714

716-
let end: ops::Bound<&usize> = range.end_bound();
717-
let end = match end {
715+
let end = match range.end_bound() {
718716
ops::Bound::Included(end) => {
719717
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
720718
}
@@ -732,6 +730,59 @@ where
732730
ops::Range { start, end }
733731
}
734732

733+
/// Performs bounds-checking of a range without panicking.
734+
///
735+
/// This is a version of [`range`] that returns [`None`] instead of panicking.
736+
///
737+
/// # Examples
738+
///
739+
/// ```
740+
/// #![feature(slice_range)]
741+
///
742+
/// use std::slice;
743+
///
744+
/// let v = [10, 40, 30];
745+
/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len()));
746+
/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len()));
747+
/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len()));
748+
/// ```
749+
///
750+
/// Returns [`None`] when [`Index::index`] would panic:
751+
///
752+
/// ```
753+
/// #![feature(slice_range)]
754+
///
755+
/// use std::slice;
756+
///
757+
/// assert_eq!(None, slice::try_range(2..1, ..3));
758+
/// assert_eq!(None, slice::try_range(1..4, ..3));
759+
/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3));
760+
/// ```
761+
///
762+
/// [`Index::index`]: ops::Index::index
763+
#[unstable(feature = "slice_range", issue = "76393")]
764+
#[must_use]
765+
pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
766+
where
767+
R: ops::RangeBounds<usize>,
768+
{
769+
let len = bounds.end;
770+
771+
let start = match range.start_bound() {
772+
ops::Bound::Included(&start) => start,
773+
ops::Bound::Excluded(start) => start.checked_add(1)?,
774+
ops::Bound::Unbounded => 0,
775+
};
776+
777+
let end = match range.end_bound() {
778+
ops::Bound::Included(end) => end.checked_add(1)?,
779+
ops::Bound::Excluded(&end) => end,
780+
ops::Bound::Unbounded => len,
781+
};
782+
783+
if start > end || end > len { None } else { Some(ops::Range { start, end }) }
784+
}
785+
735786
/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
736787
pub(crate) fn into_range_unchecked(
737788
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)
Please sign in to comment.