linearize/map/
iters.rs

1#[allow(unused_imports)]
2use crate::StaticMap;
3use {
4    crate::Linearize,
5    core::{iter::Enumerate, marker::PhantomData, ops::Range},
6};
7
8/// An immutable iterator over the keys and values of a [`StaticMap`].
9pub struct Iter<'a, L, T>
10where
11    L: Linearize,
12{
13    iter: Range<usize>,
14    storage: *const T,
15    _phantom: PhantomData<fn() -> (L, &'a T)>,
16}
17
18impl<'a, L, T> Iter<'a, L, T>
19where
20    L: Linearize,
21    T: 'a,
22{
23    pub(super) fn new(storage: &'a L::Storage<T>) -> Self {
24        Self {
25            iter: 0..L::LENGTH,
26            storage: <L::Storage<T> as AsRef<[T]>>::as_ref(storage).as_ptr(),
27            _phantom: Default::default(),
28        }
29    }
30
31    /// # Safety
32    ///
33    /// i must have been returned by self.iter
34    unsafe fn item(storage: *const T, i: usize) -> (L, &'a T) {
35        // SAFETY: self.iter only returns values in 0..L::LENGTH.
36        let k = L::from_linear_unchecked(i);
37        // SAFETY:
38        // - *self.storage is L::Storage<T>
39        // - L::Storage<T> is required to be [T; L::LENGTH]
40        // - [T; L::LENGTH]: AsRef<[T]> returns a slice of length L::LENGTH;
41        // - self.storage is a pointer to the first element of this slice
42        // - i is less than L::LENGTH
43        let v = &*storage.add(i);
44        (k, v)
45    }
46}
47
48impl<'a, L, T> Clone for Iter<'a, L, T>
49where
50    L: Linearize,
51    T: 'a,
52{
53    fn clone(&self) -> Self {
54        Self {
55            iter: self.iter.clone(),
56            storage: self.storage,
57            _phantom: Default::default(),
58        }
59    }
60}
61
62macro_rules! impl_iter {
63    ($name:ident, $ref_type:ty) => {
64        impl<'a, L, T> Iterator for $name<'a, L, T>
65        where
66            L: Linearize,
67            T: 'a,
68        {
69            type Item = (L, $ref_type);
70
71            fn next(&mut self) -> Option<Self::Item> {
72                self.iter.next().map(|i| unsafe {
73                    // SAFETY: i was returned by self.iter
74                    Self::item(self.storage, i)
75                })
76            }
77
78            fn size_hint(&self) -> (usize, Option<usize>) {
79                self.iter.size_hint()
80            }
81
82            fn count(self) -> usize
83            where
84                Self: Sized,
85            {
86                self.iter.count()
87            }
88
89            fn last(self) -> Option<Self::Item>
90            where
91                Self: Sized,
92            {
93                self.iter.last().map(|i| unsafe {
94                    // SAFETY: i was returned by self.iter
95                    Self::item(self.storage, i)
96                })
97            }
98
99            fn nth(&mut self, n: usize) -> Option<Self::Item> {
100                self.iter.nth(n).map(|i| unsafe {
101                    // SAFETY: i was returned by self.iter
102                    Self::item(self.storage, i)
103                })
104            }
105        }
106
107        impl<'a, L, T> ExactSizeIterator for $name<'a, L, T>
108        where
109            L: Linearize,
110            T: 'a,
111        {
112        }
113
114        impl<'a, L, T> DoubleEndedIterator for $name<'a, L, T>
115        where
116            L: Linearize,
117            T: 'a,
118        {
119            fn next_back(&mut self) -> Option<Self::Item> {
120                self.iter.next_back().map(|i| unsafe {
121                    // SAFETY: i was returned by self.iter
122                    Self::item(self.storage, i)
123                })
124            }
125
126            fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
127                self.iter.nth_back(n).map(|i| unsafe {
128                    // SAFETY: i was returned by self.iter
129                    Self::item(self.storage, i)
130                })
131            }
132        }
133    };
134}
135
136impl_iter!(Iter, &'a T);
137
138/// A mutable iterator over the keys and values of a [`StaticMap`].
139pub struct IterMut<'a, L, T>
140where
141    L: Linearize,
142{
143    iter: Range<usize>,
144    storage: *mut T,
145    _phantom: PhantomData<fn() -> (L, &'a mut T)>,
146}
147
148impl<'a, L, T> IterMut<'a, L, T>
149where
150    L: Linearize,
151    T: 'a,
152{
153    pub(super) fn new(storage: &'a mut L::Storage<T>) -> Self {
154        Self {
155            iter: 0..L::LENGTH,
156            storage: <L::Storage<T> as AsMut<[T]>>::as_mut(storage).as_mut_ptr(),
157            _phantom: Default::default(),
158        }
159    }
160
161    /// # Safety
162    ///
163    /// - i must have been returned by self.iter
164    /// - no i must be used more than once
165    unsafe fn item(storage: *mut T, i: usize) -> (L, &'a mut T) {
166        // SAFETY: self.iter only returns values in 0..L::LENGTH.
167        let k = L::from_linear_unchecked(i);
168        // SAFETY:
169        // - L::Storage<T> is required to be [T; L::LENGTH]
170        // - [T; L::LENGTH]: AsMut<[T]> returns a slice of length L::LENGTH
171        // - self.storage is a pointer to the first element of this slice
172        // - i is less than L::LENGTH
173        // - Each i appears at most once in this iterator
174        let v = &mut *storage.add(i);
175        (k, v)
176    }
177}
178
179// SAFETY: We never clone self.iter so every value returned by it is unique.
180impl_iter!(IterMut, &'a mut T);
181
182/// A consuming iterator over the keys and values of a [`StaticMap`].
183pub struct IntoIter<L, T>
184where
185    L: Linearize,
186{
187    iter: Enumerate<<<L as Linearize>::Storage<T> as IntoIterator>::IntoIter>,
188}
189
190impl<L, T> IntoIter<L, T>
191where
192    L: Linearize,
193{
194    pub(super) fn new(storage: L::Storage<T>) -> Self {
195        Self {
196            iter: <L::Storage<T> as IntoIterator>::into_iter(storage).enumerate(),
197        }
198    }
199
200    /// # Safety
201    ///
202    /// - i must have been returned by self.iter
203    unsafe fn key(i: usize) -> L {
204        unsafe {
205            // SAFETY:
206            // - self.iter is <L::Storage<T> as IntoIterator>::into_iter(storage).enumerate().
207            // - L::Storage<T> is [T; L::LENGTH].
208            // - Therefore, <L::Storage<T> as IntoIterator>::into_iter(storage) returns
209            //   exactly L::LENGTH elements.
210            // - Therefore, i < L::LENGTH.
211            L::from_linear_unchecked(i)
212        }
213    }
214}
215
216impl<L, T> Iterator for IntoIter<L, T>
217where
218    L: Linearize,
219{
220    type Item = (L, T);
221
222    fn next(&mut self) -> Option<Self::Item> {
223        self.iter.next().map(|(i, v)| {
224            let k = unsafe {
225                // SAFETY: i was returned by self.iter
226                Self::key(i)
227            };
228            (k, v)
229        })
230    }
231
232    fn size_hint(&self) -> (usize, Option<usize>) {
233        self.iter.size_hint()
234    }
235
236    fn count(self) -> usize
237    where
238        Self: Sized,
239    {
240        self.iter.count()
241    }
242
243    fn last(self) -> Option<Self::Item>
244    where
245        Self: Sized,
246    {
247        self.iter.last().map(|(i, v)| {
248            let k = unsafe {
249                // SAFETY: i was returned by self.iter
250                Self::key(i)
251            };
252            (k, v)
253        })
254    }
255
256    fn nth(&mut self, n: usize) -> Option<Self::Item> {
257        self.iter.nth(n).map(|(i, v)| {
258            let k = unsafe {
259                // SAFETY: i was returned by self.iter
260                Self::key(i)
261            };
262            (k, v)
263        })
264    }
265}
266
267impl<L, T> ExactSizeIterator for IntoIter<L, T> where L: Linearize {}
268
269impl<L, T> DoubleEndedIterator for IntoIter<L, T>
270where
271    L: Linearize,
272{
273    fn next_back(&mut self) -> Option<Self::Item> {
274        self.iter.next_back().map(|(i, v)| {
275            let k = unsafe {
276                // SAFETY: i was returned by self.iter
277                Self::key(i)
278            };
279            (k, v)
280        })
281    }
282
283    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
284        self.iter.nth_back(n).map(|(i, v)| {
285            let k = unsafe {
286                // SAFETY: i was returned by self.iter
287                Self::key(i)
288            };
289            (k, v)
290        })
291    }
292}
293
294/// A consuming iterator over the keys and values of a [`StaticMap`].
295pub struct IntoValues<L, T>
296where
297    L: Linearize,
298{
299    iter: <<L as Linearize>::Storage<T> as IntoIterator>::IntoIter,
300}
301
302impl<L, T> IntoValues<L, T>
303where
304    L: Linearize,
305{
306    pub(super) fn new(storage: L::Storage<T>) -> Self {
307        Self {
308            iter: <L::Storage<T> as IntoIterator>::into_iter(storage),
309        }
310    }
311}
312
313impl<L, T> Iterator for IntoValues<L, T>
314where
315    L: Linearize,
316{
317    type Item = T;
318
319    fn next(&mut self) -> Option<Self::Item> {
320        self.iter.next()
321    }
322
323    fn size_hint(&self) -> (usize, Option<usize>) {
324        self.iter.size_hint()
325    }
326
327    fn count(self) -> usize
328    where
329        Self: Sized,
330    {
331        self.iter.count()
332    }
333
334    fn last(self) -> Option<Self::Item>
335    where
336        Self: Sized,
337    {
338        self.iter.last()
339    }
340
341    fn nth(&mut self, n: usize) -> Option<Self::Item> {
342        self.iter.nth(n)
343    }
344}
345
346impl<L, T> ExactSizeIterator for IntoValues<L, T> where L: Linearize {}
347
348impl<L, T> DoubleEndedIterator for IntoValues<L, T>
349where
350    L: Linearize,
351{
352    fn next_back(&mut self) -> Option<Self::Item> {
353        self.iter.next_back()
354    }
355
356    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
357        self.iter.nth_back(n)
358    }
359}