From f4cdcad75e339106d866cf0ce9298faab36a3205 Mon Sep 17 00:00:00 2001 From: Klim Tsoutsman Date: Wed, 17 Jun 2026 10:10:59 +0200 Subject: [PATCH] Add `map` to `SlotMap` Similar to #133, but now the `map` function takes `self` i.e. ``` pub fn map(self, mut f: F) -> SlotMap where F: FnMut(K, V) -> U ``` Signed-off-by: Klim Tsoutsman --- src/basic.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/basic.rs b/src/basic.rs index 81f77e6..f13a9ac 100644 --- a/src/basic.rs +++ b/src/basic.rs @@ -64,6 +64,34 @@ impl Slot { } } } + + fn map(self, key_idx: u32, mut f: F) -> Slot + where + K: Key, + F: FnMut(K, T) -> U, + { + let mut this = ManuallyDrop::new(self); + let version = this.version; + + if this.occupied() { + let key = KeyData::new(key_idx, version).into(); + let value = unsafe { ManuallyDrop::take(&mut this.u.value) }; + + Slot { + u: SlotUnion { + value: ManuallyDrop::new(f(key, value)), + }, + version, + } + } else { + let next_free = unsafe { this.u.next_free }; + + Slot { + u: SlotUnion { next_free }, + version, + } + } + } } impl Drop for Slot { @@ -1006,6 +1034,38 @@ impl SlotMap { inner: self.iter_mut(), } } + + /// Returns a new slotmap preserving the keys, but mapping the values with `f`. + /// + /// # Examples + /// + /// ``` + /// # use slotmap::*; + /// let mut sm = SlotMap::new(); + /// let k1 = sm.insert(1); + /// let k2 = sm.insert(2); + /// + /// let sm = sm.map(|_k, v| v.to_string()); + /// assert_eq!(sm[k1], "1"); + /// assert_eq!(sm[k2], "2"); + /// ``` + pub fn map(self, mut f: F) -> SlotMap + where + F: FnMut(K, V) -> U, + { + let mut new_slots = Vec::with_capacity(self.slots.capacity()); + + for (idx, slot) in self.slots.into_iter().enumerate() { + new_slots.push(slot.map(idx as u32, &mut f)); + } + + SlotMap { + slots: new_slots, + free_head: self.free_head, + num_elems: self.num_elems, + _k: PhantomData, + } + } } impl Clone for SlotMap