about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexis (Poliorcetics) Bourget <ab_github@poliorcetiq.eu>2023-05-06 15:37:38 +0200
committerAlexis (Poliorcetics) Bourget <ab_github@poliorcetiq.eu>2023-05-06 15:37:38 +0200
commitc5e0607915075b37c3eb0e4d3caf8aac4d0b76ec (patch)
treefcde38b990af5c2f2ed1181ce1126981736ad0b9
parenta4966c92829f945d3846eb0ca0e240ac7f7c8c60 (diff)
downloadrust-c5e0607915075b37c3eb0e4d3caf8aac4d0b76ec.tar.gz
rust-c5e0607915075b37c3eb0e4d3caf8aac4d0b76ec.zip
fix(todo): implement IntoIterator for ArenaMap<IDX, V>
-rw-r--r--lib/la-arena/src/map.rs64
1 files changed, 58 insertions, 6 deletions
diff --git a/lib/la-arena/src/map.rs b/lib/la-arena/src/map.rs
index 610f7d92d65..750f345b539 100644
--- a/lib/la-arena/src/map.rs
+++ b/lib/la-arena/src/map.rs
@@ -1,3 +1,4 @@
+use std::iter::Enumerate;
 use std::marker::PhantomData;
 
 use crate::Idx;
@@ -94,12 +95,6 @@ impl<T, V> ArenaMap<Idx<T>, V> {
             .filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_mut()?)))
     }
 
-    /// Returns an iterator over the arena indexes and values in the map.
-    // FIXME: Implement `IntoIterator` trait.
-    pub fn into_iter(self) -> impl Iterator<Item = (Idx<T>, V)> + DoubleEndedIterator {
-        self.v.into_iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o?)))
-    }
-
     /// Gets the given key's corresponding entry in the map for in-place manipulation.
     pub fn entry(&mut self, idx: Idx<T>) -> Entry<'_, Idx<T>, V> {
         let idx = Self::to_idx(idx);
@@ -154,6 +149,63 @@ impl<T, V> FromIterator<(Idx<V>, T)> for ArenaMap<Idx<V>, T> {
     }
 }
 
+pub struct ArenaMapIter<IDX, V> {
+    iter: Enumerate<std::vec::IntoIter<Option<V>>>,
+    _ty: PhantomData<IDX>,
+}
+
+impl<T, V> IntoIterator for ArenaMap<Idx<T>, V> {
+    type Item = (Idx<T>, V);
+
+    type IntoIter = ArenaMapIter<Idx<T>, V>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        let iter = self.v.into_iter().enumerate();
+        Self::IntoIter { iter, _ty: PhantomData }
+    }
+}
+
+impl<T, V> ArenaMapIter<Idx<T>, V> {
+    fn mapper((idx, o): (usize, Option<V>)) -> Option<(Idx<T>, V)> {
+        Some((ArenaMap::<Idx<T>, V>::from_idx(idx), o?))
+    }
+}
+
+impl<T, V> Iterator for ArenaMapIter<Idx<T>, V> {
+    type Item = (Idx<T>, V);
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        for next in self.iter.by_ref() {
+            match Self::mapper(next) {
+                Some(r) => return Some(r),
+                None => continue,
+            }
+        }
+
+        None
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<T, V> DoubleEndedIterator for ArenaMapIter<Idx<T>, V> {
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        while let Some(next_back) = self.iter.next_back() {
+            match Self::mapper(next_back) {
+                Some(r) => return Some(r),
+                None => continue,
+            }
+        }
+
+        None
+    }
+}
+
 /// A view into a single entry in a map, which may either be vacant or occupied.
 ///
 /// This `enum` is constructed from the [`entry`] method on [`ArenaMap`].