1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(clippy::let_unit_value)]
5
6use core::{
83 marker::PhantomData,
84 ops::{Index, IndexMut, Deref, DerefMut},
85};
86
87trait IsValidIndex<const INDEX: usize> {
92 const RESULT: ();
93}
94
95pub struct StaticIndex<const INDEX: usize>;
97
98impl<T, const INDEX: usize, const N: usize> IsValidIndex<INDEX> for [T; N] {
99 const RESULT: () = assert!(N > INDEX, "Index is out of bounds!");
100}
101
102impl<T, const INDEX: usize, const N: usize> Index<StaticIndex<INDEX>> for [T; N] {
103 type Output = T;
104
105 fn index(&self, _: StaticIndex<INDEX>) -> &Self::Output {
106 let _ = <[T; N] as IsValidIndex<INDEX>>::RESULT;
107
108 unsafe { &*(self.as_ptr().add(INDEX) as *const T) }
110 }
111}
112
113impl<T, const INDEX: usize, const N: usize> IndexMut<StaticIndex<INDEX>> for [T; N] {
114 fn index_mut(&mut self, _: StaticIndex<INDEX>) -> &mut Self::Output {
115 let _ = <[T; N] as IsValidIndex<INDEX>>::RESULT;
116
117 unsafe { &mut *(self.as_mut_ptr().add(INDEX) as *mut T) }
119 }
120}
121
122trait IsValidRangeIndex<const START: usize, const LENGTH: usize> {
127 const RESULT: ();
128}
129
130pub struct StaticRangeIndex<const START: usize, const LENGTH: usize>;
134
135impl<T, const START: usize, const LENGTH: usize, const N: usize> IsValidRangeIndex<START, LENGTH>
136 for [T; N]
137{
138 const RESULT: () = {
139 assert!(N > START, "Starting index is out of bounds!");
140 assert!(N - START >= LENGTH, "Ending index is out of bounds! Check your range index's length.");
141 };
142}
143
144impl<T, const START: usize, const LENGTH: usize, const N: usize>
145 Index<StaticRangeIndex<START, LENGTH>> for [T; N]
146{
147 type Output = [T; LENGTH];
148
149 fn index(&self, _: StaticRangeIndex<START, LENGTH>) -> &Self::Output {
150 let _ = <[T; N] as IsValidRangeIndex<START, LENGTH>>::RESULT;
151
152 unsafe { &*(self.as_ptr().add(START) as *const [T; LENGTH]) }
154 }
155}
156
157impl<T, const START: usize, const LENGTH: usize, const N: usize>
158 IndexMut<StaticRangeIndex<START, LENGTH>> for [T; N]
159{
160 fn index_mut(&mut self, _: StaticRangeIndex<START, LENGTH>) -> &mut Self::Output {
161 let _ = <[T; N] as IsValidRangeIndex<START, LENGTH>>::RESULT;
162
163 unsafe { &mut *(self.as_mut_ptr().add(START) as *mut [T; LENGTH]) }
165 }
166}
167
168#[repr(transparent)]
179pub struct SliceWrapper<'a, I, T>(
180 T,
182
183 PhantomData<&'a ()>,
186
187 PhantomData<I>
192);
193
194impl<'a, I, T> SliceWrapper<'a, I, T> where T: AsRef<[I]> {
195 pub fn new(data: T) -> Self {
196 Self(data, PhantomData, PhantomData)
197 }
198}
199
200impl<'a, I, T> Deref for SliceWrapper<'a, I, T> {
201 type Target = T;
202 fn deref(&self) -> &Self::Target {
203 &self.0
204 }
205}
206
207impl<'a, I, T> DerefMut for SliceWrapper<'a, I, T> {
208 fn deref_mut(&mut self) -> &mut Self::Target {
209 &mut self.0
210 }
211}
212
213impl<I, S: AsRef<[I]>, const START: usize, const LENGTH: usize> Index<StaticRangeIndex<START, LENGTH>> for SliceWrapper<'_, I, S> {
214 type Output = [I; LENGTH];
215
216 fn index(&self, _: StaticRangeIndex<START, LENGTH>) -> &Self::Output {
217 let inner: &[I] = self.0.as_ref();
218
219 assert!(inner.len() > START, "Starting index {} is out of bounds", START);
220 assert!(inner.len() - START >= LENGTH, "Not enough items after index {} (requested {}; length: {})", START, LENGTH, inner.len());
221
222 unsafe { &*(inner.as_ptr().add(START) as *const [I; LENGTH]) }
224 }
225}
226
227impl<I, S: AsRef<[I]>, const INDEX: usize> Index<StaticIndex<INDEX>> for SliceWrapper<'_, I, S> {
228 type Output = I;
229
230 fn index(&self, _: StaticIndex<INDEX>) -> &Self::Output {
231 self.0.as_ref().index(INDEX)
232 }
233}
234
235impl<I, S: AsRef<[I]> + AsMut<[I]>, const START: usize, const LENGTH: usize> IndexMut<StaticRangeIndex<START, LENGTH>> for SliceWrapper<'_, I, S> {
236 fn index_mut(&mut self, _: StaticRangeIndex<START, LENGTH>) -> &mut Self::Output {
237 let inner: &mut [I] = self.0.as_mut();
238
239 assert!(inner.len() > START, "Starting index {} is out of bounds", START);
240 assert!(inner.len() - START >= LENGTH, "Not enough items after index {} (requested {}; length: {})", START, LENGTH, inner.len());
241
242 unsafe { &mut *(inner.as_mut_ptr().add(START) as *mut [I; LENGTH]) }
244 }
245}
246
247impl<I, S: AsRef<[I]> + AsMut<[I]>, const INDEX: usize> IndexMut<StaticIndex<INDEX>> for SliceWrapper<'_, I, S> {
248 fn index_mut(&mut self, _: StaticIndex<INDEX>) -> &mut Self::Output {
249 self.0.as_mut().index_mut(INDEX)
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 mod core_functionality {
258 use super::*;
259
260 #[test]
261 fn test_immutable_static_slice() {
262 let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
263 let sub_arr = arr[StaticRangeIndex::<4, 8>];
264
265 assert_eq!(sub_arr, arr[4..12]);
266 }
267
268 #[test]
269 fn test_mutable_static_slice() {
270 let mut arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
271 let sub_arr = &mut arr[StaticRangeIndex::<4, 8>];
272
273 sub_arr[0] = 1234;
274 assert_eq!(arr[4], 1234);
275 }
276
277 #[test]
278 fn test_full_immutable_static_slice() {
279 let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
280 let sub_arr = arr[StaticRangeIndex::<0, 12>];
281
282 assert_eq!(arr, sub_arr);
283 }
284
285 #[test]
286 fn test_full_mutable_static_slice() {
287 let mut arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
288 let sub_arr = &mut arr[StaticRangeIndex::<0, 12>];
289
290 sub_arr[4] = 5;
291 sub_arr[5] = 4;
292 assert_eq!(arr[4], 5);
293 assert_eq!(arr[5], 4);
294 }
295
296 #[test]
297 fn test_immutable_static_index() {
298 let arr = [1, 2, 3, 4, 5];
299 assert_eq!(arr[StaticIndex::<4>], 5);
300 }
301
302 #[test]
303 fn test_mutable_static_index() {
304 let mut arr = [1, 2, 3, 4, 5];
305 arr[StaticIndex::<4>] = 6;
306 assert_eq!(arr, [1, 2, 3, 4, 6]);
307 }
308 }
309
310 mod wrapper_functionality {
311 use super::*;
312
313 #[test]
314 fn test_wrapped_slice_read_single() {
315 let x = SliceWrapper::new(&[1, 2, 3]);
316 assert_eq!(x[StaticIndex::<2>], 3);
317 assert_eq!(x.len(), 3);
318 }
319
320 #[test]
321 fn test_wrapped_slice_write_single() {
322 let mut x = [1, 2, 3];
323 let mut y = SliceWrapper::new(&mut x);
324 y[StaticIndex::<2>] = 5;
325 assert_eq!(x[2], 5);
326 }
327
328 #[test]
329 fn test_wrapped_slice_read_multi() {
330 let x = SliceWrapper::new(&[1, 2, 3]);
331 assert_eq!(x[StaticRangeIndex::<0, 2>], [1, 2]);
332 }
333
334 #[test]
335 fn test_wrapped_slice_write_multi() {
336 let mut x = [1, 2, 3];
337 let mut y = SliceWrapper::new(&mut x);
338 y[StaticRangeIndex::<0, 2>] = [3, 4];
339 assert_eq!(x, [3, 4, 3]);
340 }
341
342 #[test]
343 fn test_wrapped_vec_read() {
344 let x = vec![1, 2, 3];
345 let x = SliceWrapper::new(x);
346 assert_eq!(x[StaticRangeIndex::<0, 2>], [1, 2]);
347 assert_eq!(x.len(), 3);
348 }
349
350 #[test]
351 fn test_wrapped_vec_write() {
352 let mut x = vec![1, 2, 3];
353 let mut y = SliceWrapper::new(&mut x);
354 y[StaticRangeIndex::<1, 2>] = [4, 5];
355
356 assert_eq!(y[StaticRangeIndex::<0, 3>], [1, 4, 5]);
357 assert_eq!(x[0..3], [1, 4, 5]);
358 }
359 }
360
361 mod wrapper_safety {
362 use super::*;
363
364 #[test]
365 #[should_panic]
366 fn wrapped_slice_oob_read_should_panic() {
367 let x = SliceWrapper::new(&[1, 2, 3]);
368 let _ = x[StaticIndex::<3>];
369 }
370
371 #[test]
372 #[should_panic]
373 fn wrapped_slice_oob_write_should_panic() {
374 let mut x = [1, 2, 3];
375 let mut x = SliceWrapper::new(&mut x);
376 x[StaticIndex::<3>] = 1337;
377 }
378
379 #[test]
380 #[should_panic]
381 fn wrapped_slice_oob_range_read_should_panic() {
382 let x = SliceWrapper::new(&[1, 2, 3]);
383 let _ = x[StaticRangeIndex::<0, 5>];
384 }
385
386 #[test]
387 #[should_panic]
388 fn wrapped_slice_oob_range_write_should_panic() {
389 let mut x = [1, 2, 3];
390 let mut x = SliceWrapper::new(&mut x);
391 x[StaticRangeIndex::<0, 5>] = [2, 3, 4, 5, 6];
392 }
393
394 #[test]
395 #[should_panic]
396 fn wrapped_vec_oob_read_should_panic() {
397 let x = SliceWrapper::new(vec![1, 2, 3]);
398 let _ = x[StaticIndex::<3>];
399 }
400
401 #[test]
402 #[should_panic]
403 fn wrapped_vec_oob_write_should_panic() {
404 let mut x = SliceWrapper::new(vec![1, 2, 3]);
405 x[StaticIndex::<3>] = 1337;
406 }
407
408 #[test]
409 #[should_panic]
410 fn wrapped_vec_oob_range_read_should_panic() {
411 let x = SliceWrapper::new(vec![1, 2, 3]);
412 let _ = x[StaticRangeIndex::<0, 5>];
413 }
414
415 #[test]
416 #[should_panic]
417 fn wrapped_vec_oob_range_write_should_panic() {
418 let mut x = SliceWrapper::new(vec![1, 2, 3]);
419 x[StaticRangeIndex::<0, 5>] = [2, 3, 4, 5, 6];
420 }
421 }
422}