use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
use crate::Stride;
mod private {
use super::*;
pub trait Sealed {}
impl Sealed for usize {}
impl Sealed for Range<usize> {}
impl Sealed for RangeFrom<usize> {}
impl Sealed for RangeFull {}
impl Sealed for RangeInclusive<usize> {}
impl Sealed for RangeTo<usize> {}
impl Sealed for RangeToInclusive<usize> {}
}
trait Unstride: private::Sealed {
fn unstride<const S: usize>(self) -> Self;
}
pub unsafe trait StrideIndex<T: ?Sized>: private::Sealed {
type Output: ?Sized;
fn get(self, stride: &T) -> Option<&Self::Output>;
fn get_mut(self, stride: &mut T) -> Option<&mut Self::Output>;
unsafe fn get_unchecked(self, stride: *const T) -> *const Self::Output;
unsafe fn get_unchecked_mut(self, stride: *mut T) -> *mut Self::Output;
#[track_caller]
fn index(self, stride: &T) -> &Self::Output;
#[track_caller]
fn index_mut(self, stride: &mut T) -> &mut Self::Output;
}
impl Unstride for usize {
fn unstride<const S: usize>(self) -> Self {
self * S
}
}
impl Unstride for Range<usize> {
fn unstride<const S: usize>(self) -> Self {
Range {
start: self.start * S,
end: self.end * S,
}
}
}
impl Unstride for RangeFrom<usize> {
fn unstride<const S: usize>(self) -> Self {
RangeFrom {
start: self.start * S,
}
}
}
impl Unstride for RangeFull {
fn unstride<const S: usize>(self) -> Self {
self
}
}
impl Unstride for RangeInclusive<usize> {
fn unstride<const S: usize>(self) -> Self {
RangeInclusive::new(self.start() * S, self.end() * S)
}
}
impl Unstride for RangeTo<usize> {
fn unstride<const S: usize>(self) -> Self {
RangeTo { end: self.end * S }
}
}
impl Unstride for RangeToInclusive<usize> {
fn unstride<const S: usize>(self) -> Self {
RangeToInclusive { end: self.end * S }
}
}
unsafe impl<T, const S: usize> StrideIndex<Stride<T, S>> for usize {
type Output = T;
fn get(self, stride: &Stride<T, S>) -> Option<&Self::Output> {
let i = self.unstride::<S>();
stride.data.get(i)
}
fn get_mut(self, stride: &mut Stride<T, S>) -> Option<&mut Self::Output> {
let i = self.unstride::<S>();
stride.data.get_mut(i)
}
unsafe fn get_unchecked(self, stride: *const Stride<T, S>) -> *const Self::Output {
let i = self.unstride::<S>();
unsafe { (*stride).data.get_unchecked(i) }
}
unsafe fn get_unchecked_mut(self, stride: *mut Stride<T, S>) -> *mut Self::Output {
let i = self.unstride::<S>();
unsafe { (*stride).data.get_unchecked_mut(i) }
}
#[track_caller]
fn index(self, stride: &Stride<T, S>) -> &Self::Output {
let i = self.unstride::<S>();
&stride.data[i]
}
#[track_caller]
fn index_mut(self, stride: &mut Stride<T, S>) -> &mut Self::Output {
let i = self.unstride::<S>();
&mut stride.data[i]
}
}
macro_rules! impl_stride_index {
($Index:ty) => {
unsafe impl<T, const S: usize> StrideIndex<Stride<T, S>> for $Index {
type Output = Stride<T, S>;
fn get(self, stride: &Stride<T, S>) -> Option<&Self::Output> {
let i = self.unstride::<S>();
stride.data.get(i).map(Stride::new)
}
fn get_mut(self, stride: &mut Stride<T, S>) -> Option<&mut Self::Output> {
let i = self.unstride::<S>();
stride.data.get_mut(i).map(Stride::new_mut)
}
unsafe fn get_unchecked(self, stride: *const Stride<T, S>) -> *const Self::Output {
let i = self.unstride::<S>();
let slice = unsafe { (*stride).data.get_unchecked(i) };
Stride::new(slice)
}
unsafe fn get_unchecked_mut(self, stride: *mut Stride<T, S>) -> *mut Self::Output {
let i = self.unstride::<S>();
let slice = unsafe { (*stride).data.get_unchecked_mut(i) };
Stride::new_mut(slice)
}
#[track_caller]
fn index(self, stride: &Stride<T, S>) -> &Self::Output {
let i = self.unstride::<S>();
Stride::new(&stride.data[i])
}
#[track_caller]
fn index_mut(self, stride: &mut Stride<T, S>) -> &mut Self::Output {
let i = self.unstride::<S>();
Stride::new_mut(&mut stride.data[i])
}
}
};
}
impl_stride_index! { Range<usize> }
impl_stride_index! { RangeFrom<usize> }
impl_stride_index! { RangeFull }
impl_stride_index! { RangeInclusive<usize> }
impl_stride_index! { RangeTo<usize> }
impl_stride_index! { RangeToInclusive<usize> }