pub struct OverlayMap<K, V, S = DefaultHashBuilder>{ /* private fields */ }
Expand description
A two-layered map where each key holds a current (foreground) and optional historical (background) value.
OverlayMap
is a high-performance associative container designed for efficient, non-cloning updates
and reversible state transitions. When inserting a new value for an existing key, the current
foreground is automatically moved to the background. This allows you to update state while
preserving a previous version — useful for rollback, previews, speculative updates, or undo systems.
All operations are zero-copy and allocation-free beyond what the internal map requires. Background values are stored in-place and never cloned or reallocated.
Internally, each key maps to an Overlay<V>
that manages the foreground and background slots.
The API provides full control over pushing, pulling, and swapping values, with minimal overhead.
§Features
- Efficient push/pull/swap operations
- No cloning or heap allocation for values
- Zero-cost foreground/background transitions
- Map keys only retained when a value is present
§Example
use overlay_map::OverlayMap;
let mut map = OverlayMap::new();
// Insert a new value
map.push("player", 1);
// Overwrite it — original goes to background
map.push("player", 2);
assert_eq!(map.fg(&"player"), Some(&2));
assert_eq!(map.bg(&"player"), Some(&1));
// Pull removes the current foreground and promotes background
let pulled = map.pull(&"player");
assert_eq!(pulled, Some(2));
assert_eq!(map.fg(&"player"), Some(&1));
// Pull again — entry is now removed
let pulled = map.pull(&"player");
assert_eq!(pulled, Some(1));
assert_eq!(map.fg(&"player"), None);
Implementations§
Source§impl<K, V> OverlayMap<K, V, DefaultHashBuilder>
impl<K, V> OverlayMap<K, V, DefaultHashBuilder>
Source§impl<K, V, S> OverlayMap<K, V, S>
impl<K, V, S> OverlayMap<K, V, S>
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates an empty OverlayMap
with the specified capacity and default hasher.
Sourcepub fn with_hasher(hasher: S) -> Self
pub fn with_hasher(hasher: S) -> Self
Creates an empty OverlayMap
that will use the given hasher.
Sourcepub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self
Creates an empty OverlayMap
with the specified capacity and hasher.
Sourcepub fn fg(&self, key: &K) -> Option<&V>
pub fn fg(&self, key: &K) -> Option<&V>
Get an immutable reference to the value associated with the key.
Returns None
if the key was not found in the map.
Sourcepub fn bg(&self, key: &K) -> Option<&V>
pub fn bg(&self, key: &K) -> Option<&V>
Get an immutable reference to the value associated with the key in the background layer.
Returns None
if the key was not found in the background layer.
Sourcepub fn push(&mut self, key: K, value: V) -> bool
pub fn push(&mut self, key: K, value: V) -> bool
Push a value into the foreground layer, preserving the previous value in the background.
If the key was already present, the current foreground is moved to the background slot, and the new value becomes the new foreground. No cloning occurs. The old background value is dropped if it was present.
Returns true
if there was already a foreground value (i.e. a
background now definitely exists).
Sourcepub fn push_if<F>(&mut self, key: &K, predicate: F) -> bool
pub fn push_if<F>(&mut self, key: &K, predicate: F) -> bool
Conditionally push a new value into the foreground based on the current value.
If the key exists, the current foreground value is passed to the
predicate. If the predicate returns Some(new_val)
, the new value is
pushed and the old one is preserved in the background. If it returns
None
, nothing is changed.
Returns true
if a new value was pushed.
Sourcepub fn pull(&mut self, key: &K) -> Option<V>
pub fn pull(&mut self, key: &K) -> Option<V>
Pulls the foreground value for a key, promoting the background to foreground if present.
This removes and returns the current foreground value for the given key. If a background value exists, it is promoted to foreground. If the key has no background after the pull, the key is removed from the map entirely.
§Returns
Some(value)
if the key existed and a foreground value was pulled.None
if the key did not exist.
§Invariants
- After this operation, the key is only retained if a background value was available to promote.
- Keys in the map always have at least one value (foreground), unless removed by
pull
.
§Example
use overlay_map::OverlayMap;
let mut map = OverlayMap::<&str, i32>::new();
map.push("key", 1);
map.push("key", 2);
assert_eq!(map.fg(&"key"), Some(&2));
assert_eq!(map.bg(&"key"), Some(&1));
let pulled = map.pull(&"key");
assert_eq!(pulled, Some(2));
assert_eq!(map.fg(&"key"), Some(&1)); // background promoted
let pulled = map.pull(&"key");
assert_eq!(pulled, Some(1));
assert_eq!(map.fg(&"key"), None); // entry removed
Sourcepub fn pull_if<F>(&mut self, key: &K, predicate: F) -> Option<V>
pub fn pull_if<F>(&mut self, key: &K, predicate: F) -> Option<V>
Conditionally pulls the foreground value for a key, promoting the background if present.
If the key exists and the provided predicate returns true
for the current foreground,
this removes and returns the foreground value. The background (if any) is promoted to
foreground, and the key is removed from the map if no background remains.
If the predicate returns false
or the key does not exist, the map is left unchanged.
§Returns
Some(value)
if the predicate matched and the foreground was pulled.None
if the key was not found or the predicate returnedfalse
.
§Invariants
- After this operation, the key is only retained if a background value was available to promote.
- Keys in the map always have at least one value (foreground), unless removed by
pull_if
.
§Example
use overlay_map::OverlayMap;
let mut map = OverlayMap::<&str, i32>::new();
map.push("key", 10);
map.push("key", 20);
// Only pull if the foreground is 20
let pulled = map.pull_if(&"key", |v| *v == 20);
assert_eq!(pulled, Some(20));
assert_eq!(map.fg(&"key"), Some(&10));
// Predicate does not match: nothing is pulled
let pulled = map.pull_if(&"key", |v| *v == 999);
assert_eq!(pulled, None);
assert_eq!(map.fg(&"key"), Some(&10));
// Pull remaining value, removing the key
let pulled = map.pull_if(&"key", |_| true);
assert_eq!(pulled, Some(10));
assert_eq!(map.fg(&"key"), None);
Sourcepub fn swap(&mut self, key: K, value: V) -> Option<V>
pub fn swap(&mut self, key: K, value: V) -> Option<V>
Swap a value into the foreground layer, preserving the previous value in the background, and returning the evicted background value if present.
If the key was already present, the current foreground is moved to the background slot, and the new value becomes the new foreground. No cloning occurs. The old background value is returned if present.
Sourcepub fn swap_if<F>(&mut self, key: &K, predicate: F) -> Option<V>
pub fn swap_if<F>(&mut self, key: &K, predicate: F) -> Option<V>
Conditionally swap a new value into the foreground based on the current value.
If the key exists, the current foreground value is passed to the
predicate. If the predicate returns Some(new_val)
, the new value is
pushed and the old one is preserved in the background. If it returns
None
, nothing is changed.
The evicted background value is returned if present.
Sourcepub fn flip(&mut self, key: &K)
pub fn flip(&mut self, key: &K)
Flips the foreground and background values for the given key, if present.
This operation swaps the logical roles of the foreground and background values for the specified key. If the key is present in the map, the values are flipped:
- The background becomes the new foreground
- The foreground becomes the new background
This does not move, clone, or reallocate any values — it is a zero-cost operation that simply toggles the internal bit mask controlling foreground/background interpretation.
If the key is not present in the map, or if it has no background value, the operation has no effect.
§Example
use overlay_map::OverlayMap;
let mut map = OverlayMap::new();
map.push("slot", 1);
map.push("slot", 2); // now: fg = 2, bg = 1
map.flip(&"slot");
assert_eq!(map.fg(&"slot"), Some(&1));
assert_eq!(map.bg(&"slot"), Some(&2));
Sourcepub fn extend_count<I>(&mut self, iter: I) -> usizewhere
I: IntoIterator<Item = (K, V)>,
pub fn extend_count<I>(&mut self, iter: I) -> usizewhere
I: IntoIterator<Item = (K, V)>,
Extends the map with a sequence of key-value pairs, counting foreground replacements.
Each (K, V)
pair is pushed into the foreground. If a key already exists,
the current foreground is moved to the background, and the new value becomes
the new foreground. If the key is new, it is inserted without affecting any background.
This method returns the number of keys that were already present — i.e., how many pushes replaced an existing foreground value.
No cloning or heap allocation is performed beyond what’s necessary for the HashMap
.
§Example
use overlay_map::OverlayMap;
let mut map = OverlayMap::new();
map.push("a", 1);
let replaced = map.extend_count([("a", 2), ("b", 3)]);
assert_eq!(replaced, 1); // "a" was already present, "b" was new
assert_eq!(map.fg(&"a"), Some(&2));
assert_eq!(map.bg(&"a"), Some(&1));
assert_eq!(map.fg(&"b"), Some(&3));
Trait Implementations§
Source§impl<K, V, S> Clone for OverlayMap<K, V, S>
impl<K, V, S> Clone for OverlayMap<K, V, S>
Source§impl<K, V: Default, S: Default> Default for OverlayMap<K, V, S>
impl<K, V: Default, S: Default> Default for OverlayMap<K, V, S>
Source§fn default() -> OverlayMap<K, V, S>
fn default() -> OverlayMap<K, V, S>
Source§impl<K, V, S> Extend<(K, V)> for OverlayMap<K, V, S>
impl<K, V, S> Extend<(K, V)> for OverlayMap<K, V, S>
Source§fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I)
Inserts each (K, V)
pair into the map by pushing the value into the foreground layer.
This behaves the same as calling push for each element in the iterator. If a key already exists, the current foreground value is moved to the background, and the new value becomes the foreground. If the key is new, it is inserted.
This implementation does not return any count of replaced entries — if you need that,
use extend_count
instead.
§Example
use overlay_map::OverlayMap;
let mut map = OverlayMap::new();
map.extend([("x", 1), ("y", 2)]);
assert_eq!(map.fg(&"x"), Some(&1));
assert_eq!(map.fg(&"y"), Some(&2));
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)Source§impl<K, V, S> IntoIterator for OverlayMap<K, V, S>
impl<K, V, S> IntoIterator for OverlayMap<K, V, S>
Source§impl<K, V, S> PartialEq for OverlayMap<K, V, S>
impl<K, V, S> PartialEq for OverlayMap<K, V, S>
impl<K, V, S> Eq for OverlayMap<K, V, S>
impl<K, V, S> Sync for OverlayMap<K, V, S>
OverlayMap
is Sync
because all access to internal state is gated through &self
for read-only operations, and mutation requires exclusive access via &mut self
.
- The underlying
HashMap
is notSync
by default, but we do not expose any interior mutability or unsynchronized shared mutation. - All mutation methods (e.g.,
push
,pull
,swap
) require&mut self
. - Shared access via
&OverlayMap
only allows read-only operations likefg
,bg
,len
, andis_empty
, which do not mutate internal state. Overlay<T>
is also safe for concurrent read access and does not use interior mutability.
Auto Trait Implementations§
impl<K, V, S> Freeze for OverlayMap<K, V, S>where
S: Freeze,
impl<K, V, S> RefUnwindSafe for OverlayMap<K, V, S>
impl<K, V, S> Send for OverlayMap<K, V, S>
impl<K, V, S> Unpin for OverlayMap<K, V, S>
impl<K, V, S> UnwindSafe for OverlayMap<K, V, S>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.