| #![unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| //! Helper types for indexing slices. | |
| use crate::intrinsics::slice_get_unchecked; | |
| use crate::slice::SliceIndex; | |
| use crate::{cmp, ops, range}; | |
| /// Clamps an index, guaranteeing that it will only access valid elements of the slice. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(sliceindex_wrappers)] | |
| /// | |
| /// use core::index::Clamp; | |
| /// | |
| /// let s: &[usize] = &[0, 1, 2, 3]; | |
| /// | |
| /// assert_eq!(&3, &s[Clamp(6)]); | |
| /// assert_eq!(&[1, 2, 3], &s[Clamp(1..6)]); | |
| /// assert_eq!(&[] as &[usize], &s[Clamp(5..6)]); | |
| /// assert_eq!(&[0, 1, 2, 3], &s[Clamp(..6)]); | |
| /// assert_eq!(&[0, 1, 2, 3], &s[Clamp(..=6)]); | |
| /// assert_eq!(&[] as &[usize], &s[Clamp(6..)]); | |
| /// ``` | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| #[derive(Debug)] | |
| pub struct Clamp<Idx>(pub Idx); | |
| /// Always accesses the last element of the slice. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(sliceindex_wrappers)] | |
| /// #![feature(slice_index_methods)] | |
| /// | |
| /// use core::index::Last; | |
| /// use core::slice::SliceIndex; | |
| /// | |
| /// let s = &[0, 1, 2, 3]; | |
| /// | |
| /// assert_eq!(&3, &s[Last]); | |
| /// assert_eq!(None, Last.get(&[] as &[usize])); | |
| /// | |
| /// ``` | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| #[derive(Debug)] | |
| pub struct Last; | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<usize> { | |
| type Output = T; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| slice.get(cmp::min(self.0, slice.len() - 1)) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| slice.get_mut(cmp::min(self.0, slice.len() - 1)) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { slice_get_unchecked(slice, cmp::min(self.0, slice.len() - 1)) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { slice_get_unchecked(slice, cmp::min(self.0, slice.len() - 1)) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| &(*slice)[cmp::min(self.0, slice.len() - 1)] | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| &mut (*slice)[cmp::min(self.0, slice.len() - 1)] | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<range::Range<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| // SAFETY: a range ending before len is always valid | |
| unsafe { (start..end).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| // SAFETY: a range ending before len is always valid | |
| unsafe { (start..end).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<ops::Range<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| // SAFETY: a range ending before len is always valid | |
| unsafe { (start..end).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| // SAFETY: a range ending before len is always valid | |
| unsafe { (start..end).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len()); | |
| let end = cmp::min(self.0.end, slice.len()); | |
| (start..end).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeInclusive<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.last, slice.len() - 1); | |
| (start..=end).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.last, slice.len() - 1); | |
| (start..=end).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.last, slice.len() - 1); | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (start..=end).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.last, slice.len() - 1); | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (start..=end).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.last, slice.len() - 1); | |
| (start..=end).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.last, slice.len() - 1); | |
| (start..=end).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<ops::RangeInclusive<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.end, slice.len() - 1); | |
| (start..=end).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.end, slice.len() - 1); | |
| (start..=end).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.end, slice.len() - 1); | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (start..=end).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.end, slice.len() - 1); | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (start..=end).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.end, slice.len() - 1); | |
| (start..=end).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| let start = cmp::min(self.0.start, slice.len() - 1); | |
| let end = cmp::min(self.0.end, slice.len() - 1); | |
| (start..=end).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeFrom<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| (cmp::min(self.0.start, slice.len())..).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| (cmp::min(self.0.start, slice.len())..).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: a range starting at len is valid | |
| unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: a range starting at len is valid | |
| unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| (cmp::min(self.0.start, slice.len())..).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| (cmp::min(self.0.start, slice.len())..).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<ops::RangeFrom<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| (cmp::min(self.0.start, slice.len())..).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| (cmp::min(self.0.start, slice.len())..).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: a range starting at len is valid | |
| unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: a range starting at len is valid | |
| unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| (cmp::min(self.0.start, slice.len())..).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| (cmp::min(self.0.start, slice.len())..).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<ops::RangeTo<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| (..cmp::min(self.0.end, slice.len())).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| (..cmp::min(self.0.end, slice.len())).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: a range ending before len is always valid | |
| unsafe { (..cmp::min(self.0.end, slice.len())).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: a range ending before len is always valid | |
| unsafe { (..cmp::min(self.0.end, slice.len())).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| (..cmp::min(self.0.end, slice.len())).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| (..cmp::min(self.0.end, slice.len())).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeToInclusive<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| (..=cmp::min(self.0.last, slice.len() - 1)).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| (..=cmp::min(self.0.last, slice.len() - 1)).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (..=cmp::min(self.0.last, slice.len() - 1)).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (..=cmp::min(self.0.last, slice.len() - 1)).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| (..=cmp::min(self.0.last, slice.len() - 1)).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| (..=cmp::min(self.0.last, slice.len() - 1)).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<ops::RangeToInclusive<usize>> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| (..=cmp::min(self.0.end, slice.len() - 1)).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| (..=cmp::min(self.0.end, slice.len() - 1)).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (..=cmp::min(self.0.end, slice.len() - 1)).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { (..=cmp::min(self.0.end, slice.len() - 1)).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| (..=cmp::min(self.0.end, slice.len() - 1)).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| (..=cmp::min(self.0.end, slice.len() - 1)).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Clamp<ops::RangeFull> { | |
| type Output = [T]; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| (..).get(slice) | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| (..).get_mut(slice) | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: RangeFull just returns `slice` here | |
| unsafe { (..).get_unchecked(slice) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: RangeFull just returns `slice` here | |
| unsafe { (..).get_unchecked_mut(slice) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| (..).index(slice) | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| (..).index_mut(slice) | |
| } | |
| } | |
| #[unstable(feature = "sliceindex_wrappers", issue = "146179")] | |
| unsafe impl<T> SliceIndex<[T]> for Last { | |
| type Output = T; | |
| fn get(self, slice: &[T]) -> Option<&Self::Output> { | |
| slice.last() | |
| } | |
| fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { | |
| slice.last_mut() | |
| } | |
| unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { slice_get_unchecked(slice, slice.len() - 1) } | |
| } | |
| unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { | |
| // SAFETY: the caller ensures that the slice isn't empty | |
| unsafe { slice_get_unchecked(slice, slice.len() - 1) } | |
| } | |
| fn index(self, slice: &[T]) -> &Self::Output { | |
| // N.B., use intrinsic indexing | |
| &(*slice)[slice.len() - 1] | |
| } | |
| fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { | |
| // N.B., use intrinsic indexing | |
| &mut (*slice)[slice.len() - 1] | |
| } | |
| } |