@@ -37,28 +37,28 @@ fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
3737#[ inline( never) ]
3838#[ cold]
3939#[ track_caller]
40- pub ( crate ) fn slice_end_index_len_fail ( index : usize , len : usize ) -> ! {
40+ fn slice_end_index_len_fail ( index : usize , len : usize ) -> ! {
4141 panic ! ( "range end index {} out of range for slice of length {}" , index, len) ;
4242}
4343
4444#[ inline( never) ]
4545#[ cold]
4646#[ track_caller]
47- pub ( crate ) fn slice_index_order_fail ( index : usize , end : usize ) -> ! {
47+ fn slice_index_order_fail ( index : usize , end : usize ) -> ! {
4848 panic ! ( "slice index starts at {} but ends at {}" , index, end) ;
4949}
5050
5151#[ inline( never) ]
5252#[ cold]
5353#[ track_caller]
54- pub ( crate ) fn slice_start_index_overflow_fail ( ) -> ! {
54+ fn slice_start_index_overflow_fail ( ) -> ! {
5555 panic ! ( "attempted to index slice from after maximum usize" ) ;
5656}
5757
5858#[ inline( never) ]
5959#[ cold]
6060#[ track_caller]
61- pub ( crate ) fn slice_end_index_overflow_fail ( ) -> ! {
61+ fn slice_end_index_overflow_fail ( ) -> ! {
6262 panic ! ( "attempted to index slice up to maximum usize" ) ;
6363}
6464
@@ -449,3 +449,100 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
449449 ( 0 ..=self . end ) . index_mut ( slice)
450450 }
451451}
452+
453+ /// Performs bounds-checking of a range.
454+ ///
455+ /// This method is similar to [`Index::index`] for slices, but it returns a
456+ /// [`Range`] equivalent to `range`. You can use this method to turn any range
457+ /// into `start` and `end` values.
458+ ///
459+ /// `bounds` is the range of the slice to use for bounds-checking. It should
460+ /// be a [`RangeTo`] range that ends at the length of the slice.
461+ ///
462+ /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
463+ /// [`slice::get_unchecked_mut`] for slices with the given range.
464+ ///
465+ /// [`Range`]: ops::Range
466+ /// [`RangeTo`]: ops::RangeTo
467+ /// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
468+ /// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
469+ ///
470+ /// # Panics
471+ ///
472+ /// Panics if `range` would be out of bounds.
473+ ///
474+ /// # Examples
475+ ///
476+ /// ```
477+ /// #![feature(slice_range)]
478+ ///
479+ /// use std::slice;
480+ ///
481+ /// let v = [10, 40, 30];
482+ /// assert_eq!(1..2, slice::range(1..2, ..v.len()));
483+ /// assert_eq!(0..2, slice::range(..2, ..v.len()));
484+ /// assert_eq!(1..3, slice::range(1.., ..v.len()));
485+ /// ```
486+ ///
487+ /// Panics when [`Index::index`] would panic:
488+ ///
489+ /// ```should_panic
490+ /// #![feature(slice_range)]
491+ ///
492+ /// use std::slice;
493+ ///
494+ /// slice::range(2..1, ..3);
495+ /// ```
496+ ///
497+ /// ```should_panic
498+ /// #![feature(slice_range)]
499+ ///
500+ /// use std::slice;
501+ ///
502+ /// slice::range(1..4, ..3);
503+ /// ```
504+ ///
505+ /// ```should_panic
506+ /// #![feature(slice_range)]
507+ ///
508+ /// use std::slice;
509+ ///
510+ /// slice::range(1..=usize::MAX, ..3);
511+ /// ```
512+ ///
513+ /// [`Index::index`]: ops::Index::index
514+ #[ track_caller]
515+ #[ unstable( feature = "slice_range" , issue = "76393" ) ]
516+ pub fn range < R > ( range : R , bounds : ops:: RangeTo < usize > ) -> ops:: Range < usize >
517+ where
518+ R : ops:: RangeBounds < usize > ,
519+ {
520+ let len = bounds. end ;
521+
522+ let start: ops:: Bound < & usize > = range. start_bound ( ) ;
523+ let start = match start {
524+ ops:: Bound :: Included ( & start) => start,
525+ ops:: Bound :: Excluded ( start) => {
526+ start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
527+ }
528+ ops:: Bound :: Unbounded => 0 ,
529+ } ;
530+
531+ let end: ops:: Bound < & usize > = range. end_bound ( ) ;
532+ let end = match end {
533+ ops:: Bound :: Included ( end) => {
534+ end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
535+ }
536+ ops:: Bound :: Excluded ( & end) => end,
537+ ops:: Bound :: Unbounded => len,
538+ } ;
539+
540+ if start > end {
541+ slice_index_order_fail ( start, end) ;
542+ }
543+ if end > len {
544+ slice_end_index_len_fail ( end, len) ;
545+ }
546+
547+ ops:: Range { start, end }
548+ }
0 commit comments