@@ -704,17 +704,15 @@ where
704
704
{
705
705
let len = bounds. end ;
706
706
707
- let start: ops:: Bound < & usize > = range. start_bound ( ) ;
708
- let start = match start {
707
+ let start = match range. start_bound ( ) {
709
708
ops:: Bound :: Included ( & start) => start,
710
709
ops:: Bound :: Excluded ( start) => {
711
710
start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
712
711
}
713
712
ops:: Bound :: Unbounded => 0 ,
714
713
} ;
715
714
716
- let end: ops:: Bound < & usize > = range. end_bound ( ) ;
717
- let end = match end {
715
+ let end = match range. end_bound ( ) {
718
716
ops:: Bound :: Included ( end) => {
719
717
end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
720
718
}
@@ -732,6 +730,59 @@ where
732
730
ops:: Range { start, end }
733
731
}
734
732
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
+
735
786
/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
736
787
pub ( crate ) fn into_range_unchecked (
737
788
len : usize ,
0 commit comments