//! Densely numbered entity references as set keys. use crate::keys::Keys; use crate::EntityRef; use alloc::vec::Vec; use core::marker::PhantomData; /// A set of `K` for densely indexed entity references. /// /// The `EntitySet` data structure uses the dense index space to implement a set with a bitvector. /// Like `SecondaryMap`, an `EntitySet` is used to associate secondary information with entities. #[derive(Debug, Clone)] pub struct EntitySet where K: EntityRef, { elems: Vec, len: usize, unused: PhantomData, } /// Shared `EntitySet` implementation for all value types. impl EntitySet where K: EntityRef, { /// Create a new empty set. pub fn new() -> Self { Self { elems: Vec::new(), len: 0, unused: PhantomData, } } /// Creates a new empty set with the specified capacity. pub fn with_capacity(capacity: usize) -> Self { Self { elems: Vec::with_capacity((capacity + 7) / 8), ..Self::new() } } /// Get the element at `k` if it exists. pub fn contains(&self, k: K) -> bool { let index = k.index(); if index < self.len { (self.elems[index / 8] & (1 << (index % 8))) != 0 } else { false } } /// Is this set completely empty? pub fn is_empty(&self) -> bool { if self.len != 0 { false } else { self.elems.iter().all(|&e| e == 0) } } /// Returns the cardinality of the set. More precisely, it returns the number of calls to /// `insert` with different key values, that have happened since the the set was most recently /// `clear`ed or created with `new`. pub fn cardinality(&self) -> usize { let mut n: usize = 0; for byte_ix in 0..self.len / 8 { n += self.elems[byte_ix].count_ones() as usize; } for bit_ix in (self.len / 8) * 8..self.len { if (self.elems[bit_ix / 8] & (1 << (bit_ix % 8))) != 0 { n += 1; } } n } /// Remove all entries from this set. pub fn clear(&mut self) { self.len = 0; self.elems.clear() } /// Iterate over all the keys in this set. pub fn keys(&self) -> Keys { Keys::with_len(self.len) } /// Resize the set to have `n` entries by adding default entries as needed. pub fn resize(&mut self, n: usize) { self.elems.resize((n + 7) / 8, 0); self.len = n } /// Insert the element at `k`. pub fn insert(&mut self, k: K) -> bool { let index = k.index(); if index >= self.len { self.resize(index + 1) } let result = !self.contains(k); self.elems[index / 8] |= 1 << (index % 8); result } /// Removes and returns the entity from the set if it exists. pub fn pop(&mut self) -> Option { if self.len == 0 { return None; } // Clear the last known entity in the list. let last_index = self.len - 1; self.elems[last_index / 8] &= !(1 << (last_index % 8)); // Set the length to the next last stored entity or zero if we pop'ed // the last entity. self.len = self .elems .iter() .enumerate() .rev() .find(|(_, &byte)| byte != 0) // Map `i` from byte index to bit level index. // `(i + 1) * 8` = Last bit in byte. // `last - byte.leading_zeros()` = last set bit in byte. // `as usize` won't ever truncate as the potential range is `0..=8`. .map_or(0, |(i, byte)| ((i + 1) * 8) - byte.leading_zeros() as usize); Some(K::new(last_index)) } } #[cfg(test)] mod tests { use super::*; use core::u32; // `EntityRef` impl for testing. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] struct E(u32); impl EntityRef for E { fn new(i: usize) -> Self { E(i as u32) } fn index(self) -> usize { self.0 as usize } } #[test] fn basic() { let r0 = E(0); let r1 = E(1); let r2 = E(2); let mut m = EntitySet::new(); let v: Vec = m.keys().collect(); assert_eq!(v, []); assert!(m.is_empty()); m.insert(r2); m.insert(r1); assert!(!m.contains(r0)); assert!(m.contains(r1)); assert!(m.contains(r2)); assert!(!m.contains(E(3))); assert!(!m.is_empty()); let v: Vec = m.keys().collect(); assert_eq!(v, [r0, r1, r2]); m.resize(20); assert!(!m.contains(E(3))); assert!(!m.contains(E(4))); assert!(!m.contains(E(8))); assert!(!m.contains(E(15))); assert!(!m.contains(E(19))); m.insert(E(8)); m.insert(E(15)); assert!(!m.contains(E(3))); assert!(!m.contains(E(4))); assert!(m.contains(E(8))); assert!(!m.contains(E(9))); assert!(!m.contains(E(14))); assert!(m.contains(E(15))); assert!(!m.contains(E(16))); assert!(!m.contains(E(19))); assert!(!m.contains(E(20))); assert!(!m.contains(E(u32::MAX))); m.clear(); assert!(m.is_empty()); } #[test] fn pop_ordered() { let r0 = E(0); let r1 = E(1); let r2 = E(2); let mut m = EntitySet::new(); m.insert(r0); m.insert(r1); m.insert(r2); assert_eq!(r2, m.pop().unwrap()); assert_eq!(r1, m.pop().unwrap()); assert_eq!(r0, m.pop().unwrap()); assert!(m.pop().is_none()); assert!(m.pop().is_none()); } #[test] fn pop_unordered() { let mut blocks = [ E(0), E(1), E(6), E(7), E(5), E(9), E(10), E(2), E(3), E(11), E(12), ]; let mut m = EntitySet::new(); for &block in &blocks { m.insert(block); } assert_eq!(m.len, 13); blocks.sort(); for &block in blocks.iter().rev() { assert_eq!(block, m.pop().unwrap()); } assert!(m.is_empty()); } }