diff --git a/src/dense.rs b/src/dense.rs index 42d3b93..dfdda65 100644 --- a/src/dense.rs +++ b/src/dense.rs @@ -252,7 +252,10 @@ impl DenseSlotMap { /// ``` #[inline(always)] pub fn insert(&mut self, value: V) -> K { - unsafe { self.try_insert_with_key::<_, Never>(move |_| Ok(value)).unwrap_unchecked_() } + unsafe { + self.try_insert_with_key::<_, Never>(move |_| Ok(value)) + .unwrap_unchecked_() + } } /// Inserts a value given by `f` into the slot map. The key where the @@ -277,7 +280,10 @@ impl DenseSlotMap { where F: FnOnce(K) -> V, { - unsafe { self.try_insert_with_key::<_, Never>(move |k| Ok(f(k))).unwrap_unchecked_() } + unsafe { + self.try_insert_with_key::<_, Never>(move |k| Ok(f(k))) + .unwrap_unchecked_() + } } /// Inserts a value given by `f` into the slot map. The key where the @@ -515,7 +521,10 @@ impl DenseSlotMap { /// ``` pub unsafe fn get_unchecked(&self, key: K) -> &V { debug_assert!(self.contains_key(key)); - let idx = self.slots.get_unchecked(key.data().idx as usize).idx_or_free; + let idx = self + .slots + .get_unchecked(key.data().idx as usize) + .idx_or_free; &self.values.get_unchecked(idx as usize) } @@ -565,7 +574,10 @@ impl DenseSlotMap { /// ``` pub unsafe fn get_unchecked_mut(&mut self, key: K) -> &mut V { debug_assert!(self.contains_key(key)); - let idx = self.slots.get_unchecked(key.data().idx as usize).idx_or_free; + let idx = self + .slots + .get_unchecked(key.data().idx as usize) + .idx_or_free; self.values.get_unchecked_mut(idx as usize) } @@ -785,6 +797,81 @@ impl DenseSlotMap { inner: self.iter_mut(), } } + + /// Returns the index that can be used to access the value associated to + /// this key in the [`Vec`] returned by [`into_dense()`]. This index is + /// only valid if no mutations occur to the slotmap between the index + /// being retrieved and the slotmap being converted to its dense form. + /// + /// # Examples + /// + /// ``` + /// # use slotmap::*; + /// let mut sm = DenseSlotMap::new(); + /// let keys = [ + /// sm.insert(1), + /// sm.insert(2), + /// sm.insert(3), + /// ]; + /// sm.values_mut().for_each(|n| { *n *= 3 }); + /// let indices: Vec<_> = + /// keys + /// .into_iter() + /// .map(|key| sm.get_dense_index(*key).unwrap()) + /// .collect(); + /// let dense = sm.into_dense(); + /// assert_eq!( + /// [3, 6, 9], + /// [ + /// dense[indices[0]], + /// dense[indices[1]], + /// dense[indices[2]], + /// ] + /// ); + /// ``` + pub fn get_dense_index(&self, key: K) -> Option { + let kd = key.data(); + self.slots + .get(kd.idx as usize) + .filter(|slot| slot.version == kd.version.get()) + .map(|slot| slot.idx_or_free as usize) + } + + /// Returns a dense [`Vec`] of the values in this [`DenseSlotMap`], + /// in an arbitrary order. Indices into this [`Vec`] can be + /// retrieved by calling [`get_dense_index()`] *without mutating + /// the slotmap between the index retrieval and the conversion to + /// dense [`Vec`]*. Mutating the slotmap before conversion + /// invalidates all retrieved indices. + /// + /// # Example + /// + /// ``` + /// # use slotmap::*; + /// let mut sm = DenseSlotMap::new(); + /// let keys = [ + /// sm.insert(4), + /// sm.insert(2), + /// sm.insert(5), + /// ]; + /// let indices: Vec<_> = + /// keys + /// .into_iter() + /// .map(|key| sm.get_dense_index(*key).unwrap()) + /// .collect(); + /// let dense = sm.into_dense(); + /// assert_eq!( + /// [4, 2, 5], + /// [ + /// dense[indices[0]], + /// dense[indices[1]], + /// dense[indices[2]], + /// ] + /// ); + /// ``` + pub fn into_dense(self) -> Vec { + self.values + } } impl Clone for DenseSlotMap @@ -1132,7 +1219,10 @@ mod serialize { } // Ensure the first slot exists and is empty for the sentinel. - if serde_slots.get(0).map_or(true, |slot| slot.version % 2 == 1) { + if serde_slots + .get(0) + .map_or(true, |slot| slot.version % 2 == 1) + { return Err(de::Error::custom(&"first slot not empty")); }