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 ArenaMap, 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, 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) -> Entry<'_, Idx, V> { let idx = Self::to_idx(idx); @@ -154,6 +149,63 @@ impl FromIterator<(Idx, T)> for ArenaMap, T> { } } +pub struct ArenaMapIter { + iter: Enumerate>>, + _ty: PhantomData, +} + +impl IntoIterator for ArenaMap, V> { + type Item = (Idx, V); + + type IntoIter = ArenaMapIter, V>; + + fn into_iter(self) -> Self::IntoIter { + let iter = self.v.into_iter().enumerate(); + Self::IntoIter { iter, _ty: PhantomData } + } +} + +impl ArenaMapIter, V> { + fn mapper((idx, o): (usize, Option)) -> Option<(Idx, V)> { + Some((ArenaMap::, V>::from_idx(idx), o?)) + } +} + +impl Iterator for ArenaMapIter, V> { + type Item = (Idx, V); + + #[inline] + fn next(&mut self) -> Option { + 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) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for ArenaMapIter, V> { + #[inline] + fn next_back(&mut self) -> Option { + 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`].