@@ -81,6 +81,8 @@ mod private_slice_index {
81
81
impl Sealed for ops:: RangeInclusive < usize > { }
82
82
#[ stable( feature = "slice_get_slice" , since = "1.28.0" ) ]
83
83
impl Sealed for ops:: RangeToInclusive < usize > { }
84
+ #[ stable( feature = "slice_index_with_ops_bound_pair" , since = "1.53.0" ) ]
85
+ impl Sealed for ( ops:: Bound < usize > , ops:: Bound < usize > ) { }
84
86
}
85
87
86
88
/// A helper trait used for indexing operations.
@@ -546,3 +548,113 @@ where
546
548
547
549
ops:: Range { start, end }
548
550
}
551
+
552
+ /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
553
+ fn into_range_unchecked (
554
+ len : usize ,
555
+ ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
556
+ ) -> ops:: Range < usize > {
557
+ use ops:: Bound ;
558
+ let start = match start {
559
+ Bound :: Included ( i) => i,
560
+ Bound :: Excluded ( i) => i + 1 ,
561
+ Bound :: Unbounded => 0 ,
562
+ } ;
563
+ let end = match end {
564
+ Bound :: Included ( i) => i + 1 ,
565
+ Bound :: Excluded ( i) => i,
566
+ Bound :: Unbounded => len,
567
+ } ;
568
+ start..end
569
+ }
570
+
571
+ /// Convert pair of `ops::Bound`s into `ops::Range`.
572
+ /// Returns `None` on overflowing indices.
573
+ fn into_range (
574
+ len : usize ,
575
+ ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
576
+ ) -> Option < ops:: Range < usize > > {
577
+ use ops:: Bound ;
578
+ let start = match start {
579
+ Bound :: Included ( start) => start,
580
+ Bound :: Excluded ( start) => start. checked_add ( 1 ) ?,
581
+ Bound :: Unbounded => 0 ,
582
+ } ;
583
+
584
+ let end = match end {
585
+ Bound :: Included ( end) => end. checked_add ( 1 ) ?,
586
+ Bound :: Excluded ( end) => end,
587
+ Bound :: Unbounded => len,
588
+ } ;
589
+
590
+ // Don't bother with checking `start < end` and `end <= len`
591
+ // since these checks are handled by `Range` impls
592
+
593
+ Some ( start..end)
594
+ }
595
+
596
+ /// Convert pair of `ops::Bound`s into `ops::Range`.
597
+ /// Panics on overflowing indices.
598
+ fn into_slice_range (
599
+ len : usize ,
600
+ ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
601
+ ) -> ops:: Range < usize > {
602
+ use ops:: Bound ;
603
+ let start = match start {
604
+ Bound :: Included ( start) => start,
605
+ Bound :: Excluded ( start) => {
606
+ start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
607
+ }
608
+ Bound :: Unbounded => 0 ,
609
+ } ;
610
+
611
+ let end = match end {
612
+ Bound :: Included ( end) => {
613
+ end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
614
+ }
615
+ Bound :: Excluded ( end) => end,
616
+ Bound :: Unbounded => len,
617
+ } ;
618
+
619
+ // Don't bother with checking `start < end` and `end <= len`
620
+ // since these checks are handled by `Range` impls
621
+
622
+ start..end
623
+ }
624
+
625
+ #[ stable( feature = "slice_index_with_ops_bound_pair" , since = "1.53.0" ) ]
626
+ unsafe impl < T > SliceIndex < [ T ] > for ( ops:: Bound < usize > , ops:: Bound < usize > ) {
627
+ type Output = [ T ] ;
628
+
629
+ #[ inline]
630
+ fn get ( self , slice : & [ T ] ) -> Option < & Self :: Output > {
631
+ into_range ( slice. len ( ) , self ) ?. get ( slice)
632
+ }
633
+
634
+ #[ inline]
635
+ fn get_mut ( self , slice : & mut [ T ] ) -> Option < & mut Self :: Output > {
636
+ into_range ( slice. len ( ) , self ) ?. get_mut ( slice)
637
+ }
638
+
639
+ #[ inline]
640
+ unsafe fn get_unchecked ( self , slice : * const [ T ] ) -> * const Self :: Output {
641
+ // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
642
+ unsafe { into_range_unchecked ( slice. len ( ) , self ) . get_unchecked ( slice) }
643
+ }
644
+
645
+ #[ inline]
646
+ unsafe fn get_unchecked_mut ( self , slice : * mut [ T ] ) -> * mut Self :: Output {
647
+ // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
648
+ unsafe { into_range_unchecked ( slice. len ( ) , self ) . get_unchecked_mut ( slice) }
649
+ }
650
+
651
+ #[ inline]
652
+ fn index ( self , slice : & [ T ] ) -> & Self :: Output {
653
+ into_slice_range ( slice. len ( ) , self ) . index ( slice)
654
+ }
655
+
656
+ #[ inline]
657
+ fn index_mut ( self , slice : & mut [ T ] ) -> & mut Self :: Output {
658
+ into_slice_range ( slice. len ( ) , self ) . index_mut ( slice)
659
+ }
660
+ }
0 commit comments