Skip to content

Commit 8ac8935

Browse files
committed
Add SliceIndex impl for pair of Bounds
1 parent 2e46cb3 commit 8ac8935

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

library/core/src/slice/index.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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_bound_pair", since = "1.51.0")]
85+
impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
8486
}
8587

8688
/// A helper trait used for indexing operations.
@@ -449,3 +451,104 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
449451
(0..=self.end).index_mut(slice)
450452
}
451453
}
454+
455+
#[stable(feature = "slice_index_bound_pair", since = "1.51.0")]
456+
unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
457+
type Output = [T];
458+
459+
#[inline]
460+
fn get(self, slice: &[T]) -> Option<&[T]> {
461+
let start = match self.0 {
462+
ops::Bound::Unbounded => 0,
463+
ops::Bound::Included(start) => start,
464+
ops::Bound::Excluded(start) => start.checked_add(1)?,
465+
};
466+
let end = match self.1 {
467+
ops::Bound::Unbounded => slice.len(),
468+
ops::Bound::Included(end) => end.checked_add(1)?,
469+
ops::Bound::Excluded(end) => end,
470+
};
471+
(start..end).get(slice)
472+
}
473+
474+
#[inline]
475+
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
476+
let start = match self.0 {
477+
ops::Bound::Unbounded => 0,
478+
ops::Bound::Included(start) => start,
479+
ops::Bound::Excluded(start) => start.checked_add(1)?,
480+
};
481+
let end = match self.1 {
482+
ops::Bound::Unbounded => slice.len(),
483+
ops::Bound::Included(end) => end.checked_add(1)?,
484+
ops::Bound::Excluded(end) => end,
485+
};
486+
(start..end).get_mut(slice)
487+
}
488+
489+
#[inline]
490+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
491+
let start = match self.0 {
492+
ops::Bound::Unbounded => 0,
493+
ops::Bound::Included(start) => start,
494+
ops::Bound::Excluded(start) => start + 1,
495+
};
496+
let end = match self.1 {
497+
ops::Bound::Unbounded => slice.len(),
498+
ops::Bound::Included(end) => end + 1,
499+
ops::Bound::Excluded(end) => end,
500+
};
501+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
502+
unsafe { (start..end).get_unchecked(slice) }
503+
}
504+
505+
#[inline]
506+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
507+
let start = match self.0 {
508+
ops::Bound::Unbounded => 0,
509+
ops::Bound::Included(start) => start,
510+
ops::Bound::Excluded(start) => start + 1,
511+
};
512+
let end = match self.1 {
513+
ops::Bound::Unbounded => slice.len(),
514+
ops::Bound::Included(end) => end + 1,
515+
ops::Bound::Excluded(end) => end,
516+
};
517+
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
518+
unsafe { (start..end).get_unchecked_mut(slice) }
519+
}
520+
521+
#[inline]
522+
fn index(self, slice: &[T]) -> &[T] {
523+
let start = match self.0 {
524+
ops::Bound::Unbounded => 0,
525+
ops::Bound::Included(start) => start,
526+
ops::Bound::Excluded(start) if start == usize::MAX => slice_start_index_overflow_fail(),
527+
ops::Bound::Excluded(start) => start + 1,
528+
};
529+
let end = match self.1 {
530+
ops::Bound::Unbounded => slice.len(),
531+
ops::Bound::Included(end) if end == usize::MAX => slice_end_index_overflow_fail(),
532+
ops::Bound::Included(end) => end + 1,
533+
ops::Bound::Excluded(end) => end,
534+
};
535+
(start..end).index(slice)
536+
}
537+
538+
#[inline]
539+
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
540+
let start = match self.0 {
541+
ops::Bound::Unbounded => 0,
542+
ops::Bound::Included(start) => start,
543+
ops::Bound::Excluded(start) if start == usize::MAX => slice_start_index_overflow_fail(),
544+
ops::Bound::Excluded(start) => start + 1,
545+
};
546+
let end = match self.1 {
547+
ops::Bound::Unbounded => slice.len(),
548+
ops::Bound::Included(end) if end == usize::MAX => slice_end_index_overflow_fail(),
549+
ops::Bound::Included(end) => end + 1,
550+
ops::Bound::Excluded(end) => end,
551+
};
552+
(start..end).index_mut(slice)
553+
}
554+
}

0 commit comments

Comments
 (0)