@@ -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
713764pub ( crate ) fn into_range_unchecked (
714765 len : usize ,
0 commit comments