@@ -81,6 +81,8 @@ mod private_slice_index {
8181 impl Sealed for ops:: RangeInclusive < usize > { }
8282 #[ stable( feature = "slice_get_slice" , since = "1.28.0" ) ]
8383 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 > ) { }
8486}
8587
8688/// A helper trait used for indexing operations.
@@ -546,3 +548,113 @@ where
546548
547549 ops:: Range { start, end }
548550}
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