diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b3bde7..fde507a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/unordered.rs b/src/unordered.rs index b86a7f1..ca85033 100644 --- a/src/unordered.rs +++ b/src/unordered.rs @@ -161,7 +161,11 @@ impl Lots { 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); } @@ -225,6 +229,13 @@ impl Lots { 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` for all contained values. #[inline] #[must_use] @@ -294,6 +305,24 @@ impl<'a, T> Iterator for Iter<'a, T> { } } +/// An iterator providing exclusive access to all values contained in a +/// [`Lots`]. +pub struct IterMut<'a, T>(slice::IterMut<'a, SlotData>); + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option { + loop { + match self.0.next()? { + SlotData::Empty { .. } => {} + SlotData::Populated { contents, .. } => return Some(contents), + } + } + } +} + /// An iterator over a [`Lots`] that returns each contained value and its /// associated [`LotId`]. #[derive(Clone)] @@ -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); } @@ -410,6 +443,16 @@ impl<'a, T> IntoIterator for &'a Lots { } } +impl<'a, T> IntoIterator for &'a mut Lots { + 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(vec::IntoIter>); @@ -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); @@ -497,8 +541,11 @@ fn iteration() { let values = map.iter().copied().collect::>(); assert_eq!(values, &[1, 3, 4]); + for value in map.iter_mut() { + *value += 1; + } let values = map.into_iter().collect::>(); - assert_eq!(values, &[1, 3, 4]); + assert_eq!(values, &[2, 4, 5]); } #[test]