1use core::ops::{
2 Bound, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
3};
4
5use crate::index;
6use crate::layout::{Dense, Layout};
7use crate::mapping::Mapping;
8use crate::shape::Shape;
9use crate::slice::Slice;
10
11pub trait SliceIndex<T, S: Shape, L: Layout> {
13 type Output: ?Sized;
15
16 #[doc(hidden)]
17 unsafe fn get_unchecked(self, slice: &Slice<T, S, L>) -> &Self::Output;
18
19 #[doc(hidden)]
20 unsafe fn get_unchecked_mut(self, slice: &mut Slice<T, S, L>) -> &mut Self::Output;
21
22 #[doc(hidden)]
23 fn index(self, slice: &Slice<T, S, L>) -> &Self::Output;
24
25 #[doc(hidden)]
26 fn index_mut(self, slice: &mut Slice<T, S, L>) -> &mut Self::Output;
27}
28
29impl<T, S: Shape, L: Layout> SliceIndex<T, S, L> for &[usize] {
30 type Output = T;
31
32 #[inline]
33 unsafe fn get_unchecked(self, slice: &Slice<T, S, L>) -> &T {
34 unsafe { &*slice.as_ptr().offset(slice.mapping().offset(self)) }
35 }
36
37 #[inline]
38 unsafe fn get_unchecked_mut(self, slice: &mut Slice<T, S, L>) -> &mut T {
39 unsafe { &mut *slice.as_mut_ptr().offset(slice.mapping().offset(self)) }
40 }
41
42 #[inline]
43 fn index(self, slice: &Slice<T, S, L>) -> &T {
44 assert!(self.len() == slice.rank(), "invalid rank");
45
46 for i in 0..self.len() {
47 if self[i] >= slice.dim(i) {
48 index::panic_bounds_check(self[i], slice.dim(i));
49 }
50 }
51
52 unsafe { SliceIndex::get_unchecked(self, slice) }
53 }
54
55 #[inline]
56 fn index_mut(self, slice: &mut Slice<T, S, L>) -> &mut T {
57 assert!(self.len() == slice.rank(), "invalid rank");
58
59 for i in 0..self.len() {
60 if self[i] >= slice.dim(i) {
61 index::panic_bounds_check(self[i], slice.dim(i));
62 }
63 }
64
65 unsafe { SliceIndex::get_unchecked_mut(self, slice) }
66 }
67}
68
69impl<T, const N: usize, S: Shape, L: Layout> SliceIndex<T, S, L> for [usize; N] {
70 type Output = T;
71
72 #[inline]
73 unsafe fn get_unchecked(self, slice: &Slice<T, S, L>) -> &T {
74 unsafe { SliceIndex::get_unchecked(&self[..], slice) }
75 }
76
77 #[inline]
78 unsafe fn get_unchecked_mut(self, slice: &mut Slice<T, S, L>) -> &mut T {
79 unsafe { SliceIndex::get_unchecked_mut(&self[..], slice) }
80 }
81
82 #[inline]
83 fn index(self, slice: &Slice<T, S, L>) -> &T {
84 SliceIndex::index(&self[..], slice)
85 }
86
87 #[inline]
88 fn index_mut(self, slice: &mut Slice<T, S, L>) -> &mut T {
89 SliceIndex::index_mut(&self[..], slice)
90 }
91}
92
93impl<T, S: Shape, L: Layout> SliceIndex<T, S, L> for usize {
94 type Output = T;
95
96 #[inline]
97 unsafe fn get_unchecked(self, slice: &Slice<T, S, L>) -> &T {
98 unsafe { &*slice.as_ptr().offset(slice.mapping().linear_offset(self)) }
99 }
100
101 #[inline]
102 unsafe fn get_unchecked_mut(self, slice: &mut Slice<T, S, L>) -> &mut T {
103 unsafe { &mut *slice.as_mut_ptr().offset(slice.mapping().linear_offset(self)) }
104 }
105
106 #[inline]
107 fn index(self, slice: &Slice<T, S, L>) -> &T {
108 if self >= slice.len() {
109 index::panic_bounds_check(self, slice.len());
110 }
111
112 unsafe { SliceIndex::get_unchecked(self, slice) }
113 }
114
115 #[inline]
116 fn index_mut(self, slice: &mut Slice<T, S, L>) -> &mut T {
117 if self >= slice.len() {
118 index::panic_bounds_check(self, slice.len());
119 }
120
121 unsafe { SliceIndex::get_unchecked_mut(self, slice) }
122 }
123}
124
125macro_rules! impl_slice_index {
126 ($type:ty) => {
127 impl<T, S: Shape> SliceIndex<T, S, Dense> for $type {
128 type Output = [T];
129
130 #[inline]
131 unsafe fn get_unchecked(self, slice: &Slice<T, S>) -> &[T] {
132 unsafe { <&[T]>::from(slice.flatten()).get_unchecked(self) }
133 }
134
135 #[inline]
136 unsafe fn get_unchecked_mut(self, slice: &mut Slice<T, S>) -> &mut [T] {
137 unsafe { <&mut [T]>::from(slice.flatten_mut()).get_unchecked_mut(self) }
138 }
139
140 #[inline]
141 fn index(self, slice: &Slice<T, S>) -> &[T] {
142 <&[T]>::from(slice.flatten()).index(self)
143 }
144
145 #[inline]
146 fn index_mut(self, slice: &mut Slice<T, S>) -> &mut [T] {
147 <&mut [T]>::from(slice.flatten_mut()).index_mut(self)
148 }
149 }
150 };
151}
152
153impl_slice_index!((Bound<usize>, Bound<usize>));
154impl_slice_index!(Range<usize>);
155impl_slice_index!(RangeFrom<usize>);
156impl_slice_index!(RangeFull);
157impl_slice_index!(RangeInclusive<usize>);
158impl_slice_index!(RangeTo<usize>);
159impl_slice_index!(RangeToInclusive<usize>);