Skip to content

Commit

Permalink
feat(map): Add MutableKeys::iter_mut2
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jul 28, 2024
1 parent 109e4e3 commit dbcba0c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mod tests;
pub use self::core::raw_entry_v1::{self, RawEntryApiV1};
pub use self::core::{Entry, IndexedEntry, OccupiedEntry, VacantEntry};
pub use self::iter::{
Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Splice, Values, ValuesMut,
Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, IterMut2, Keys, Splice, Values, ValuesMut,
};
pub use self::mutable::MutableEntryKey;
pub use self::mutable::MutableKeys;
Expand Down
61 changes: 61 additions & 0 deletions src/map/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,67 @@ impl<K, V> Default for IterMut<'_, K, V> {
}
}

/// A mutable iterator over the entries of an [`IndexMap`].
///
/// This `struct` is created by the [`MutableKeys::iter_mut2`][super::MutableKeys::iter_mut2] method.
/// See its documentation for more.
pub struct IterMut2<'a, K, V> {
iter: slice::IterMut<'a, Bucket<K, V>>,
}

impl<'a, K, V> IterMut2<'a, K, V> {
pub(super) fn new(entries: &'a mut [Bucket<K, V>]) -> Self {
Self {
iter: entries.iter_mut(),
}
}

/// Returns a slice of the remaining entries in the iterator.
pub fn as_slice(&self) -> &Slice<K, V> {
Slice::from_slice(self.iter.as_slice())
}

/// Returns a mutable slice of the remaining entries in the iterator.
///
/// To avoid creating `&mut` references that alias, this is forced to consume the iterator.
pub fn into_slice(self) -> &'a mut Slice<K, V> {
Slice::from_mut_slice(self.iter.into_slice())
}
}

impl<'a, K, V> Iterator for IterMut2<'a, K, V> {
type Item = (&'a mut K, &'a mut V);

iterator_methods!(Bucket::muts);
}

impl<K, V> DoubleEndedIterator for IterMut2<'_, K, V> {
double_ended_iterator_methods!(Bucket::muts);
}

impl<K, V> ExactSizeIterator for IterMut2<'_, K, V> {
fn len(&self) -> usize {
self.iter.len()
}
}

impl<K, V> FusedIterator for IterMut2<'_, K, V> {}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut2<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let iter = self.iter.as_slice().iter().map(Bucket::refs);
f.debug_list().entries(iter).finish()
}
}

impl<K, V> Default for IterMut2<'_, K, V> {
fn default() -> Self {
Self {
iter: [].iter_mut(),
}
}
}

/// An owning iterator over the entries of an [`IndexMap`].
///
/// This `struct` is created by the [`IndexMap::into_iter`] method
Expand Down
10 changes: 9 additions & 1 deletion src/map/mutable.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use core::hash::{BuildHasher, Hash};

use super::{
Bucket, Entries, Entry, Equivalent, IndexMap, IndexedEntry, OccupiedEntry, VacantEntry,
Bucket, Entries, Entry, Equivalent, IndexMap, IndexedEntry, IterMut2, OccupiedEntry,
VacantEntry,
};

/// Opt-in mutable access to [`IndexMap`] keys.
Expand Down Expand Up @@ -36,6 +37,9 @@ pub trait MutableKeys: private::Sealed {
/// Computes in **O(1)** time.
fn get_index_mut2(&mut self, index: usize) -> Option<(&mut Self::Key, &mut Self::Value)>;

/// Return an iterator over the key-value pairs of the map, in their order
fn iter_mut2(&mut self) -> IterMut2<'_, Self::Key, Self::Value>;

/// Scan through each key-value pair in the map and keep those where the
/// closure `keep` returns `true`.
///
Expand Down Expand Up @@ -74,6 +78,10 @@ where
self.as_entries_mut().get_mut(index).map(Bucket::muts)
}

fn iter_mut2(&mut self) -> IterMut2<'_, Self::Key, Self::Value> {
IterMut2::new(self.as_entries_mut())
}

fn retain2<F>(&mut self, keep: F)
where
F: FnMut(&mut K, &mut V) -> bool,
Expand Down
1 change: 1 addition & 0 deletions src/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ fn iter_default() {
}
assert_default::<Iter<'static, K, V>>();
assert_default::<IterMut<'static, K, V>>();
assert_default::<IterMut2<'static, K, V>>();
assert_default::<IntoIter<K, V>>();
assert_default::<Keys<'static, K, V>>();
assert_default::<IntoKeys<K, V>>();
Expand Down

0 comments on commit dbcba0c

Please sign in to comment.