blob: 3baefdf10cecb22a60fcf4ab74b7c19cb2aee485 [file] [log] [blame] [edit]
#![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<range::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<range::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]
}
}