overlay_map/
lib.rs

1//! A two-layered map structure where the foreground is mutable and the
2//! background is preserved.
3//!
4//! OverlayMap lets you insert values without cloning, while keeping a single
5//! layer of historical context. Each key has a current value (foreground) and
6//! may have a previous value (background), which is automatically managed
7//! during updates.
8//!
9//! ```rust
10//! use overlay_map::Overlay;
11//!
12//! let mut door = Overlay::new_fg("Alice");
13//! println!("Present: {:?}, {:?}", door.fg(), door.bg());
14//!
15//! for name in ["Bob", "Carol", "Dave", "Eve"] {
16//!     if let Some(evicted) = door.swap(name) {
17//!         println!("{evicted} left");
18//!     }
19//!     println!("Present: {:?}, {:?}", door.bg(), door.fg());
20//! }
21//!
22//! while let Some(pulled) = door.pull() {
23//!     println!("{pulled} left");
24//! }
25//!
26//! println!("Present: {:?}, {:?}", door.bg(), door.fg());
27//! ```
28
29use std::{
30    hash::{BuildHasher, Hash},
31    mem::MaybeUninit,
32};
33
34use hashbrown::{DefaultHashBuilder, HashMap, hash_map::RawEntryMut};
35
36/// A two-layered map where each key holds a current (foreground) and optional historical (background) value.
37///
38/// `OverlayMap` is a high-performance associative container designed for efficient, non-cloning updates
39/// and reversible state transitions. When inserting a new value for an existing key, the current
40/// foreground is automatically moved to the background. This allows you to update state while
41/// preserving a previous version — useful for rollback, previews, speculative updates, or undo systems.
42///
43/// All operations are zero-copy and allocation-free beyond what the internal map requires. Background
44/// values are stored in-place and never cloned or reallocated.
45///
46/// Internally, each key maps to an [`Overlay<V>`] that manages the foreground and background slots.
47/// The API provides full control over pushing, pulling, and swapping values, with minimal overhead.
48///
49/// # Features
50///
51/// - Efficient push/pull/swap operations
52/// - No cloning or heap allocation for values
53/// - Zero-cost foreground/background transitions
54/// - Map keys only retained when a value is present
55///
56/// # Example
57///
58/// ```
59/// use overlay_map::OverlayMap;
60///
61/// let mut map = OverlayMap::new();
62///
63/// // Insert a new value
64/// map.push("player", 1);
65///
66/// // Overwrite it — original goes to background
67/// map.push("player", 2);
68///
69/// assert_eq!(map.fg(&"player"), Some(&2));
70/// assert_eq!(map.bg(&"player"), Some(&1));
71///
72/// // Pull removes the current foreground and promotes background
73/// let pulled = map.pull(&"player");
74/// assert_eq!(pulled, Some(2));
75/// assert_eq!(map.fg(&"player"), Some(&1));
76///
77/// // Pull again — entry is now removed
78/// let pulled = map.pull(&"player");
79/// assert_eq!(pulled, Some(1));
80/// assert_eq!(map.fg(&"player"), None);
81/// ```
82#[derive(Debug, Default)]
83pub struct OverlayMap<K, V, S = DefaultHashBuilder>
84where
85    K: Eq + Hash,
86{
87    map: HashMap<K, Overlay<V>, S>,
88}
89
90/// `OverlayMap` is `Sync` because all access to internal state is gated through `&self`
91/// for read-only operations, and mutation requires exclusive access via `&mut self`.
92///
93/// - The underlying `HashMap` is not `Sync` by default, but we do not expose any interior
94///   mutability or unsynchronized shared mutation.
95/// - All mutation methods (e.g., `push`, `pull`, `swap`) require `&mut self`.
96/// - Shared access via `&OverlayMap` only allows read-only operations like `fg`, `bg`, `len`,
97///   and `is_empty`, which do not mutate internal state.
98/// - `Overlay<T>` is also safe for concurrent read access and does not use interior mutability.
99unsafe impl<K, V, S> Sync for OverlayMap<K, V, S>
100where
101    K: Eq + Hash + Sync,
102    S: Sync,
103{
104}
105
106impl<K, V> OverlayMap<K, V, DefaultHashBuilder>
107where
108    K: Eq + Hash,
109{
110    /// Creates a new, empty `OverlayMap` using the default hasher.
111    pub fn new() -> Self {
112        Self::with_hasher(DefaultHashBuilder::default())
113    }
114}
115
116impl<K, V, S> OverlayMap<K, V, S>
117where
118    K: Eq + Hash,
119    S: BuildHasher + Default,
120{
121    /// Creates an empty `OverlayMap` with the specified capacity and default hasher.
122    pub fn with_capacity(capacity: usize) -> Self {
123        Self::with_capacity_and_hasher(capacity, Default::default())
124    }
125
126    /// Creates an empty `OverlayMap` that will use the given hasher.
127    pub fn with_hasher(hasher: S) -> Self {
128        Self {
129            map: HashMap::with_hasher(hasher),
130        }
131    }
132
133    /// Creates an empty `OverlayMap` with the specified capacity and hasher.
134    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
135        Self {
136            map: HashMap::with_capacity_and_hasher(capacity, hasher),
137        }
138    }
139
140    /// Number of unique keys in the map.
141    pub fn len(&self) -> usize {
142        self.map.len()
143    }
144
145    /// Check if the map is empty.
146    pub fn is_empty(&self) -> bool {
147        self.map.is_empty()
148    }
149
150    /// Get an immutable reference to the value associated with the key.
151    ///
152    /// Returns `None` if the key was not found in the map.
153    #[inline]
154    pub fn fg(&self, key: &K) -> Option<&V> {
155        self.map.get(key).map(|entry| entry.fg_unchecked())
156    }
157
158    /// Get an immutable reference to the value associated with the key in the background layer.
159    ///
160    /// Returns `None` if the key was not found in the background layer.
161    #[inline]
162    pub fn bg(&self, key: &K) -> Option<&V> {
163        self.map.get(key).and_then(|entry| entry.bg())
164    }
165
166    /// Push a value into the foreground layer, preserving the previous value in
167    /// the background.
168    ///
169    /// If the key was already present, the current foreground is moved to the
170    /// background slot, and the new value becomes the new foreground. No
171    /// cloning occurs. The old background value is dropped if it was present.
172    ///
173    /// Returns `true` if there was already a foreground value (i.e. a
174    /// background now definitely exists).
175    #[inline]
176    pub fn push(&mut self, key: K, value: V) -> bool {
177        match self.map.raw_entry_mut().from_key(&key) {
178            RawEntryMut::Occupied(mut occupied) => {
179                occupied.get_mut().push(value);
180                true
181            }
182            RawEntryMut::Vacant(vacant) => {
183                vacant.insert(key, Overlay::new_fg(value));
184                false
185            }
186        }
187    }
188
189    /// Conditionally push a new value into the foreground based on the current
190    /// value.
191    ///
192    /// If the key exists, the current foreground value is passed to the
193    /// predicate. If the predicate returns `Some(new_val)`, the new value is
194    /// pushed and the old one is preserved in the background. If it returns
195    /// `None`, nothing is changed.
196    ///
197    /// Returns `true` if a new value was pushed.
198    pub fn push_if<F>(&mut self, key: &K, predicate: F) -> bool
199    where
200        F: FnOnce(&V) -> Option<V>,
201    {
202        let entry = match self.map.get_mut(key) {
203            Some(e) => e,
204            None => return false,
205        };
206
207        match predicate(entry.fg_unchecked()) {
208            Some(new) => {
209                entry.push(new);
210                true
211            }
212            None => false,
213        }
214    }
215
216    /// Pulls the foreground value for a key, promoting the background to foreground if present.
217    ///
218    /// This removes and returns the current foreground value for the given key. If a background
219    /// value exists, it is promoted to foreground. If the key has no background after the pull,
220    /// the key is removed from the map entirely.
221    ///
222    /// # Returns
223    ///
224    /// - `Some(value)` if the key existed and a foreground value was pulled.
225    /// - `None` if the key did not exist.
226    ///
227    /// # Invariants
228    ///
229    /// - After this operation, the key is only retained if a background value was available
230    ///   to promote.
231    /// - Keys in the map always have at least one value (foreground), unless removed by `pull`.
232    ///
233    /// # Example
234    ///
235    /// ```
236    /// use overlay_map::OverlayMap;
237    ///
238    /// let mut map = OverlayMap::<&str, i32>::new();
239    /// map.push("key", 1);
240    /// map.push("key", 2);
241    ///
242    /// assert_eq!(map.fg(&"key"), Some(&2));
243    /// assert_eq!(map.bg(&"key"), Some(&1));
244    ///
245    /// let pulled = map.pull(&"key");
246    /// assert_eq!(pulled, Some(2));
247    /// assert_eq!(map.fg(&"key"), Some(&1)); // background promoted
248    ///
249    /// let pulled = map.pull(&"key");
250    /// assert_eq!(pulled, Some(1));
251    /// assert_eq!(map.fg(&"key"), None); // entry removed
252    /// ```
253    #[inline]
254    pub fn pull(&mut self, key: &K) -> Option<V> {
255        match self.map.raw_entry_mut().from_key(key) {
256            RawEntryMut::Occupied(mut occupied) => {
257                let entry = occupied.get_mut();
258                let evicted = entry.pull_unchecked();
259                if entry.is_empty() {
260                    occupied.remove();
261                }
262                Some(evicted)
263            }
264            RawEntryMut::Vacant(_) => None,
265        }
266    }
267
268    /// Conditionally pulls the foreground value for a key, promoting the background if present.
269    ///
270    /// If the key exists and the provided predicate returns `true` for the current foreground,
271    /// this removes and returns the foreground value. The background (if any) is promoted to
272    /// foreground, and the key is removed from the map if no background remains.
273    ///
274    /// If the predicate returns `false` or the key does not exist, the map is left unchanged.
275    ///
276    /// # Returns
277    ///
278    /// - `Some(value)` if the predicate matched and the foreground was pulled.
279    /// - `None` if the key was not found or the predicate returned `false`.
280    ///
281    /// # Invariants
282    ///
283    /// - After this operation, the key is only retained if a background value was available
284    ///   to promote.
285    /// - Keys in the map always have at least one value (foreground), unless removed by `pull_if`.
286    ///
287    /// # Example
288    ///
289    /// ```
290    /// use overlay_map::OverlayMap;
291    ///
292    /// let mut map = OverlayMap::<&str, i32>::new();
293    /// map.push("key", 10);
294    /// map.push("key", 20);
295    ///
296    /// // Only pull if the foreground is 20
297    /// let pulled = map.pull_if(&"key", |v| *v == 20);
298    /// assert_eq!(pulled, Some(20));
299    /// assert_eq!(map.fg(&"key"), Some(&10));
300    ///
301    /// // Predicate does not match: nothing is pulled
302    /// let pulled = map.pull_if(&"key", |v| *v == 999);
303    /// assert_eq!(pulled, None);
304    /// assert_eq!(map.fg(&"key"), Some(&10));
305    ///
306    /// // Pull remaining value, removing the key
307    /// let pulled = map.pull_if(&"key", |_| true);
308    /// assert_eq!(pulled, Some(10));
309    /// assert_eq!(map.fg(&"key"), None);
310    /// ```
311    pub fn pull_if<F>(&mut self, key: &K, predicate: F) -> Option<V>
312    where
313        F: FnOnce(&V) -> bool,
314    {
315        match self.map.raw_entry_mut().from_key(key) {
316            RawEntryMut::Occupied(mut occupied) => {
317                let entry = occupied.get_mut();
318                if predicate(entry.fg_unchecked()) {
319                    let evicted = entry.pull_unchecked();
320                    if entry.is_empty() {
321                        occupied.remove();
322                    }
323                    Some(evicted)
324                } else {
325                    None
326                }
327            }
328            RawEntryMut::Vacant(_) => None,
329        }
330    }
331
332    /// Swap a value into the foreground layer, preserving the previous value in
333    /// the background, and returning the evicted background value if present.
334    ///
335    /// If the key was already present, the current foreground is moved to the
336    /// background slot, and the new value becomes the new foreground. No
337    /// cloning occurs. The old background value is returned if present.
338    #[inline]
339    pub fn swap(&mut self, key: K, value: V) -> Option<V> {
340        match self.map.raw_entry_mut().from_key(&key) {
341            RawEntryMut::Occupied(mut occupied) => occupied.get_mut().swap(value),
342            RawEntryMut::Vacant(vacant) => {
343                vacant.insert(key, Overlay::new_fg(value));
344                None
345            }
346        }
347    }
348
349    /// Conditionally swap a new value into the foreground based on the current
350    /// value.
351    ///
352    /// If the key exists, the current foreground value is passed to the
353    /// predicate. If the predicate returns `Some(new_val)`, the new value is
354    /// pushed and the old one is preserved in the background. If it returns
355    /// `None`, nothing is changed.
356    ///
357    /// The evicted background value is returned if present.
358    pub fn swap_if<F>(&mut self, key: &K, predicate: F) -> Option<V>
359    where
360        F: FnOnce(&V) -> Option<V>,
361    {
362        let entry = self.map.get_mut(key)?;
363        match predicate(entry.fg_unchecked()) {
364            Some(new) => entry.swap(new),
365            None => None,
366        }
367    }
368
369    /// Flips the foreground and background values for the given key, if present.
370    ///
371    /// This operation swaps the logical roles of the foreground and background values
372    /// for the specified key. If the key is present in the map, the values are flipped:
373    ///
374    /// - The background becomes the new foreground
375    /// - The foreground becomes the new background
376    ///
377    /// This does **not** move, clone, or reallocate any values — it is a zero-cost operation
378    /// that simply toggles the internal bit mask controlling foreground/background interpretation.
379    ///
380    /// If the key is not present in the map, or if it has no background value, the operation
381    /// has no effect.
382    ///
383    /// # Example
384    ///
385    /// ```
386    /// use overlay_map::OverlayMap;
387    ///
388    /// let mut map = OverlayMap::new();
389    /// map.push("slot", 1);
390    /// map.push("slot", 2); // now: fg = 2, bg = 1
391    ///
392    /// map.flip(&"slot");
393    ///
394    /// assert_eq!(map.fg(&"slot"), Some(&1));
395    /// assert_eq!(map.bg(&"slot"), Some(&2));
396    /// ```
397    pub fn flip(&mut self, key: &K) {
398        if let Some(entry) = self.map.get_mut(key) {
399            entry.flip();
400        }
401    }
402
403    /// Extends the map with a sequence of key-value pairs, counting foreground replacements.
404    ///
405    /// Each `(K, V)` pair is pushed into the foreground. If a key already exists,
406    /// the current foreground is moved to the background, and the new value becomes
407    /// the new foreground. If the key is new, it is inserted without affecting any background.
408    ///
409    /// This method returns the number of keys that were already present — i.e., how many
410    /// pushes replaced an existing foreground value.
411    ///
412    /// No cloning or heap allocation is performed beyond what's necessary for the `HashMap`.
413    ///
414    /// # Example
415    /// ```
416    /// use overlay_map::OverlayMap;
417    ///
418    /// let mut map = OverlayMap::new();
419    /// map.push("a", 1);
420    ///
421    /// let replaced = map.extend_count([("a", 2), ("b", 3)]);
422    /// assert_eq!(replaced, 1); // "a" was already present, "b" was new
423    ///
424    /// assert_eq!(map.fg(&"a"), Some(&2));
425    /// assert_eq!(map.bg(&"a"), Some(&1));
426    /// assert_eq!(map.fg(&"b"), Some(&3));
427    /// ```
428    pub fn extend_count<I>(&mut self, iter: I) -> usize
429    where
430        I: IntoIterator<Item = (K, V)>,
431    {
432        let mut replaced = 0;
433        for (key, val) in iter {
434            replaced += self.push(key, val) as usize;
435        }
436        replaced
437    }
438}
439
440impl<K, V, S> Clone for OverlayMap<K, V, S>
441where
442    K: Clone + Eq + Hash,
443    V: Clone,
444    S: Clone + BuildHasher,
445{
446    fn clone(&self) -> Self {
447        Self {
448            map: self.map.clone(),
449        }
450    }
451}
452
453impl<K, V, S> PartialEq for OverlayMap<K, V, S>
454where
455    K: Eq + Hash,
456    V: PartialEq,
457    S: BuildHasher,
458{
459    fn eq(&self, other: &Self) -> bool {
460        self.map == other.map
461    }
462}
463
464impl<K, V, S> Eq for OverlayMap<K, V, S>
465where
466    K: Eq + Hash,
467    V: Eq,
468    S: BuildHasher,
469{
470}
471
472impl<K, V, S> Extend<(K, V)> for OverlayMap<K, V, S>
473where
474    K: Eq + Hash,
475    S: BuildHasher + Default,
476{
477    /// Inserts each `(K, V)` pair into the map by pushing the value into the foreground layer.
478    ///
479    /// This behaves the same as calling [`push`] for each element in the iterator. If a key
480    /// already exists, the current foreground value is moved to the background, and the
481    /// new value becomes the foreground. If the key is new, it is inserted.
482    ///
483    /// This implementation does **not** return any count of replaced entries — if you need that,
484    /// use [`extend_count`](Self::extend_count) instead.
485    ///
486    /// # Example
487    /// ```
488    /// use overlay_map::OverlayMap;
489    ///
490    /// let mut map = OverlayMap::new();
491    /// map.extend([("x", 1), ("y", 2)]);
492    ///
493    /// assert_eq!(map.fg(&"x"), Some(&1));
494    /// assert_eq!(map.fg(&"y"), Some(&2));
495    /// ```
496    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
497        for (k, v) in iter {
498            self.push(k, v);
499        }
500    }
501}
502
503impl<K, V, S> IntoIterator for OverlayMap<K, V, S>
504where
505    K: Eq + Hash,
506    S: BuildHasher,
507{
508    type Item = (K, Overlay<V>);
509    type IntoIter = hashbrown::hash_map::IntoIter<K, Overlay<V>>;
510
511    fn into_iter(self) -> Self::IntoIter {
512        self.map.into_iter()
513    }
514}
515
516const SLOT0_PRESENT: u8 = 1 << 0;
517const SLOT1_PRESENT: u8 = 1 << 1;
518const SLOT_MASK: u8 = SLOT0_PRESENT | SLOT1_PRESENT;
519const FG_SLOT: u8 = 1 << 2;
520
521/// A two-layer value container used by [`OverlayMap`] to manage current and historical values.
522///
523/// `Overlay<T>` stores up to two values:
524///
525/// - A **foreground** value representing the current state.
526/// - An optional **background** value representing the previous state.
527///
528/// When used through [`OverlayMap`], each key maps to an `Overlay<T>` to track updates
529/// without requiring clones or reallocations. You can also use `Overlay<T>` standalone
530/// to manage two-layer state transitions for any value type.
531///
532/// Values are moved, never cloned. All operations (push, pull, swap) are zero-cost and
533/// memory-efficient.
534///
535/// # Use Cases
536///
537/// - Managing current and previous state in UI or simulation logic
538/// - Efficient delta tracking for configs, game state, etc.
539/// - Avoiding `Option<(T, T)>` or custom wrappers with cloning overhead
540///
541/// # Examples
542///
543/// ```
544/// use overlay_map::Overlay;
545///
546/// let mut entry = Overlay::new_fg("current");
547/// entry.push("next"); // moves "current" into background
548///
549/// assert_eq!(entry.fg(), Some(&"next"));
550/// assert_eq!(entry.bg(), Some(&"current"));
551///
552/// let pulled = entry.pull();
553/// assert_eq!(pulled, Some("next"));
554/// assert_eq!(entry.fg(), Some(&"current"));
555/// ```
556#[derive(Debug)]
557pub struct Overlay<T> {
558    bits: u8,
559    slots: [MaybeUninit<T>; 2],
560}
561
562impl<T> Overlay<T> {
563    /// Creates a new `Overlay` with no values.
564    ///
565    /// ```
566    /// use overlay_map::Overlay;
567    ///
568    /// let entry: Overlay<&str> = Overlay::new_empty();
569    /// assert!(entry.is_empty());
570    /// assert_eq!(entry.fg(), None);
571    /// assert_eq!(entry.bg(), None);
572    /// ```
573    pub fn new_empty() -> Self {
574        Self {
575            bits: 0,
576            slots: [MaybeUninit::uninit(), MaybeUninit::uninit()],
577        }
578    }
579
580    /// Creates a new `Overlay` with a foreground value and no background.
581    ///
582    /// ```
583    /// use overlay_map::Overlay;
584    ///
585    /// let entry = Overlay::new_fg("fg");
586    /// assert_eq!(entry.fg(), Some(&"fg"));
587    /// assert_eq!(entry.bg(), None);
588    /// ```
589    pub fn new_fg(val: T) -> Self {
590        Self {
591            bits: SLOT0_PRESENT,
592            slots: [MaybeUninit::new(val), MaybeUninit::uninit()],
593        }
594    }
595
596    /// Creates a new `Overlay` with both foreground and background values.
597    ///
598    /// ```
599    /// use overlay_map::Overlay;
600    ///
601    /// let entry = Overlay::new_both("fg", "bg");
602    /// assert_eq!(entry.fg(), Some(&"fg"));
603    /// assert_eq!(entry.bg(), Some(&"bg"));
604    /// ```
605    pub fn new_both(fg: T, bg: T) -> Self {
606        Self {
607            bits: SLOT0_PRESENT | SLOT1_PRESENT,
608            slots: [MaybeUninit::new(fg), MaybeUninit::new(bg)],
609        }
610    }
611
612    /// Returns a reference to the current foreground value, if present.
613    ///
614    /// This returns `Some(&T)` only if the foreground slot contains a value.
615    /// If the slot is logically empty, returns `None`. This is a safe version that
616    /// checks the presence bits before accessing memory.
617    ///
618    /// # Safety
619    /// This function is fully safe and performs a presence check before dereferencing.
620    ///
621    /// # Returns
622    /// - `Some(&T)` if the foreground slot is initialized
623    /// - `None` if the foreground slot is uninitialized
624    ///
625    /// ```
626    /// use overlay_map::OverlayMap;
627    ///
628    /// let mut map = OverlayMap::new();
629    /// map.push("x", 10);
630    /// map.push("x", 20);
631    /// assert_eq!(map.fg(&"x"), Some(&20));
632    /// assert_eq!(map.bg(&"x"), Some(&10));
633    /// ```
634    #[inline]
635    pub fn fg(&self) -> Option<&T> {
636        let idx = self.fg_index();
637        if self.is_slot_present(idx) {
638            Some(unsafe { self.slots[idx].assume_init_ref() })
639        } else {
640            None
641        }
642    }
643
644    /// Returns a reference to the foreground value **without checking** if it is present.
645    ///
646    /// # Safety
647    /// This function **assumes** the foreground slot is initialized. Calling this when
648    /// the slot is uninitialized (i.e. after a `pull()` without a background, or
649    /// after constructing an empty `Overlay`) results in **undefined behavior**.
650    ///
651    /// Use [`fg`](Self::fg) if you are not certain the slot is populated.
652    ///
653    /// ```
654    /// use overlay_map::Overlay;
655    ///
656    /// let entry = Overlay::new_both("fg", "bg");
657    /// assert_eq!(entry.fg_unchecked(), &"fg");
658    /// assert_eq!(entry.bg_unchecked(), &"bg");
659    /// ```
660    #[inline]
661    pub fn fg_unchecked(&self) -> &T {
662        let idx = self.fg_index();
663        unsafe { self.slots[idx].assume_init_ref() }
664    }
665
666    /// Returns a reference to the background value, if present.
667    ///
668    /// Returns `Some(&T)` only if the background slot is initialized.
669    ///
670    /// ```
671    /// use overlay_map::OverlayMap;
672    ///
673    /// let mut map = OverlayMap::new();
674    /// map.push("x", 10);
675    /// map.push("x", 20);
676    /// assert_eq!(map.fg(&"x"), Some(&20));
677    /// assert_eq!(map.bg(&"x"), Some(&10));
678    /// ```
679    #[inline]
680    pub fn bg(&self) -> Option<&T> {
681        let idx = self.bg_index();
682        if self.is_slot_present(idx) {
683            Some(unsafe { self.slots[idx].assume_init_ref() })
684        } else {
685            None
686        }
687    }
688
689    /// Returns a reference to the background value **without checking** if it is present.
690    ///
691    /// # Safety
692    /// This assumes the background slot is initialized. Calling this when it is not
693    /// will cause **undefined behavior**.
694    ///
695    /// Prefer [`bg`](Self::bg) if you're unsure whether the background is set.
696    ///
697    /// ```
698    /// use overlay_map::Overlay;
699    ///
700    /// let entry = Overlay::new_both("fg", "bg");
701    /// assert_eq!(entry.fg_unchecked(), &"fg");
702    /// assert_eq!(entry.bg_unchecked(), &"bg");
703    /// ```
704    #[inline]
705    pub fn bg_unchecked(&self) -> &T {
706        let idx = self.bg_index();
707        unsafe { self.slots[idx].assume_init_ref() }
708    }
709
710    /// Returns `true` if both slots are empty.
711    ///
712    /// This is used to determine whether the entry contains any values
713    /// at all. It does not consider which slot is foreground or background.
714    ///
715    /// ```
716    /// use overlay_map::Overlay;
717    ///
718    /// let mut entry = Overlay::new_fg("fg");
719    /// assert!(!entry.is_empty());
720    /// entry.pull();
721    /// assert!(entry.is_empty());
722    /// ```
723    #[inline]
724    pub fn is_empty(&self) -> bool {
725        (self.bits & SLOT_MASK) == 0
726    }
727
728    /// Returns `true` if both foreground and background values are currently present.
729    ///
730    /// This is useful for determining whether [`clear_unchecked`](Self::clear_unchecked)
731    /// is safe to call.
732    ///
733    /// # Example
734    /// ```
735    /// use overlay_map::Overlay;
736    ///
737    /// let mut entry = Overlay::new_both("a", "b");
738    /// assert!(entry.is_full());
739    ///
740    /// entry.pull();
741    /// assert!(!entry.is_full()); // background promoted, only one value remains
742    /// ```
743    #[inline]
744    pub fn is_full(&self) -> bool {
745        (self.bits & SLOT_MASK) == SLOT_MASK
746    }
747
748    /// Clears the overlay, dropping any foreground and background values.
749    ///
750    /// This is the most efficient way to reset the overlay to an empty state. It
751    /// avoids value movement or promotion and directly drops the contents of both
752    /// slots (if present). After calling `clear`, the overlay will report as empty,
753    /// and both `fg()` and `bg()` will return `None`.
754    ///
755    /// # Example
756    /// ```
757    /// use overlay_map::Overlay;
758    ///
759    /// let mut entry = Overlay::new_both("a", "b");
760    /// assert_eq!(entry.fg(), Some(&"a"));
761    /// assert_eq!(entry.bg(), Some(&"b"));
762    ///
763    /// entry.clear();
764    ///
765    /// assert_eq!(entry.fg(), None);
766    /// assert_eq!(entry.bg(), None);
767    /// assert!(entry.is_empty());
768    /// ```
769    #[inline]
770    pub fn clear(&mut self) {
771        if (self.bits & SLOT0_PRESENT) != 0 {
772            unsafe { self.slots[0].assume_init_drop() };
773        }
774        if (self.bits & SLOT1_PRESENT) != 0 {
775            unsafe { self.slots[1].assume_init_drop() };
776        }
777        self.bits = 0;
778    }
779
780    /// Clears the overlay without checking which slots are present.
781    ///
782    /// This is an **unsafe**, ultra-fast variant of [`Overlay::clear`] that skips
783    /// all internal presence checks. It will **unconditionally drop** both slots,
784    /// regardless of whether they are actually initialized.
785    ///
786    /// # Safety
787    ///
788    /// You must guarantee that both the **foreground** and **background** values
789    /// are currently present in the overlay. Calling this when either layer is
790    /// missing will result in **undefined behavior**, such as memory corruption
791    /// or double-drop.
792    ///
793    /// This is intended for use in performance-critical contexts where you already
794    /// know the exact slot state — for example, if you've just cloned from a known
795    /// full overlay, or you're clearing a batch of overlays all known to be full.
796    ///
797    /// For a safe version, use [`clear`](Self::clear).
798    ///
799    /// # Example
800    /// ```
801    /// use overlay_map::Overlay;
802    ///
803    /// let mut entry = Overlay::new_both("a", "b");
804    /// entry.clear_unchecked(); // caller guarantees both slots are present
805    ///
806    /// assert!(entry.is_empty());
807    /// ```
808    ///
809    /// # See Also
810    /// - [`Overlay::clear`] — safe version with slot checks
811    /// - [`Overlay::is_empty`] — to check for emptiness before clearing
812    #[inline]
813    pub fn clear_unchecked(&mut self) {
814        unsafe {
815            self.slots[0].assume_init_drop();
816            self.slots[1].assume_init_drop();
817        }
818        self.bits = 0;
819    }
820
821    /// Push a value into the foreground layer, preserving the previous foreground in the background.
822    ///
823    /// If the foreground slot already contains a value, it is moved into the background slot.
824    /// The new value is then written into the foreground slot. Any previous background value
825    /// will be dropped to make room—no cloning is performed at any point.
826    ///
827    /// This operation is always safe, even if the entry is empty. If no foreground is currently
828    /// present, the value will simply be inserted.
829    ///
830    /// # Example
831    /// ```
832    /// use overlay_map::Overlay;
833    ///
834    /// let mut entry = Overlay::new_fg("a");
835    /// entry.push("b");
836    ///
837    /// assert_eq!(entry.fg(), Some(&"b"));
838    /// assert_eq!(entry.bg(), Some(&"a"));
839    /// ```
840    #[inline]
841    pub fn push(&mut self, val: T) {
842        self.push_fg_to_bg();
843        let idx = self.fg_index();
844        self.slots[idx] = MaybeUninit::new(val);
845        self.bits |= 1 << idx;
846    }
847
848    /// Safely pull the current foreground value out, promoting the background to foreground if present.
849    ///
850    /// If the foreground value is present, it is removed and returned. The background (if any) is
851    /// promoted to the foreground. If neither value remains, the entry becomes empty.
852    ///
853    /// Returns `None` if the foreground was not present.
854    ///
855    /// # Example
856    /// ```
857    /// use overlay_map::Overlay;
858    ///
859    /// let mut entry = Overlay::new_both("a", "b");
860    /// let pulled = entry.pull();
861    ///
862    /// assert_eq!(pulled, Some("a"));
863    /// assert_eq!(entry.fg(), Some(&"b")); // background promoted
864    /// ```
865    #[inline]
866    pub fn pull(&mut self) -> Option<T> {
867        let fgi = self.fg_index();
868        if !self.is_slot_present(fgi) {
869            return None;
870        }
871
872        let evicted = unsafe { self.slots[fgi].assume_init_read() };
873        self.bits &= !(1 << fgi);
874        self.flip_unchecked();
875        Some(evicted)
876    }
877
878    /// Pull the current foreground value without checking if it is present.
879    ///
880    /// # Safety
881    /// The caller must ensure the foreground slot is present. If it is not, this will result
882    /// in undefined behavior.
883    ///
884    /// See [`Self::pull`] for a safe alternative.
885    ///
886    /// ```
887    /// use overlay_map::Overlay;
888    ///
889    /// let mut entry = Overlay::new_both("fg", "bg");
890    /// let pulled = entry.pull_unchecked();
891    /// assert_eq!(pulled, "fg");
892    /// assert_eq!(entry.fg(), Some(&"bg"));
893    /// ```
894    #[inline]
895    pub fn pull_unchecked(&mut self) -> T {
896        let fgi = self.fg_index();
897        let evicted = unsafe { self.slots[fgi].assume_init_read() };
898        self.bits &= !(1 << fgi);
899        self.flip_unchecked();
900        evicted
901    }
902
903    /// Swap in a new foreground value, returning the old background if present.
904    ///
905    /// If a background value exists, it is evicted and returned. The new value is written into
906    /// the background slot, which is then promoted to become the new foreground. The current
907    /// foreground is preserved in-place.
908    ///
909    /// If no background was present, this behaves like a standard push operation,
910    /// and `None` is returned.
911    ///
912    /// # Example
913    /// ```
914    /// use overlay_map::Overlay;
915    ///
916    /// let mut entry = Overlay::new_both("a", "b");
917    /// let evicted = entry.swap("c");
918    ///
919    /// assert_eq!(evicted, Some("b"));
920    /// assert_eq!(entry.fg(), Some(&"c"));
921    /// assert_eq!(entry.bg(), Some(&"a"));
922    /// ```
923    #[inline]
924    pub fn swap(&mut self, val: T) -> Option<T> {
925        let bgi = self.bg_index();
926        if self.is_slot_present(bgi) {
927            let evicted = unsafe { self.slots[bgi].assume_init_read() };
928            self.slots[bgi] = MaybeUninit::new(val);
929            self.flip_unchecked();
930            Some(evicted)
931        } else {
932            self.push(val);
933            None
934        }
935    }
936
937    /// Get an iterator over the foreground and background values.
938    ///
939    /// ```
940    /// use overlay_map::Overlay;
941    ///
942    /// let entry = Overlay::new_both("fg", "bg");
943    /// let values: Vec<_> = entry.iter().cloned().collect();
944    /// assert_eq!(values, vec!["fg", "bg"]);
945    /// ```
946    pub fn iter(&self) -> impl Iterator<Item = &T> {
947        self.fg().into_iter().chain(self.bg())
948    }
949
950    /// Flips the foreground and background layers, if both are present.
951    ///
952    /// This operation swaps the logical roles of the two slots:
953    ///
954    /// - The foreground becomes the background
955    /// - The background becomes the foreground
956    ///
957    /// If only one value is present, the overlay remains unchanged to preserve
958    /// the guarantee that a foreground value is always present when the overlay is in use.
959    ///
960    /// This is a zero-cost, branchless operation — no memory is moved, cloned, or reallocated.
961    /// Internally, it simply toggles a bit flag **only if** both slots are occupied.
962    ///
963    /// # Example
964    /// ```
965    /// use overlay_map::Overlay;
966    ///
967    /// let mut entry = Overlay::new_both("a", "b");
968    /// assert_eq!(entry.fg(), Some(&"a"));
969    /// assert_eq!(entry.bg(), Some(&"b"));
970    ///
971    /// entry.flip();
972    ///
973    /// assert_eq!(entry.fg(), Some(&"b"));
974    /// assert_eq!(entry.bg(), Some(&"a"));
975    ///
976    /// // Flip has no effect when only one value is present
977    /// let mut single = Overlay::new_fg("only");
978    /// single.flip();
979    /// assert_eq!(single.fg(), Some(&"only"));
980    /// assert_eq!(single.bg(), None);
981    /// ```
982    #[inline]
983    pub fn flip(&mut self) {
984        let mask = ((self.bits & SLOT_MASK) >> 1) & 1;
985        self.bits ^= mask << 2;
986    }
987
988    #[inline]
989    fn flip_unchecked(&mut self) {
990        self.bits ^= FG_SLOT;
991    }
992
993    #[inline]
994    fn fg_index(&self) -> usize {
995        ((self.bits & FG_SLOT) >> 2) as usize
996    }
997
998    #[inline]
999    fn bg_index(&self) -> usize {
1000        self.fg_index() ^ 1
1001    }
1002
1003    #[inline]
1004    fn is_slot_present(&self, idx: usize) -> bool {
1005        (self.bits & (1 << idx)) != 0
1006    }
1007
1008    /// Moves the current foreground value to the background slot, dropping any
1009    /// previous background.
1010    ///
1011    /// This operation updates only internal bits and memory slots. The value
1012    /// itself is not cloned or moved in memory. If a background value already
1013    /// exists, it is dropped before being replaced.
1014    #[inline]
1015    fn push_fg_to_bg(&mut self) {
1016        let bgi = self.bg_index();
1017        if self.is_slot_present(bgi) {
1018            unsafe {
1019                self.slots[bgi].assume_init_drop();
1020            }
1021        }
1022        self.flip_unchecked();
1023    }
1024}
1025
1026impl<T> Default for Overlay<T> {
1027    fn default() -> Self {
1028        Self::new_empty()
1029    }
1030}
1031
1032impl<T> From<T> for Overlay<T> {
1033    fn from(value: T) -> Self {
1034        Self::new_fg(value)
1035    }
1036}
1037
1038impl<T: Clone> Clone for Overlay<T> {
1039    fn clone(&self) -> Self {
1040        let mut clone = Self::new_empty();
1041        clone.bits = self.bits;
1042
1043        if self.is_slot_present(0) {
1044            clone.slots[0] = MaybeUninit::new(unsafe { self.slots[0].assume_init_ref().clone() });
1045        }
1046
1047        if self.is_slot_present(1) {
1048            clone.slots[1] = MaybeUninit::new(unsafe { self.slots[1].assume_init_ref().clone() });
1049        }
1050
1051        clone
1052    }
1053}
1054
1055impl<T: PartialEq> PartialEq for Overlay<T> {
1056    fn eq(&self, other: &Self) -> bool {
1057        if (self.bits & SLOT_MASK) != (other.bits & SLOT_MASK) {
1058            return false;
1059        }
1060        self.fg() == other.fg() && self.bg() == other.bg()
1061    }
1062}
1063
1064impl<T: Eq> Eq for Overlay<T> {}
1065
1066impl<V> Drop for Overlay<V> {
1067    fn drop(&mut self) {
1068        if (self.bits & SLOT0_PRESENT) != 0 {
1069            unsafe { self.slots[0].assume_init_drop() };
1070        }
1071
1072        if (self.bits & SLOT1_PRESENT) != 0 {
1073            unsafe { self.slots[1].assume_init_drop() };
1074        }
1075    }
1076}
1077
1078pub struct OverlayIntoIter<T> {
1079    overlay: Overlay<T>,
1080}
1081
1082impl<T> Iterator for OverlayIntoIter<T> {
1083    type Item = T;
1084
1085    fn next(&mut self) -> Option<Self::Item> {
1086        self.overlay.pull()
1087    }
1088}
1089
1090impl<T> IntoIterator for Overlay<T> {
1091    type Item = T;
1092    type IntoIter = OverlayIntoIter<T>;
1093
1094    /// Creates an iterator over the values in the overlay.
1095    ///
1096    /// ```
1097    /// use overlay_map::Overlay;
1098    ///
1099    /// let entry = Overlay::new_both("fg", "bg");
1100    /// let values: Vec<_> = entry.into_iter().collect();
1101    /// assert_eq!(values, vec!["fg", "bg"]);
1102    /// ```
1103    fn into_iter(self) -> Self::IntoIter {
1104        OverlayIntoIter { overlay: self }
1105    }
1106}
1107
1108#[cfg(test)]
1109mod tests {
1110    use super::*;
1111
1112    #[test]
1113    fn integration_push_pull_cycle() {
1114        let mut map = OverlayMap::<&str, i32>::new();
1115
1116        map.push("x", 1);
1117        map.push("x", 2);
1118        map.push("x", 3);
1119
1120        assert_eq!(map.fg(&"x"), Some(&3));
1121        assert_eq!(map.bg(&"x"), Some(&2));
1122
1123        let pulled = map.pull(&"x");
1124        assert_eq!(pulled, Some(3));
1125        assert_eq!(map.fg(&"x"), Some(&2));
1126
1127        let pulled = map.pull(&"x");
1128        assert_eq!(pulled, Some(2));
1129        assert_eq!(map.fg(&"x"), None);
1130        assert!(map.is_empty());
1131    }
1132
1133    #[test]
1134    fn extend_count_overlapping_and_new() {
1135        let mut map = OverlayMap::<&str, i32>::new();
1136        map.push("a", 10);
1137        map.push("b", 20);
1138
1139        let replaced = map.extend_count([("a", 100), ("c", 300), ("b", 200)]);
1140        assert_eq!(replaced, 2); // a and b existed
1141
1142        assert_eq!(map.fg(&"a"), Some(&100));
1143        assert_eq!(map.bg(&"a"), Some(&10));
1144
1145        assert_eq!(map.fg(&"b"), Some(&200));
1146        assert_eq!(map.bg(&"b"), Some(&20));
1147
1148        assert_eq!(map.fg(&"c"), Some(&300));
1149        assert_eq!(map.bg(&"c"), None);
1150    }
1151
1152    #[test]
1153    fn push_if_and_swap_if_logic() {
1154        let mut map = OverlayMap::<&str, i32>::new();
1155        map.push("key", 1);
1156
1157        let pushed = map.push_if(&"key", |v| if *v < 5 { Some(*v + 10) } else { None });
1158        assert!(pushed);
1159        assert_eq!(map.fg(&"key"), Some(&11));
1160        assert_eq!(map.bg(&"key"), Some(&1));
1161
1162        let evicted = map.swap_if(&"key", |v| if *v == 11 { Some(42) } else { None });
1163        assert_eq!(evicted, Some(1));
1164        assert_eq!(map.fg(&"key"), Some(&42));
1165        assert_eq!(map.bg(&"key"), Some(&11));
1166    }
1167}