index_vec/
indexing.rs

1use crate::{Idx, IndexSlice};
2
3mod private_slice_index {
4    pub trait Sealed {}
5}
6
7/// This is the equivalent of the sealed `core::slice::SliceIndex` trait. It
8/// cannot be overridden from user, code nor should it normally need use
9/// directly (Outside of trait bounds, I guess).
10pub trait IdxSliceIndex<I: Idx, T>: private_slice_index::Sealed {
11    type Output: ?Sized;
12
13    fn get(self, slice: &IndexSlice<I, [T]>) -> Option<&Self::Output>;
14    fn get_mut(self, slice: &mut IndexSlice<I, [T]>) -> Option<&mut Self::Output>;
15
16    fn index(self, slice: &IndexSlice<I, [T]>) -> &Self::Output;
17    fn index_mut(self, slice: &mut IndexSlice<I, [T]>) -> &mut Self::Output;
18}
19
20// Does this defeat the point of sealing?
21impl<I: Idx> private_slice_index::Sealed for I {}
22
23impl<I: Idx, T> IdxSliceIndex<I, T> for I {
24    type Output = T;
25
26    #[inline]
27    fn get(self, slice: &IndexSlice<I, [T]>) -> Option<&Self::Output> {
28        slice.raw.get(self.index())
29    }
30    #[inline]
31    fn get_mut(self, slice: &mut IndexSlice<I, [T]>) -> Option<&mut Self::Output> {
32        slice.raw.get_mut(self.index())
33    }
34
35    #[inline]
36    fn index(self, slice: &IndexSlice<I, [T]>) -> &Self::Output {
37        &slice.raw[self.index()]
38    }
39
40    #[inline]
41    fn index_mut(self, slice: &mut IndexSlice<I, [T]>) -> &mut Self::Output {
42        &mut slice.raw[self.index()]
43    }
44}
45
46macro_rules! range_slice {
47    ($r:ty) => {
48        impl<I: Idx, T> IdxSliceIndex<I, T> for $r {
49            type Output = IndexSlice<I, [T]>;
50
51            #[inline]
52            fn get(self, slice: &IndexSlice<I, [T]>) -> Option<&Self::Output> {
53                slice.raw.get(self.into_range()).map(IndexSlice::new)
54            }
55            #[inline]
56            fn get_mut(self, slice: &mut IndexSlice<I, [T]>) -> Option<&mut Self::Output> {
57                slice
58                    .raw
59                    .get_mut(self.into_range())
60                    .map(IndexSlice::new_mut)
61            }
62
63            #[inline]
64            fn index(self, slice: &IndexSlice<I, [T]>) -> &Self::Output {
65                IndexSlice::new(&slice.raw[self.into_range()])
66            }
67            #[inline]
68            fn index_mut(self, slice: &mut IndexSlice<I, [T]>) -> &mut Self::Output {
69                IndexSlice::new_mut(&mut slice.raw[self.into_range()])
70            }
71        }
72    };
73}
74
75impl<I: Idx> private_slice_index::Sealed for core::ops::Range<I> {}
76impl<I: Idx> private_slice_index::Sealed for core::ops::RangeFrom<I> {}
77impl<I: Idx> private_slice_index::Sealed for core::ops::RangeTo<I> {}
78impl<I: Idx> private_slice_index::Sealed for core::ops::RangeInclusive<I> {}
79impl<I: Idx> private_slice_index::Sealed for core::ops::RangeToInclusive<I> {}
80
81range_slice!(core::ops::Range<I>);
82range_slice!(core::ops::RangeFrom<I>);
83range_slice!(core::ops::RangeTo<I>);
84range_slice!(core::ops::RangeInclusive<I>);
85range_slice!(core::ops::RangeToInclusive<I>);
86// range_slice!(core::ops::RangeFull);
87impl private_slice_index::Sealed for core::ops::RangeFull {}
88impl<I: Idx, T> IdxSliceIndex<I, T> for core::ops::RangeFull {
89    type Output = IndexSlice<I, [T]>;
90
91    #[inline]
92    fn get(self, slice: &IndexSlice<I, [T]>) -> Option<&Self::Output> {
93        Some(slice)
94    }
95
96    #[inline]
97    fn get_mut(self, slice: &mut IndexSlice<I, [T]>) -> Option<&mut Self::Output> {
98        Some(slice)
99    }
100
101    #[inline]
102    fn index(self, slice: &IndexSlice<I, [T]>) -> &Self::Output {
103        slice
104    }
105
106    #[inline]
107    fn index_mut(self, slice: &mut IndexSlice<I, [T]>) -> &mut Self::Output {
108        slice
109    }
110}
111
112impl private_slice_index::Sealed for usize {}
113// As an ergonomic concession, implement this for `usize` as well, it's too painful without
114impl<I: Idx, T> IdxSliceIndex<I, T> for usize {
115    type Output = T;
116
117    #[inline]
118    fn get(self, slice: &IndexSlice<I, [T]>) -> Option<&Self::Output> {
119        slice.raw.get(self)
120    }
121    #[inline]
122    fn get_mut(self, slice: &mut IndexSlice<I, [T]>) -> Option<&mut Self::Output> {
123        slice.raw.get_mut(self)
124    }
125
126    #[inline]
127    fn index(self, slice: &IndexSlice<I, [T]>) -> &Self::Output {
128        &slice.raw[self]
129    }
130    #[inline]
131    fn index_mut(self, slice: &mut IndexSlice<I, [T]>) -> &mut Self::Output {
132        &mut slice.raw[self]
133    }
134}
135
136/// This trait to function in API signatures where `Vec<T>` or `[T]` use `R:
137/// RangeBounds<usize>`. There are blanket implementations for the basic range
138/// types in `core::ops` for all Idx types. e.g. `Range<I: Idx>`, `RangeFrom<I:
139/// Idx>`, `RangeTo<I: Idx>`, etc all implement it.
140///
141/// IMO it's unfortunate that this needs to be present in the API, but it
142/// doesn't hurt that much.
143pub trait IdxRangeBounds<I>: private_range_bounds::Sealed
144where
145    I: Idx,
146{
147    type Range: core::ops::RangeBounds<usize>;
148    fn into_range(self) -> Self::Range;
149}
150
151mod private_range_bounds {
152    pub trait Sealed {}
153}
154
155impl<I: Idx> private_range_bounds::Sealed for core::ops::Range<I> {}
156impl<I: Idx> private_range_bounds::Sealed for core::ops::RangeFrom<I> {}
157impl<I: Idx> private_range_bounds::Sealed for core::ops::RangeTo<I> {}
158impl<I: Idx> private_range_bounds::Sealed for core::ops::RangeInclusive<I> {}
159impl<I: Idx> private_range_bounds::Sealed for core::ops::RangeToInclusive<I> {}
160impl private_range_bounds::Sealed for core::ops::RangeFull {}
161
162impl<I: Idx> IdxRangeBounds<I> for core::ops::Range<I> {
163    type Range = core::ops::Range<usize>;
164    #[inline]
165    fn into_range(self) -> Self::Range {
166        self.start.index()..self.end.index()
167    }
168}
169
170impl<I: Idx> IdxRangeBounds<I> for core::ops::RangeFrom<I> {
171    type Range = core::ops::RangeFrom<usize>;
172    #[inline]
173    fn into_range(self) -> Self::Range {
174        self.start.index()..
175    }
176}
177
178impl<I: Idx> IdxRangeBounds<I> for core::ops::RangeFull {
179    type Range = core::ops::RangeFull;
180    #[inline]
181    fn into_range(self) -> Self::Range {
182        self
183    }
184}
185
186impl<I: Idx> IdxRangeBounds<I> for core::ops::RangeTo<I> {
187    type Range = core::ops::RangeTo<usize>;
188    #[inline]
189    fn into_range(self) -> Self::Range {
190        ..self.end.index()
191    }
192}
193
194impl<I: Idx> IdxRangeBounds<I> for core::ops::RangeInclusive<I> {
195    type Range = core::ops::RangeInclusive<usize>;
196    #[inline]
197    fn into_range(self) -> Self::Range {
198        self.start().index()..=self.end().index()
199    }
200}
201
202impl<I: Idx> IdxRangeBounds<I> for core::ops::RangeToInclusive<I> {
203    type Range = core::ops::RangeToInclusive<usize>;
204    #[inline]
205    fn into_range(self) -> Self::Range {
206        ..=self.end.index()
207    }
208}
209
210impl<I, R, T> core::ops::Index<R> for IndexSlice<I, [T]>
211where
212    I: Idx,
213    R: IdxSliceIndex<I, T>,
214{
215    type Output = R::Output;
216    #[inline]
217    fn index(&self, index: R) -> &R::Output {
218        index.index(self)
219    }
220}
221
222impl<I, R, T> core::ops::IndexMut<R> for IndexSlice<I, [T]>
223where
224    I: Idx,
225    R: IdxSliceIndex<I, T>,
226{
227    #[inline]
228    fn index_mut(&mut self, index: R) -> &mut R::Output {
229        index.index_mut(self)
230    }
231}