Skip to main content

goud_engine/core/handle/
iterators.rs

1//! Iterator types for [`HandleMap`](super::HandleMap).
2
3use std::marker::PhantomData;
4
5use super::allocator::HandleAllocator;
6use super::handle_type::Handle;
7
8/// An iterator over handle-value pairs in a [`HandleMap`](super::HandleMap).
9///
10/// This struct is created by the [`iter`](super::HandleMap::iter) method on `HandleMap`.
11/// It yields `(Handle<T>, &V)` pairs for all live entries.
12///
13/// # Iteration Order
14///
15/// Iteration order is based on the internal storage order (by slot index),
16/// which corresponds to allocation order for slots that haven't been recycled.
17/// Do not rely on any specific ordering as it may change with insertions and removals.
18///
19/// # Example
20///
21/// ```
22/// use goud_engine::core::handle::HandleMap;
23///
24/// struct Texture;
25///
26/// let mut map: HandleMap<Texture, &str> = HandleMap::new();
27/// map.insert("first");
28/// map.insert("second");
29/// map.insert("third");
30///
31/// for (handle, value) in map.iter() {
32///     println!("Handle {:?} => {}", handle, value);
33/// }
34/// ```
35pub struct HandleMapIter<'a, T, V> {
36    /// Reference to the allocator for generation checking.
37    pub(crate) allocator: &'a HandleAllocator<T>,
38
39    /// Iterator over the values vector with indices.
40    pub(crate) values_iter: std::iter::Enumerate<std::slice::Iter<'a, Option<V>>>,
41}
42
43impl<'a, T, V> Iterator for HandleMapIter<'a, T, V> {
44    type Item = (Handle<T>, &'a V);
45
46    fn next(&mut self) -> Option<Self::Item> {
47        // Iterate through values, skipping None entries
48        loop {
49            match self.values_iter.next() {
50                Some((index, Some(value))) => {
51                    // Reconstruct the handle from index and current generation
52                    let index = index as u32;
53                    // Get the current generation for this slot
54                    if let Some(&generation) = self.allocator.generations.get(index as usize) {
55                        let handle = Handle::new(index, generation);
56                        // Only yield if the handle is alive (matches current generation)
57                        if self.allocator.is_alive(handle) {
58                            return Some((handle, value));
59                        }
60                    }
61                    // Generation mismatch or out of bounds - skip this entry
62                    // This shouldn't happen if the map is consistent, but handle gracefully
63                }
64                Some((_, None)) => {
65                    // Empty slot, continue to next
66                    continue;
67                }
68                None => {
69                    // End of iteration
70                    return None;
71                }
72            }
73        }
74    }
75
76    fn size_hint(&self) -> (usize, Option<usize>) {
77        // Lower bound is 0 (all remaining could be None)
78        // Upper bound is remaining elements in the iterator
79        let (_, upper) = self.values_iter.size_hint();
80        (0, upper)
81    }
82}
83
84/// A mutable iterator over handle-value pairs in a [`HandleMap`](super::HandleMap).
85///
86/// This struct is created by the [`iter_mut`](super::HandleMap::iter_mut) method on `HandleMap`.
87/// It yields `(Handle<T>, &mut V)` pairs for all live entries.
88///
89/// # Example
90///
91/// ```
92/// use goud_engine::core::handle::HandleMap;
93///
94/// struct Counter;
95///
96/// let mut map: HandleMap<Counter, i32> = HandleMap::new();
97/// map.insert(1);
98/// map.insert(2);
99/// map.insert(3);
100///
101/// for (handle, value) in map.iter_mut() {
102///     *value *= 2;
103/// }
104///
105/// // All values are now doubled
106/// ```
107pub struct HandleMapIterMut<'a, T, V> {
108    /// Pointer to the allocator for generation checking.
109    /// We use a raw pointer because we can't hold a reference while iterating mutably.
110    pub(crate) allocator_ptr: *const HandleAllocator<T>,
111
112    /// Iterator over the values vector with indices.
113    pub(crate) values_iter: std::iter::Enumerate<std::slice::IterMut<'a, Option<V>>>,
114
115    /// Phantom marker for lifetime.
116    pub(crate) _marker: PhantomData<&'a HandleAllocator<T>>,
117}
118
119impl<'a, T, V> Iterator for HandleMapIterMut<'a, T, V> {
120    type Item = (Handle<T>, &'a mut V);
121
122    fn next(&mut self) -> Option<Self::Item> {
123        // Iterate through values, skipping None entries
124        loop {
125            match self.values_iter.next() {
126                Some((index, Some(value))) => {
127                    // Reconstruct the handle from index and current generation
128                    let index = index as u32;
129                    // SAFETY: allocator_ptr is valid for the lifetime 'a
130                    let allocator = unsafe { &*self.allocator_ptr };
131                    if let Some(&generation) = allocator.generations.get(index as usize) {
132                        let handle = Handle::new(index, generation);
133                        if allocator.is_alive(handle) {
134                            return Some((handle, value));
135                        }
136                    }
137                }
138                Some((_, None)) => {
139                    continue;
140                }
141                None => {
142                    return None;
143                }
144            }
145        }
146    }
147
148    fn size_hint(&self) -> (usize, Option<usize>) {
149        let (_, upper) = self.values_iter.size_hint();
150        (0, upper)
151    }
152}
153
154/// An iterator over handles in a [`HandleMap`](super::HandleMap).
155///
156/// This struct is created by the [`handles`](super::HandleMap::handles) method on `HandleMap`.
157/// It yields `Handle<T>` for all live entries.
158///
159/// # Example
160///
161/// ```
162/// use goud_engine::core::handle::HandleMap;
163///
164/// struct Entity;
165///
166/// let mut map: HandleMap<Entity, String> = HandleMap::new();
167/// let h1 = map.insert("entity1".to_string());
168/// let h2 = map.insert("entity2".to_string());
169///
170/// let handles: Vec<_> = map.handles().collect();
171/// assert!(handles.contains(&h1));
172/// assert!(handles.contains(&h2));
173/// ```
174pub struct HandleMapHandles<'a, T, V> {
175    /// The underlying iterator.
176    pub(crate) inner: HandleMapIter<'a, T, V>,
177}
178
179impl<'a, T, V> Iterator for HandleMapHandles<'a, T, V> {
180    type Item = Handle<T>;
181
182    fn next(&mut self) -> Option<Self::Item> {
183        self.inner.next().map(|(handle, _)| handle)
184    }
185
186    fn size_hint(&self) -> (usize, Option<usize>) {
187        self.inner.size_hint()
188    }
189}
190
191/// An iterator over values in a [`HandleMap`](super::HandleMap).
192///
193/// This struct is created by the [`values`](super::HandleMap::values) method on `HandleMap`.
194/// It yields `&V` for all live entries.
195///
196/// # Example
197///
198/// ```
199/// use goud_engine::core::handle::HandleMap;
200///
201/// struct Score;
202///
203/// let mut map: HandleMap<Score, i32> = HandleMap::new();
204/// map.insert(100);
205/// map.insert(200);
206/// map.insert(300);
207///
208/// let sum: i32 = map.values().sum();
209/// assert_eq!(sum, 600);
210/// ```
211pub struct HandleMapValues<'a, T, V> {
212    /// The underlying iterator.
213    pub(crate) inner: HandleMapIter<'a, T, V>,
214}
215
216impl<'a, T, V> Iterator for HandleMapValues<'a, T, V> {
217    type Item = &'a V;
218
219    fn next(&mut self) -> Option<Self::Item> {
220        self.inner.next().map(|(_, value)| value)
221    }
222
223    fn size_hint(&self) -> (usize, Option<usize>) {
224        self.inner.size_hint()
225    }
226}
227
228/// A mutable iterator over values in a [`HandleMap`](super::HandleMap).
229///
230/// This struct is created by the [`values_mut`](super::HandleMap::values_mut) method
231/// on `HandleMap`. It yields `&mut V` for all live entries.
232pub struct HandleMapValuesMut<'a, T, V> {
233    /// The underlying iterator.
234    pub(crate) inner: HandleMapIterMut<'a, T, V>,
235}
236
237impl<'a, T, V> Iterator for HandleMapValuesMut<'a, T, V> {
238    type Item = &'a mut V;
239
240    fn next(&mut self) -> Option<Self::Item> {
241        self.inner.next().map(|(_, value)| value)
242    }
243
244    fn size_hint(&self) -> (usize, Option<usize>) {
245        self.inner.size_hint()
246    }
247}
248
249// =============================================================================
250// HandleMap iterator factory methods and IntoIterator impls
251// =============================================================================
252
253use super::map::HandleMap;
254
255impl<T, V> HandleMap<T, V> {
256    /// Returns an iterator over handle-value pairs.
257    ///
258    /// The iterator yields `(Handle<T>, &V)` for each live entry in the map.
259    ///
260    /// # Example
261    ///
262    /// ```
263    /// use goud_engine::core::handle::HandleMap;
264    ///
265    /// struct Item;
266    ///
267    /// let mut map: HandleMap<Item, &str> = HandleMap::new();
268    /// map.insert("a");
269    /// map.insert("b");
270    /// map.insert("c");
271    ///
272    /// let count = map.iter().count();
273    /// assert_eq!(count, 3);
274    /// ```
275    #[inline]
276    pub fn iter(&self) -> HandleMapIter<'_, T, V> {
277        HandleMapIter {
278            allocator: &self.allocator,
279            values_iter: self.values.iter().enumerate(),
280        }
281    }
282
283    /// Returns a mutable iterator over handle-value pairs.
284    ///
285    /// The iterator yields `(Handle<T>, &mut V)` for each live entry in the map.
286    ///
287    /// # Example
288    ///
289    /// ```
290    /// use goud_engine::core::handle::HandleMap;
291    ///
292    /// struct Counter;
293    ///
294    /// let mut map: HandleMap<Counter, i32> = HandleMap::new();
295    /// map.insert(1);
296    /// map.insert(2);
297    ///
298    /// for (_, value) in map.iter_mut() {
299    ///     *value *= 10;
300    /// }
301    /// ```
302    #[inline]
303    pub fn iter_mut(&mut self) -> HandleMapIterMut<'_, T, V> {
304        HandleMapIterMut {
305            allocator_ptr: &self.allocator as *const HandleAllocator<T>,
306            values_iter: self.values.iter_mut().enumerate(),
307            _marker: PhantomData,
308        }
309    }
310
311    /// Returns an iterator over handles only.
312    ///
313    /// This is more efficient than `iter().map(|(h, _)| h)` if you only need handles.
314    ///
315    /// # Example
316    ///
317    /// ```
318    /// use goud_engine::core::handle::HandleMap;
319    ///
320    /// struct Entity;
321    ///
322    /// let mut map: HandleMap<Entity, ()> = HandleMap::new();
323    /// map.insert(());
324    /// map.insert(());
325    ///
326    /// let handles: Vec<_> = map.handles().collect();
327    /// assert_eq!(handles.len(), 2);
328    /// ```
329    #[inline]
330    pub fn handles(&self) -> HandleMapHandles<'_, T, V> {
331        HandleMapHandles { inner: self.iter() }
332    }
333
334    /// Returns an iterator over values only.
335    ///
336    /// # Example
337    ///
338    /// ```
339    /// use goud_engine::core::handle::HandleMap;
340    ///
341    /// struct Score;
342    ///
343    /// let mut map: HandleMap<Score, i32> = HandleMap::new();
344    /// map.insert(10);
345    /// map.insert(20);
346    /// map.insert(30);
347    ///
348    /// let total: i32 = map.values().sum();
349    /// assert_eq!(total, 60);
350    /// ```
351    #[inline]
352    pub fn values(&self) -> HandleMapValues<'_, T, V> {
353        HandleMapValues { inner: self.iter() }
354    }
355
356    /// Returns a mutable iterator over values only.
357    ///
358    /// # Example
359    ///
360    /// ```
361    /// use goud_engine::core::handle::HandleMap;
362    ///
363    /// struct Data;
364    ///
365    /// let mut map: HandleMap<Data, i32> = HandleMap::new();
366    /// map.insert(1);
367    /// map.insert(2);
368    ///
369    /// for value in map.values_mut() {
370    ///     *value += 100;
371    /// }
372    /// ```
373    #[inline]
374    pub fn values_mut(&mut self) -> HandleMapValuesMut<'_, T, V> {
375        HandleMapValuesMut {
376            inner: self.iter_mut(),
377        }
378    }
379}
380
381/// Allows iterating over a `HandleMap` with a for loop.
382impl<'a, T, V> IntoIterator for &'a HandleMap<T, V> {
383    type Item = (Handle<T>, &'a V);
384    type IntoIter = HandleMapIter<'a, T, V>;
385
386    #[inline]
387    fn into_iter(self) -> Self::IntoIter {
388        self.iter()
389    }
390}
391
392/// Allows mutably iterating over a `HandleMap` with a for loop.
393impl<'a, T, V> IntoIterator for &'a mut HandleMap<T, V> {
394    type Item = (Handle<T>, &'a mut V);
395    type IntoIter = HandleMapIterMut<'a, T, V>;
396
397    #[inline]
398    fn into_iter(self) -> Self::IntoIter {
399        self.iter_mut()
400    }
401}