Skip to content

Commit 22c0b4e

Browse files
authored
Merge pull request #335 from epage/mut
Alow Mutating Entry keys and iterator keys
2 parents 7f7d39f + 39f7cc0 commit 22c0b4e

File tree

7 files changed

+163
-3
lines changed

7 files changed

+163
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "indexmap"
33
edition = "2021"
4-
version = "2.2.6"
4+
version = "2.3.0"
55
documentation = "https://docs.rs/indexmap/"
66
repository = "https://github.com/indexmap-rs/indexmap"
77
license = "Apache-2.0 OR MIT"

RELEASES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Releases
22

3+
## 2.3.0
4+
5+
- Added trait `MutableEntryKey` for opt-in mutable access to map entry keys.
6+
- Added method `MutableKeys::iter_mut2` for opt-in mutable iteration of map
7+
keys and values.
8+
39
## 2.2.6
410

511
- Added trait `MutableValues` for opt-in mutable access to set values.

src/map.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ mod tests;
1616
pub use self::core::raw_entry_v1::{self, RawEntryApiV1};
1717
pub use self::core::{Entry, IndexedEntry, OccupiedEntry, VacantEntry};
1818
pub use self::iter::{
19-
Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Splice, Values, ValuesMut,
19+
Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, IterMut2, Keys, Splice, Values, ValuesMut,
2020
};
21+
pub use self::mutable::MutableEntryKey;
2122
pub use self::mutable::MutableKeys;
2223
pub use self::slice::Slice;
2324

src/map/core/entry.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
144144
&self.raw.bucket().key
145145
}
146146

147+
pub(crate) fn key_mut(&mut self) -> &mut K {
148+
&mut self.raw.bucket_mut().key
149+
}
150+
147151
/// Gets a reference to the entry's value in the map.
148152
pub fn get(&self) -> &V {
149153
&self.raw.bucket().value
@@ -297,6 +301,10 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
297301
&self.key
298302
}
299303

304+
pub(crate) fn key_mut(&mut self) -> &mut K {
305+
&mut self.key
306+
}
307+
300308
/// Takes ownership of the key, leaving the entry vacant.
301309
pub fn into_key(self) -> K {
302310
self.key
@@ -373,6 +381,10 @@ impl<'a, K, V> IndexedEntry<'a, K, V> {
373381
&self.map.entries[self.index].key
374382
}
375383

384+
pub(crate) fn key_mut(&mut self) -> &mut K {
385+
&mut self.map.entries[self.index].key
386+
}
387+
376388
/// Gets a reference to the entry's value in the map.
377389
pub fn get(&self) -> &V {
378390
&self.map.entries[self.index].value

src/map/iter.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,67 @@ impl<K, V> Default for IterMut<'_, K, V> {
156156
}
157157
}
158158

159+
/// A mutable iterator over the entries of an [`IndexMap`].
160+
///
161+
/// This `struct` is created by the [`MutableKeys::iter_mut2`][super::MutableKeys::iter_mut2] method.
162+
/// See its documentation for more.
163+
pub struct IterMut2<'a, K, V> {
164+
iter: slice::IterMut<'a, Bucket<K, V>>,
165+
}
166+
167+
impl<'a, K, V> IterMut2<'a, K, V> {
168+
pub(super) fn new(entries: &'a mut [Bucket<K, V>]) -> Self {
169+
Self {
170+
iter: entries.iter_mut(),
171+
}
172+
}
173+
174+
/// Returns a slice of the remaining entries in the iterator.
175+
pub fn as_slice(&self) -> &Slice<K, V> {
176+
Slice::from_slice(self.iter.as_slice())
177+
}
178+
179+
/// Returns a mutable slice of the remaining entries in the iterator.
180+
///
181+
/// To avoid creating `&mut` references that alias, this is forced to consume the iterator.
182+
pub fn into_slice(self) -> &'a mut Slice<K, V> {
183+
Slice::from_mut_slice(self.iter.into_slice())
184+
}
185+
}
186+
187+
impl<'a, K, V> Iterator for IterMut2<'a, K, V> {
188+
type Item = (&'a mut K, &'a mut V);
189+
190+
iterator_methods!(Bucket::muts);
191+
}
192+
193+
impl<K, V> DoubleEndedIterator for IterMut2<'_, K, V> {
194+
double_ended_iterator_methods!(Bucket::muts);
195+
}
196+
197+
impl<K, V> ExactSizeIterator for IterMut2<'_, K, V> {
198+
fn len(&self) -> usize {
199+
self.iter.len()
200+
}
201+
}
202+
203+
impl<K, V> FusedIterator for IterMut2<'_, K, V> {}
204+
205+
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut2<'_, K, V> {
206+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207+
let iter = self.iter.as_slice().iter().map(Bucket::refs);
208+
f.debug_list().entries(iter).finish()
209+
}
210+
}
211+
212+
impl<K, V> Default for IterMut2<'_, K, V> {
213+
fn default() -> Self {
214+
Self {
215+
iter: [].iter_mut(),
216+
}
217+
}
218+
}
219+
159220
/// An owning iterator over the entries of an [`IndexMap`].
160221
///
161222
/// This `struct` is created by the [`IndexMap::into_iter`] method

