async_ecs/storage/
masked_storage.rs

1use std::mem::swap;
2
3use hibitset::BitSet;
4
5use crate::{
6    component::Component,
7    entity::{Entity, Index},
8    storage::Storage,
9};
10
11/// The `Storage` together with the `BitSet` that knows
12/// about which elements are stored, and which are not.
13pub struct MaskedStorage<T: Component> {
14    mask: BitSet,
15    inner: T::Storage,
16}
17
18impl<T: Component> MaskedStorage<T> {
19    /// Create new masked storage.
20    pub fn new(inner: T::Storage) -> Self {
21        Self {
22            mask: BitSet::new(),
23            inner,
24        }
25    }
26
27    /// Get the mask of living elements.
28    pub fn mask(&self) -> &BitSet {
29        &self.mask
30    }
31
32    /// Get areference to the inner storage.
33    pub fn storage(&self) -> &T::Storage {
34        &self.inner
35    }
36
37    /// Get a mutable reference to the inner storage.
38    pub fn storage_mut(&mut self) -> &mut T::Storage {
39        &mut self.inner
40    }
41
42    /// Insert new element
43    pub fn insert(&mut self, entity: Entity, mut component: T) -> Option<T> {
44        let index = entity.index();
45
46        if self.mask.contains(index) {
47            swap(&mut component, unsafe { self.inner.get_mut(index) });
48
49            Some(component)
50        } else {
51            self.mask.add(index);
52
53            unsafe { self.inner.insert(index, component) };
54
55            None
56        }
57    }
58
59    /// Clear the contents of this storage.
60    pub fn clear(&mut self) {
61        unsafe { self.inner.clean(&self.mask) };
62
63        self.mask.clear();
64    }
65
66    /// Remove an element by a given index.
67    pub fn remove(&mut self, index: Index) -> Option<T> {
68        if self.mask.remove(index) {
69            Some(unsafe { self.inner.remove(index) })
70        } else {
71            None
72        }
73    }
74
75    /// Drop an element by a given index.
76    pub fn drop(&mut self, index: Index) {
77        if self.mask.remove(index) {
78            unsafe { self.inner.drop(index) };
79        }
80    }
81}