Skip to content

Commit 7224def

Browse files
committed
Add insert_before as an alternate to shift_insert
1 parent 0247a15 commit 7224def

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

src/map.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,12 +445,52 @@ where
445445
}
446446
}
447447

448+
/// Insert a key-value pair in the map before the entry at the given index, or at the end.
449+
///
450+
/// If an equivalent key already exists in the map: the key remains and
451+
/// is moved to the new position in the map, its corresponding value is updated
452+
/// with `value`, and the older value is returned inside `Some(_)`. The returned index
453+
/// will either be the given index or one less, depending on how the entry moved.
454+
/// (See [`shift_insert`](Self::shift_insert) for different behavior here.)
455+
///
456+
/// If no equivalent key existed in the map: the new key-value pair is
457+
/// inserted exactly at the given index, and `None` is returned.
458+
///
459+
/// ***Panics*** if `index` is out of bounds.
460+
/// Valid indices are `0..=map.len()` (inclusive).
461+
///
462+
/// Computes in **O(n)** time (average).
463+
///
464+
/// See also [`entry`][Self::entry] if you want to insert *or* modify,
465+
/// perhaps only using the index for new entries with [`VacantEntry::shift_insert`].
466+
pub fn insert_before(&mut self, mut index: usize, key: K, value: V) -> (usize, Option<V>) {
467+
assert!(index <= self.len(), "index out of bounds");
468+
match self.entry(key) {
469+
Entry::Occupied(mut entry) => {
470+
if index > entry.index() {
471+
// Some entries will shift down when this one moves up,
472+
// so "insert before index" becomes "move to index - 1",
473+
// keeping the entry at the original index unmoved.
474+
index -= 1;
475+
}
476+
let old = mem::replace(entry.get_mut(), value);
477+
entry.move_index(index);
478+
(index, Some(old))
479+
}
480+
Entry::Vacant(entry) => {
481+
entry.shift_insert(index, value);
482+
(index, None)
483+
}
484+
}
485+
}
486+
448487
/// Insert a key-value pair in the map at the given index.
449488
///
450489
/// If an equivalent key already exists in the map: the key remains and
451490
/// is moved to the given index in the map, its corresponding value is updated
452491
/// with `value`, and the older value is returned inside `Some(_)`.
453492
/// Note that existing entries **cannot** be moved to `index == map.len()`!
493+
/// (See [`insert_before`](Self::insert_before) for different behavior here.)
454494
///
455495
/// If no equivalent key existed in the map: the new key-value pair is
456496
/// inserted at the given index, and `None` is returned.

src/set.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,11 +383,30 @@ where
383383
(index, existing.is_none())
384384
}
385385

386+
/// Insert the value into the set before the value at the given index, or at the end.
387+
///
388+
/// If an equivalent item already exists in the set, it returns `false` leaving the
389+
/// original value in the set, but moved to the new position. The returned index
390+
/// will either be the given index or one less, depending on how the value moved.
391+
/// (See [`shift_insert`](Self::shift_insert) for different behavior here.)
392+
///
393+
/// Otherwise, it inserts the new value exactly at the given index and returns `true`.
394+
///
395+
/// ***Panics*** if `index` is out of bounds.
396+
/// Valid indices are `0..=set.len()` (inclusive).
397+
///
398+
/// Computes in **O(n)** time (average).
399+
pub fn insert_before(&mut self, index: usize, value: T) -> (usize, bool) {
400+
let (index, existing) = self.map.insert_before(index, value, ());
401+
(index, existing.is_none())
402+
}
403+
386404
/// Insert the value into the set at the given index.
387405
///
388406
/// If an equivalent item already exists in the set, it returns `false` leaving
389407
/// the original value in the set, but moved to the given index.
390408
/// Note that existing values **cannot** be moved to `index == set.len()`!
409+
/// (See [`insert_before`](Self::insert_before) for different behavior here.)
391410
///
392411
/// Otherwise, it inserts the new value at the given index and returns `true`.
393412
///

0 commit comments

Comments
 (0)