src/map/mutable.rs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use core::hash::{BuildHasher, Hash};
22

3-
use super::{Bucket, Entries, Equivalent, IndexMap};
3+
use super::{
4+
Bucket, Entries, Entry, Equivalent, IndexMap, IndexedEntry, IterMut2, OccupiedEntry,
5+
VacantEntry,
6+
};
47

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

40+
/// Return an iterator over the key-value pairs of the map, in their order
41+
fn iter_mut2(&mut self) -> IterMut2<'_, Self::Key, Self::Value>;
42+
3743
/// Scan through each key-value pair in the map and keep those where the
3844
/// closure `keep` returns `true`.
3945
///
@@ -72,6 +78,10 @@ where
7278
self.as_entries_mut().get_mut(index).map(Bucket::muts)
7379
}
7480

81+
fn iter_mut2(&mut self) -> IterMut2<'_, Self::Key, Self::Value> {
82+
IterMut2::new(self.as_entries_mut())
83+
}
84+
7585
fn retain2<F>(&mut self, keep: F)
7686
where
7787
F: FnMut(&mut K, &mut V) -> bool,
@@ -80,8 +90,77 @@ where
8090
}
8191
}
8292

93+
/// Opt-in mutable access to [`Entry`] keys.
94+
///
95+
/// These methods expose `&mut K`, mutable references to the key as it is stored
96+
/// in the map.
97+
/// You are allowed to modify the keys in the map **if the modification
98+
/// does not change the key’s hash and equality**.
99+
///
100+
/// If keys are modified erroneously, you can no longer look them up.
101+
/// This is sound (memory safe) but a logical error hazard (just like
102+
/// implementing `PartialEq`, `Eq`, or `Hash` incorrectly would be).
103+
///
104+
/// `use` this trait to enable its methods for `Entry`.
105+
///
106+
/// This trait is sealed and cannot be implemented for types outside this crate.
107+
pub trait MutableEntryKey: private::Sealed {
108+
type Key;
109+
fn key_mut(&mut self) -> &mut Self::Key;
110+
}
111+
112+
/// Opt-in mutable access to [`Entry`] keys.
113+
///
114+
/// See [`MutableEntryKey`] for more information.
115+
impl<K, V> MutableEntryKey for Entry<'_, K, V> {
116+
type Key = K;
117+
118+
/// Gets a mutable reference to the entry's key, either within the map if occupied,
119+
/// or else the new key that was used to find the entry.
120+
fn key_mut(&mut self) -> &mut Self::Key {
121+
match self {
122+
Entry::Occupied(e) => e.key_mut(),
123+
Entry::Vacant(e) => e.key_mut(),
124+
}
125+
}
126+
}
127+
128+
/// Opt-in mutable access to [`OccupiedEntry`] keys.
129+
///
130+
/// See [`MutableEntryKey`] for more information.
131+
impl<K, V> MutableEntryKey for OccupiedEntry<'_, K, V> {
132+
type Key = K;
133+
fn key_mut(&mut self) -> &mut Self::Key {
134+
self.key_mut()
135+
}
136+
}
137+
138+
/// Opt-in mutable access to [`VacantEntry`] keys.
139+
///
140+
/// See [`MutableEntryKey`] for more information.
141+
impl<K, V> MutableEntryKey for VacantEntry<'_, K, V> {
142+
type Key = K;
143+
fn key_mut(&mut self) -> &mut Self::Key {
144+
self.key_mut()
145+
}
146+
}
147+
148+
/// Opt-in mutable access to [`IndexedEntry`] keys.
149+
///
150+
/// See [`MutableEntryKey`] for more information.
151+
impl<K, V> MutableEntryKey for IndexedEntry<'_, K, V> {
152+
type Key = K;
153+
fn key_mut(&mut self) -> &mut Self::Key {
154+
self.key_mut()
155+
}
156+
}
157+
83158
mod private {
84159
pub trait Sealed {}
85160

86161
impl<K, V, S> Sealed for super::IndexMap<K, V, S> {}
162+
impl<K, V> Sealed for super::Entry<'_, K, V> {}
163+
impl<K, V> Sealed for super::OccupiedEntry<'_, K, V> {}
164+
impl<K, V> Sealed for super::VacantEntry<'_, K, V> {}
165+
impl<K, V> Sealed for super::IndexedEntry<'_, K, V> {}
87166
}

src/map/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ fn iter_default() {
497497
}
498498
assert_default::<Iter<'static, K, V>>();
499499
assert_default::<IterMut<'static, K, V>>();
500+
assert_default::<IterMut2<'static, K, V>>();
500501
assert_default::<IntoIter<K, V>>();
501502
assert_default::<Keys<'static, K, V>>();
502503
assert_default::<IntoKeys<K, V>>();

0 commit comments

Comments
 (0)