summaryrefslogtreecommitdiff
path: root/src/sparse_set.rs
diff options
context:
space:
mode:
authorDominik Kaiser2026-06-02 23:23:57 +0200
committerDominik Kaiser2026-06-02 23:23:57 +0200
commit4632dd8e9e95a377993ef677a157202fda8072f9 (patch)
tree60990f769556109c98e697c72dac1ad92f774d0f /src/sparse_set.rs
downloadecs-main.tar.gz
ecs-main.zip
Implement ECSHEADmain
Diffstat (limited to 'src/sparse_set.rs')
-rw-r--r--src/sparse_set.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/sparse_set.rs b/src/sparse_set.rs
new file mode 100644
index 0000000..d7a69eb
--- /dev/null
+++ b/src/sparse_set.rs
@@ -0,0 +1,100 @@
+use super::Entity;
+
+pub struct SparseSet<T> {
+ pub dense: Vec<T>,
+ pub entities: Vec<Entity>,
+ pub sparse: Vec<Option<usize>>,
+}
+
+impl<T> SparseSet<T> {
+ pub fn new() -> Self {
+ Self {
+ dense: Vec::new(),
+ entities: Vec::new(),
+ sparse: Vec::new(),
+ }
+ }
+
+ pub fn insert(&mut self, entity: Entity, component: T) {
+ if self.sparse.len() <= entity {
+ self.sparse.resize(entity + 1, None);
+ }
+
+ self.dense.push(component);
+ self.entities.push(entity);
+
+ let id = self.dense.len() - 1;
+ self.sparse[entity] = Some(id);
+ }
+
+ pub fn remove(&mut self, entity: Entity) {
+ let Some(id) = self.sparse.get(entity).copied().flatten() else {
+ return;
+ };
+ let Some(last) = self.entities.last().copied() else {
+ return;
+ };
+ self.dense.swap_remove(id);
+ self.entities.swap_remove(id);
+ self.sparse[last] = Some(id);
+ self.sparse[entity] = None;
+ }
+
+ pub fn iter(&self) -> impl Iterator<Item = (Entity, &T)> {
+ self.entities.iter().copied().zip(self.dense.iter())
+ }
+
+ pub fn iter_mut(&mut self) -> impl Iterator<Item = (Entity, &mut T)> {
+ self.entities.iter().copied().zip(self.dense.iter_mut())
+ }
+
+ pub fn get(&self, entity: Entity) -> Option<&T> {
+ if let Some(id) = self.sparse.get(entity) {
+ match id {
+ Some(id) => self.dense.get(*id),
+ None => None,
+ }
+ } else {
+ None
+ }
+ }
+
+ pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
+ if let Some(id) = self.sparse.get(entity) {
+ match id {
+ Some(id) => self.dense.get_mut(*id),
+ None => None,
+ }
+ } else {
+ None
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn test_remove() {
+ let mut set = SparseSet::<i32>::new();
+ set.insert(3, 300);
+ set.insert(2, 200);
+ set.insert(4, 400);
+ set.insert(7, 700);
+
+ set.remove(4);
+
+ assert!(set.get(7).copied() == Some(700));
+ assert!(set.get(3).copied() == Some(300));
+ assert!(set.get(2).copied() == Some(200));
+ assert!(set.get(4).copied().is_none());
+
+ set.remove(7);
+ assert!(set.get(7).copied().is_none());
+ assert!(set.get(3).copied() == Some(300));
+ assert!(set.get(2).copied() == Some(200));
+ assert!(set.get(4).copied().is_none());
+ }
+}