Skip to content

Commit c5e0607

Browse files
committed
fix(todo): implement IntoIterator for ArenaMap<IDX, V>
1 parent a4966c9 commit c5e0607

File tree

1 file changed

+58
-6
lines changed

1 file changed

+58
-6
lines changed

lib/la-arena/src/map.rs

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::iter::Enumerate;
12
use std::marker::PhantomData;
23

34
use crate::Idx;
@@ -94,12 +95,6 @@ impl<T, V> ArenaMap<Idx<T>, V> {
9495
.filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_mut()?)))
9596
}
9697

97-
/// Returns an iterator over the arena indexes and values in the map.
98-
// FIXME: Implement `IntoIterator` trait.
99-
pub fn into_iter(self) -> impl Iterator<Item = (Idx<T>, V)> + DoubleEndedIterator {
100-
self.v.into_iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o?)))
101-
}
102-
10398
/// Gets the given key's corresponding entry in the map for in-place manipulation.
10499
pub fn entry(&mut self, idx: Idx<T>) -> Entry<'_, Idx<T>, V> {
105100
let idx = Self::to_idx(idx);
@@ -154,6 +149,63 @@ impl<T, V> FromIterator<(Idx<V>, T)> for ArenaMap<Idx<V>, T> {
154149
}
155150
}
156151

152+
pub struct ArenaMapIter<IDX, V> {
153+
iter: Enumerate<std::vec::IntoIter<Option<V>>>,
154+
_ty: PhantomData<IDX>,
155+
}
156+
157+
impl<T, V> IntoIterator for ArenaMap<Idx<T>, V> {
158+
type Item = (Idx<T>, V);
159+
160+
type IntoIter = ArenaMapIter<Idx<T>, V>;
161+
162+
fn into_iter(self) -> Self::IntoIter {
163+
let iter = self.v.into_iter().enumerate();
164+
Self::IntoIter { iter, _ty: PhantomData }
165+
}
166+
}
167+
168+
impl<T, V> ArenaMapIter<Idx<T>, V> {
169+
fn mapper((idx, o): (usize, Option<V>)) -> Option<(Idx<T>, V)> {
170+
Some((ArenaMap::<Idx<T>, V>::from_idx(idx), o?))
171+
}
172+
}
173+
174+
impl<T, V> Iterator for ArenaMapIter<Idx<T>, V> {
175+
type Item = (Idx<T>, V);
176+
177+
#[inline]
178+
fn next(&mut self) -> Option<Self::Item> {
179+
for next in self.iter.by_ref() {
180+
match Self::mapper(next) {
181+
Some(r) => return Some(r),
182+
None => continue,
183+
}
184+
}
185+
186+
None
187+
}
188+
189+
#[inline]
190+
fn size_hint(&self) -> (usize, Option<usize>) {
191+
self.iter.size_hint()
192+
}
193+
}
194+
195+
impl<T, V> DoubleEndedIterator for ArenaMapIter<Idx<T>, V> {
196+
#[inline]
197+
fn next_back(&mut self) -> Option<Self::Item> {
198+
while let Some(next_back) = self.iter.next_back() {
199+
match Self::mapper(next_back) {
200+
Some(r) => return Some(r),
201+
None => continue,
202+
}
203+
}
204+
205+
None
206+
}
207+
}
208+
157209
/// A view into a single entry in a map, which may either be vacant or occupied.
158210
///
159211
/// This `enum` is constructed from the [`entry`] method on [`ArenaMap`].

0 commit comments

Comments
 (0)