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}