Skip to content

Commit

Permalink
Added Lots::iter_mut
Browse files Browse the repository at this point in the history
  • Loading branch information
ecton committed Dec 1, 2023
1 parent 7535473 commit 8868932
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- `Lots::iter_mut()` is now implemented.

## v0.3.0 (2023-07-25)

### Added
Expand Down
53 changes: 50 additions & 3 deletions src/unordered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,11 @@ impl<T> Lots<T> {
Some(lot) if lot.generation() == id.generation() => {
if let SlotData::Populated { .. } = lot {
let generation = lot.generation();
let SlotData::Populated { contents, .. } = mem::replace(lot, SlotData::Empty { generation }) else { unreachable!() };
let SlotData::Populated { contents, .. } =
mem::replace(lot, SlotData::Empty { generation })
else {
unreachable!()
};
self.free_indicies.push(id.index());
return Some(contents);
}
Expand Down Expand Up @@ -225,6 +229,13 @@ impl<T> Lots<T> {
self.into_iter()
}

/// Returns an iterator of exclusive references to all contained values.
#[inline]
#[must_use]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
self.into_iter()
}

/// Returns an `Iterator<Item = (LotId, &T)>` for all contained values.
#[inline]
#[must_use]
Expand Down Expand Up @@ -294,6 +305,24 @@ impl<'a, T> Iterator for Iter<'a, T> {
}
}

/// An iterator providing exclusive access to all values contained in a
/// [`Lots<T>`].
pub struct IterMut<'a, T>(slice::IterMut<'a, SlotData<T>>);

impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.0.next()? {
SlotData::Empty { .. } => {}
SlotData::Populated { contents, .. } => return Some(contents),
}
}
}
}

/// An iterator over a [`Lots<T>`] that returns each contained value and its
/// associated [`LotId`].
#[derive(Clone)]
Expand Down Expand Up @@ -351,7 +380,11 @@ where
{
if self.filter.filter(contents) {
let generation = *generation;
let SlotData::Populated { contents, .. } = mem::replace(lot, SlotData::Empty{ generation }) else { unreachable!("just matched") };
let SlotData::Populated { contents, .. } =
mem::replace(lot, SlotData::Empty { generation })
else {
unreachable!("just matched")
};
self.map.free_indicies.push(self.index);
return Some(contents);
}
Expand Down Expand Up @@ -410,6 +443,16 @@ impl<'a, T> IntoIterator for &'a Lots<T> {
}
}

impl<'a, T> IntoIterator for &'a mut Lots<T> {
type IntoIter = IterMut<'a, T>;
type Item = &'a mut T;

#[inline]
fn into_iter(self) -> Self::IntoIter {
IterMut(self.slots.iter_mut())
}
}

/// An iterator that removes all values from the collection and frees the
/// underlying collection.
pub struct IntoIter<T>(vec::IntoIter<SlotData<T>>);
Expand Down Expand Up @@ -485,6 +528,7 @@ fn slot_reuse() {
}

#[test]
#[allow(clippy::explicit_iter_loop)] // this was chosen for code coverage
fn iteration() {
let mut map = Lots::default();
map.push(1);
Expand All @@ -497,8 +541,11 @@ fn iteration() {

let values = map.iter().copied().collect::<Vec<_>>();
assert_eq!(values, &[1, 3, 4]);
for value in map.iter_mut() {
*value += 1;
}
let values = map.into_iter().collect::<Vec<_>>();
assert_eq!(values, &[1, 3, 4]);
assert_eq!(values, &[2, 4, 5]);
}

#[test]
Expand Down

0 comments on commit 8868932

Please sign in to comment.