steel_core/entity/manager/
entries.rs1use rustc_hash::FxHashMap;
4
5use super::EntityEntry;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub(super) struct EntitySlot(usize);
10
11#[derive(Default)]
12pub(super) struct EntityEntries {
13 by_id: FxHashMap<i32, EntitySlot>,
14 slots: Vec<Option<EntityEntry>>,
15 free: Vec<EntitySlot>,
16}
17
18impl EntityEntries {
19 pub(super) fn slot(&self, id: i32) -> Option<EntitySlot> {
20 self.by_id.get(&id).copied()
21 }
22
23 pub(super) fn entry(&self, slot: EntitySlot) -> &EntityEntry {
24 match &self.slots[slot.0] {
25 Some(entry) => entry,
26 None => unreachable!("spatial index refers to a vacant entity slot"),
27 }
28 }
29
30 pub(super) fn entry_mut(&mut self, slot: EntitySlot) -> &mut EntityEntry {
31 match &mut self.slots[slot.0] {
32 Some(entry) => entry,
33 None => unreachable!("spatial index refers to a vacant entity slot"),
34 }
35 }
36
37 pub(super) fn get(&self, id: i32) -> Option<&EntityEntry> {
38 self.slot(id).map(|slot| self.entry(slot))
39 }
40
41 pub(super) fn get_mut(&mut self, id: i32) -> Option<&mut EntityEntry> {
42 let slot = self.slot(id)?;
43
44 Some(self.entry_mut(slot))
45 }
46
47 pub(super) fn contains_key(&self, id: i32) -> bool {
48 self.by_id.contains_key(&id)
49 }
50
51 pub(super) fn len(&self) -> usize {
52 self.by_id.len()
53 }
54
55 pub(super) fn values(&self) -> impl Iterator<Item = &EntityEntry> {
56 self.slots.iter().filter_map(Option::as_ref)
57 }
58
59 pub(super) fn insert(&mut self, id: i32, entry: EntityEntry) -> EntitySlot {
60 let slot = if let Some(slot) = self.free.pop() {
61 self.slots[slot.0] = Some(entry);
62 slot
63 } else {
64 let slot = EntitySlot(self.slots.len());
65 self.slots.push(Some(entry));
66 slot
67 };
68
69 assert!(self.by_id.insert(id, slot).is_none(), "duplicate entity ID");
70
71 slot
72 }
73
74 pub(super) fn remove(&mut self, id: i32) -> Option<(EntitySlot, EntityEntry)> {
75 let slot = self.by_id.remove(&id)?;
76
77 let Some(entry) = self.slots[slot.0].take() else {
78 unreachable!("entity ID refers to a vacant entity slot");
79 };
80
81 self.free.push(slot);
82
83 Some((slot, entry))
84 }
85}