overlay-map 0.2.0

A two-layered map data structure for Rust that tracks current and previous values for each key โ€” with zero-clone, in-place state transitions.
Documentation
# overlay-map

**overlay-map** is a two-layered map data structure for Rust that tracks **current** and **previous** values for each key โ€” with zero-clone, in-place state transitions.

It provides `OverlayMap<K, V>`, a map where each value is an `Overlay<V>`: a compact two-slot container that allows pushing, swapping, and pulling values without cloning or heap allocation.

## ๐Ÿ“ฆ Features

- โœ… **In-place, zero-cost value updates**
- โœ… Foreground and background storage per key
- โœ… On `push`, the current foreground is moved to background
- โœ… No heap allocation or cloning for updates
- โœ… Conditional updates (`push_if`)
- โœ… Automatic removal when entries become empty
- โœ… `Overlay<T>` usable independently from the map

## ๐Ÿง  Core types

### `OverlayMap<K, V>`

A map-like wrapper for managing per-key two-layered state.

### `Overlay<T>`

A standalone container that tracks two versions of a value:
- `fg` โ†’ the current value
- `bg` โ†’ the previous value (optional)

Uses zero-copy, branchless slot flipping via raw memory and bitflags.

## ๐Ÿš€ Example: Revolving Door of Values

```rust
use overlay_map::Overlay;

fn main() {
    let mut door = Overlay::new_fg("Alice");
    println!("Present: {:?}, {:?}", door.fg(), door.bg());

    for name in ["Bob", "Carol", "Dave", "Eve"] {
        if let Some(evicted) = door.swap(name) {
            println!("{evicted} left");
        }

        println!("Present: {:?}, {:?}", door.bg(), door.fg());
    }

    while let Some(pulled) = door.pull() {
        println!("{pulled} left");
    }

    println!("Present: {:?}, {:?}", door.bg(), door.fg());
}
```

## ๐Ÿ”ฌ Internal Design

- `Overlay<T>` uses `[MaybeUninit<T>; 2]` with a compact bitflag for presence and slot state.
- No heap allocation, no `Option<T>`, no clone required.
- Operations like `push`, `pull`, `swap` are in-place and branch-minimal.
- Designed for **high-throughput**, **zero-cost** data flow and state management.

## ๐Ÿง  Why use this?

`overlay-map` is ideal for:

- Managing *current vs previous* state without full history
- Speculative updates, rollback systems, or caching layers
- Config overlays, merging, and snapshotting
- Avoiding unnecessary cloning, allocation, and indirection in hot code paths

## ๐Ÿงช Performance: `Overlay<T>` vs `Option<(T, Option<T>)>`

These benchmarks measure the performance of the `push` operation in both the
`Overlay<T>` and a conventional tuple-based implementation. Recorded on a
MacBook Air M4.

### ๐Ÿ“Š Overlay Implementation

![Overlay PDF](./assets/overlay_pdf.svg)
![Overlay Regression](./assets/overlay_regression.svg)

### ๐Ÿ“Š Tuple Implementation

![Tuple PDF](./assets/tuple_pdf.svg)
![Tuple Regression](./assets/tuple_regression.svg)

### ๐Ÿ“Š Interpretation

- **Overlay**:
  - Operates near L1 cache speeds (sub-100ps per op).
  - Compact, branchless bitfield logic leads to extremely low overhead.
- **Tuple**:
  - Slower and more predictable due to enum tagging and control-flow overhead.
  - Useful baseline, but significantly outperformed by `Overlay`.

> These graphs were generated using [Criterion.rs]https://bheisler.github.io/criterion.rs/book/ and represent measured runtime distribution and scaling with iteration count.

## ๐Ÿ“š Documentation

- [Docs.rs]https://docs.rs/overlay-map
- [Crates.io]https://crates.io/crates/overlay-map

## ๐Ÿ”’ License

MIT

## โœจ Contributing

Contributions, bug reports, and feature ideas welcome.