@@ -37,28 +37,28 @@ fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
37
37
#[ inline( never) ]
38
38
#[ cold]
39
39
#[ 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 ) -> ! {
41
41
panic ! ( "range end index {} out of range for slice of length {}" , index, len) ;
42
42
}
43
43
44
44
#[ inline( never) ]
45
45
#[ cold]
46
46
#[ track_caller]
47
- pub ( crate ) fn slice_index_order_fail ( index : usize , end : usize ) -> ! {
47
+ fn slice_index_order_fail ( index : usize , end : usize ) -> ! {
48
48
panic ! ( "slice index starts at {} but ends at {}" , index, end) ;
49
49
}
50
50
51
51
#[ inline( never) ]
52
52
#[ cold]
53
53
#[ track_caller]
54
- pub ( crate ) fn slice_start_index_overflow_fail ( ) -> ! {
54
+ fn slice_start_index_overflow_fail ( ) -> ! {
55
55
panic ! ( "attempted to index slice from after maximum usize" ) ;
56
56
}
57
57
58
58
#[ inline( never) ]
59
59
#[ cold]
60
60
#[ track_caller]
61
- pub ( crate ) fn slice_end_index_overflow_fail ( ) -> ! {
61
+ fn slice_end_index_overflow_fail ( ) -> ! {
62
62
panic ! ( "attempted to index slice up to maximum usize" ) ;
63
63
}
64
64
@@ -449,3 +449,100 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
449
449
( 0 ..=self . end ) . index_mut ( slice)
450
450
}
451
451
}
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