Skip to content

Commit 539b401

Browse files
authored
Merge pull request #361 from cuviper/insert_entry
Add `{Entry,VacantEntry}::insert_entry`
2 parents dceb0f0 + 998edb1 commit 539b401

File tree

5 files changed

+72
-30
lines changed

5 files changed

+72
-30
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.6.0"
4+
version = "2.7.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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Releases
22

3+
## 2.7.0 (2024-11-30)
4+
5+
- Added methods `Entry::insert_entry` and `VacantEntry::insert_entry`, returning
6+
an `OccupiedEntry` after insertion.
7+
38
## 2.6.0 (2024-10-01)
49

510
- Implemented `Clone` for `map::IntoIter` and `set::IntoIter`.

src/map/core.rs

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,17 @@ impl<K, V> IndexMapCore<K, V> {
316316
self.indices.find(hash.get(), eq).copied()
317317
}
318318

319+
/// Append a key-value pair to `entries`,
320+
/// *without* checking whether it already exists.
321+
fn push_entry(&mut self, hash: HashValue, key: K, value: V) {
322+
if self.entries.len() == self.entries.capacity() {
323+
// Reserve our own capacity synced to the indices,
324+
// rather than letting `Vec::push` just double it.
325+
self.borrow_mut().reserve_entries(1);
326+
}
327+
self.entries.push(Bucket { hash, key, value });
328+
}
329+
319330
pub(crate) fn insert_full(&mut self, hash: HashValue, key: K, value: V) -> (usize, Option<V>)
320331
where
321332
K: Eq,
@@ -330,7 +341,7 @@ impl<K, V> IndexMapCore<K, V> {
330341
hash_table::Entry::Vacant(entry) => {
331342
let i = self.entries.len();
332343
entry.insert(i);
333-
self.borrow_mut().push_entry(hash, key, value);
344+
self.push_entry(hash, key, value);
334345
debug_assert_eq!(self.indices.len(), self.entries.len());
335346
(i, None)
336347
}
@@ -362,7 +373,7 @@ impl<K, V> IndexMapCore<K, V> {
362373
hash_table::Entry::Vacant(entry) => {
363374
let i = self.entries.len();
364375
entry.insert(i);
365-
self.borrow_mut().push_entry(hash, key, value);
376+
self.push_entry(hash, key, value);
366377
debug_assert_eq!(self.indices.len(), self.entries.len());
367378
(i, None)
368379
}
@@ -522,37 +533,25 @@ impl<'a, K, V> RefMut<'a, K, V> {
522533
self.entries.reserve_exact(additional);
523534
}
524535

525-
/// Append a key-value pair to `entries`,
536+
/// Insert a key-value pair in `entries`,
526537
/// *without* checking whether it already exists.
527-
fn push_entry(&mut self, hash: HashValue, key: K, value: V) {
538+
fn insert_unique(mut self, hash: HashValue, key: K, value: V) -> OccupiedEntry<'a, K, V> {
528539
if self.entries.len() == self.entries.capacity() {
529540
// Reserve our own capacity synced to the indices,
530541
// rather than letting `Vec::push` just double it.
531542
self.reserve_entries(1);
532543
}
533-
self.entries.push(Bucket { hash, key, value });
534-
}
535-
536-
/// Insert a key-value pair in `entries` at a particular index,
537-
/// *without* checking whether it already exists.
538-
fn insert_entry(&mut self, index: usize, hash: HashValue, key: K, value: V) {
539-
if self.entries.len() == self.entries.capacity() {
540-
// Reserve our own capacity synced to the indices,
541-
// rather than letting `Vec::insert` just double it.
542-
self.reserve_entries(1);
543-
}
544-
self.entries.insert(index, Bucket { hash, key, value });
545-
}
546-
547-
fn insert_unique(&mut self, hash: HashValue, key: K, value: V) -> usize {
548544
let i = self.indices.len();
549-
self.indices
545+
let entry = self
546+
.indices
550547
.insert_unique(hash.get(), i, get_hash(self.entries));
551548
debug_assert_eq!(i, self.entries.len());
552-
self.push_entry(hash, key, value);
553-
i
549+
self.entries.push(Bucket { hash, key, value });
550+
OccupiedEntry::new(self.entries, entry)
554551
}
555552

553+
/// Insert a key-value pair in `entries` at a particular index,
554+
/// *without* checking whether it already exists.
556555
fn shift_insert_unique(&mut self, index: usize, hash: HashValue, key: K, value: V) {
557556
let end = self.indices.len();
558557
assert!(index <= end);
@@ -565,7 +564,12 @@ impl<'a, K, V> RefMut<'a, K, V> {
565564
let i = if i < index { i } else { i - 1 };
566565
entries[i].hash.get()
567566
});
568-
self.insert_entry(index, hash, key, value);
567+
if self.entries.len() == self.entries.capacity() {
568+
// Reserve our own capacity synced to the indices,
569+
// rather than letting `Vec::insert` just double it.
570+
self.reserve_entries(1);
571+
}
572+
self.entries.insert(index, Bucket { hash, key, value });
569573
}
570574

571575
/// Remove an entry by shifting all entries that follow it

src/map/core/entry.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ impl<'a, K, V> Entry<'a, K, V> {
3939
}
4040
}
4141

