soapy/
index.rs

1use crate::{Slice, SliceMut, SliceRef, SoaRaw, Soapy};
2use std::{
3    marker::PhantomData,
4    ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
5};
6
7/// A helper trait for indexing operations.
8pub trait SoaIndex<T>
9where
10    T: Soapy,
11{
12    /// The output type returned by non-`mut` methods.
13    type Output<'a>
14    where
15        T: 'a;
16
17    /// The output type returned by `mut` methods.
18    type OutputMut<'a>
19    where
20        T: 'a;
21
22    /// Returns the output at this location, if in bounds.
23    fn get(self, slice: &Slice<T>) -> Option<Self::Output<'_>>;
24
25    /// Returns the mutable output at this location, if in bounds.
26    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}