1use crate::{Slice, SliceMut, SliceRef, SoaRaw, Soapy};
2use std::{
3 marker::PhantomData,
4 ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
5};
6
7pub trait SoaIndex<T>
9where
10 T: Soapy,
11{
12 type Output<'a>
14 where
15 T: 'a;
16
17 type OutputMut<'a>
19 where
20 T: 'a;
21
22 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>>;
24
25 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>>;
27}
28
29impl<T> SoaIndex<T> for usize
30where
31 T: Soapy,
32{
33 type Output<'a> = T::Ref<'a> where T: 'a;
34
35 type OutputMut<'a> = T::RefMut<'a>
36 where
37 T: 'a;
38
39 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
40 if self < slice.len() {
41 Some(unsafe { slice.raw().offset(self).get_ref() })
42 } else {
43 None
44 }
45 }
46
47 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
48 if self < slice.len() {
49 Some(unsafe { slice.raw().offset(self).get_mut() })
50 } else {
51 None
52 }
53 }
54}
55
56impl<T> SoaIndex<T> for RangeFull
57where
58 T: Soapy,
59{
60 type Output<'a> = SliceRef<'a, T>
61 where
62 T: 'a;
63
64 type OutputMut<'a> = SliceMut<'a, T>
65 where
66 T: 'a;
67
68 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
69 Some(SliceRef {
70 slice: unsafe { slice.as_sized() },
71 len: slice.len(),
72 marker: PhantomData,
73 })
74 }
75
76 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
77 Some(SliceMut {
78 slice: unsafe { slice.as_sized() },
79 len: slice.len(),
80 marker: PhantomData,
81 })
82 }
83}
84
85impl<T> SoaIndex<T> for Range<usize>
86where
87 T: Soapy,
88{
89 type Output<'a> = SliceRef<'a, T>
90 where
91 T: 'a;
92
93 type OutputMut<'a> = SliceMut<'a, T>
94 where
95 T: 'a;
96
97 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
98 let len = self.len();
99 (len + self.start <= slice.len()).then(|| SliceRef {
100 slice: Slice::with_raw(unsafe { slice.raw().offset(self.start) }),
101 len,
102 marker: PhantomData,
103 })
104 }
105
106 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
107 self.get(slice).map(|s| SliceMut {
108 slice: unsafe { s.as_sized() },
109 len: s.len(),
110 marker: PhantomData,
111 })
112 }
113}
114
115impl<T> SoaIndex<T> for RangeTo<usize>
116where
117 T: Soapy,
118{
119 type Output<'a> = SliceRef<'a, T>
120 where
121 T: 'a;
122
123 type OutputMut<'a> = SliceMut<'a, T>
124 where
125 T: 'a;
126
127 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
128 (0..self.end).get(slice)
129 }
130
131 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
132 (0..self.end).get_mut(slice)
133 }
134}
135
136impl<T> SoaIndex<T> for RangeToInclusive<usize>
137where
138 T: Soapy,
139{
140 type Output<'a> = SliceRef<'a, T>
141 where
142 T: 'a;
143
144 type OutputMut<'a> = SliceMut<'a, T>
145 where
146 T: 'a;
147
148 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
149 (0..self.end + 1).get(slice)
150 }
151
152 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
153 (0..self.end + 1).get_mut(slice)
154 }
155}
156
157impl<T> SoaIndex<T> for RangeFrom<usize>
158where
159 T: Soapy,
160{
161 type Output<'a> = SliceRef<'a, T>
162 where
163 T: 'a;
164
165 type OutputMut<'a> = SliceMut<'a, T>
166 where
167 T: 'a;
168
169 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
170 (self.start..slice.len()).get(slice)
171 }
172
173 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
174 (self.start..slice.len()).get_mut(slice)
175 }
176}
177
178impl<T> SoaIndex<T> for RangeInclusive<usize>
179where
180 T: Soapy,
181{
182 type Output<'a> = SliceRef<'a, T>
183 where
184 T: 'a;
185
186 type OutputMut<'a> = SliceMut<'a, T>
187 where
188 T: 'a;
189
190 fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>> {
191 (*self.start()..*self.end() + 1).get(slice)
192 }
193
194 fn get_mut(self, slice: &mut Slice<T>) -> Option<Self::OutputMut<'_>> {
195 (*self.start()..*self.end() + 1).get_mut(slice)
196 }
197}