42+
/// Sets the value of the entry (after inserting if vacant), and returns an `OccupiedEntry`.
43+
///
44+
/// Computes in **O(1)** time (amortized average).
45+
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
46+
match self {
47+
Entry::Occupied(mut entry) => {
48+
entry.insert(value);
49+
entry
50+
}
51+
Entry::Vacant(entry) => entry.insert_entry(value),
52+
}
53+
}
54+
4255
/// Inserts the given default value in the entry if it is vacant and returns a mutable
4356
/// reference to it. Otherwise a mutable reference to an already existent value is returned.
4457
///
@@ -136,6 +149,13 @@ pub struct OccupiedEntry<'a, K, V> {
136149
}
137150

138151
impl<'a, K, V> OccupiedEntry<'a, K, V> {
152+
pub(crate) fn new(
153+
entries: &'a mut Entries<K, V>,
154+
index: hash_table::OccupiedEntry<'a, usize>,
155+
) -> Self {
156+
Self { entries, index }
157+
}
158+
139159
/// Return the index of the key-value pair
140160
#[inline]
141161
pub fn index(&self) -> usize {
@@ -182,6 +202,11 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
182202
&mut self.entries[index].value
183203
}
184204

205+
pub(super) fn into_muts(self) -> (&'a mut K, &'a mut V) {
206+
let index = self.index();
207+
self.entries[index].muts()
208+
}
209+
185210
/// Sets the value of the entry to `value`, and returns the entry's old value.
186211
pub fn insert(&mut self, value: V) -> V {
187212
mem::replace(self.get_mut(), value)
@@ -343,9 +368,18 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
343368

344369
/// Inserts the entry's key and the given value into the map, and returns a mutable reference
345370
/// to the value.
346-
pub fn insert(mut self, value: V) -> &'a mut V {
347-
let i = self.map.insert_unique(self.hash, self.key, value);
348-
&mut self.map.entries[i].value
371+
///
372+
/// Computes in **O(1)** time (amortized average).
373+
pub fn insert(self, value: V) -> &'a mut V {
374+
self.insert_entry(value).into_mut()
375+
}
376+
377+
/// Inserts the entry's key and the given value into the map, and returns an `OccupiedEntry`.
378+
///
379+
/// Computes in **O(1)** time (amortized average).
380+
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
381+
let Self { map, hash, key } = self;
382+
map.insert_unique(hash, key, value)
349383
}
350384

351385
/// Inserts the entry's key and the given value into the map at its ordered

src/map/core/raw_entry_v1.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -618,10 +618,9 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
618618

619619
/// Inserts the given key and value into the map with the provided hash,
620620
/// and returns mutable references to them.
621-
pub fn insert_hashed_nocheck(mut self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) {
621+
pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) {
622622
let hash = HashValue(hash as usize);
623-
let i = self.map.insert_unique(hash, key, value);
624-
self.map.entries[i].muts()
623+
self.map.insert_unique(hash, key, value).into_muts()
625624
}
626625

627626
/// Inserts the given key and value into the map at the given index,

0 commit comments

Comments
 (0)