bones_ecs/
bitset.rs

1//! Bitset implementation.
2//!
3//! Bitsets are powered by the [`bitset_core`] crate.
4//!
5//! A Bones bitset is a vector of 32-byte sectors. The size of a bitset can be controlled by the
6//! `keysize*` features (note that they are all mutually exclusive with each other). The `keysize`
7//! is exponentially correlated to the number of bits, or entities, that the set can track; where
8//! the number of bits equals two raised to the power of `keysize`. Below are the available
9//! `keysize`s and the size of their resulting bitsets.
10//!
11//! | Keysize | Bit Count  | Sectors    | Memory |
12//! | ------- | ---------- | ---------- | ------ |
13//! |      32 |  4 billion | 16 million | 512 MB |
14//! |      24 | 16 million |      65536 |   2 MB |
15//! |      20 |  1 million |       4096 | 128 KB |
16//! |      16 |      65536 |        256 |   8 KB |
17//! |      12 |       4096 |         16 | 512  B |
18//! |      10 |       1024 |          4 | 128  B |
19//!
20//! Keysize (`K`) refers to the name of the feature. A keysize of 16 refers to the `keysize16`
21//! feature.
22//!
23//! Bit Count is the total number of bits in the bitset (`2^K`). Due to the nature of binary
24//! numbers this means that a value with more than `K` bits should not be used to index into the
25//! bitset since e.g. `u16::MAX` is the index of the last bit in a `keysize16` bitset.
26//!
27//! Sectors is the number of sub-arrays within the bitset `Vec`. Sectors are 256 bits as they are
28//! comprised of 8 `u32`s. Note that SIMD instructions process 256 bits/entities at a time.
29//!
30//! Memory is the total amount of memory that the bitset will occupy.
31//!
32//! [`bitset_core`]: https://docs.rs/bitset_core
33
34use crate::prelude::*;
35
36#[cfg(all(
37    feature = "keysize10",
38    not(feature = "keysize12"),
39    not(feature = "keysize16"),
40    not(feature = "keysize20"),
41    not(feature = "keysize24"),
42    not(feature = "keysize32")
43))]
44#[allow(missing_docs)]
45pub const BITSET_EXP: u32 = 10;
46
47#[cfg(all(
48    feature = "keysize12",
49    not(feature = "keysize10"),
50    not(feature = "keysize16"),
51    not(feature = "keysize20"),
52    not(feature = "keysize24"),
53    not(feature = "keysize32")
54))]
55#[allow(missing_docs)]
56pub const BITSET_EXP: u32 = 12;
57
58// 16 is the default, if no `keysize*` features are enabled then use this one.
59#[cfg(any(
60    feature = "keysize16",
61    all(
62        not(feature = "keysize10"),
63        not(feature = "keysize12"),
64        not(feature = "keysize20"),
65        not(feature = "keysize24"),
66        not(feature = "keysize32")
67    )
68))]
69#[allow(missing_docs)]
70pub const BITSET_EXP: u32 = 16;
71
72#[cfg(all(
73    feature = "keysize20",
74    not(feature = "keysize10"),
75    not(feature = "keysize12"),
76    not(feature = "keysize16"),
77    not(feature = "keysize24"),
78    not(feature = "keysize32")
79))]
80#[allow(missing_docs)]
81pub const BITSET_EXP: u32 = 20;
82
83#[cfg(all(
84    feature = "keysize24",
85    not(feature = "keysize10"),
86    not(feature = "keysize12"),
87    not(feature = "keysize16"),
88    not(feature = "keysize20"),
89    not(feature = "keysize32")
90))]
91#[allow(missing_docs)]
92pub const BITSET_EXP: u32 = 24;
93
94#[cfg(all(
95    feature = "keysize32",
96    not(feature = "keysize10"),
97    not(feature = "keysize12"),
98    not(feature = "keysize16"),
99    not(feature = "keysize20"),
100    not(feature = "keysize24")
101))]
102#[allow(missing_docs)]
103pub const BITSET_EXP: u32 = 32;
104
105pub use bitset_core::*;
106
107/// The number of bits in a bitset.
108pub(crate) const BITSET_SIZE: usize = 2usize.saturating_pow(BITSET_EXP);
109
110/// The number of bits in a bitset "sector" (one of the sub-arrays).
111///
112/// A sector is an array of 8 `u32` values, so there are `8 * 32` bits in a sector.
113///
114/// This value is constant, as a sector is appropriately sized to fit into a vector register for
115/// SIMD instructions.
116const BITSET_SECTOR_SIZE: usize = 32 * 8;
117
118const BITSET_SECTOR_COUNT: usize = BITSET_SIZE / BITSET_SECTOR_SIZE;
119
120/// The type of bitsets used to track entities in component storages.
121/// Mostly used to create caches.
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123#[derive(Deref, DerefMut, Clone, Debug)]
124pub struct BitSetVec(pub Vec<[u32; 8]>);
125
126impl Default for BitSetVec {
127    fn default() -> Self {
128        create_bitset()
129    }
130}
131
132impl BitSetVec {
133    /// Check whether or not the bitset contains the given entity.
134    #[inline]
135    pub fn contains(&self, entity: Entity) -> bool {
136        self.bit_test(entity.index() as usize)
137    }
138
139    /// Set an entity on the the bitset.
140    #[inline]
141    pub fn set(&mut self, entity: Entity) {
142        self.bit_set(entity.index() as usize);
143    }
144}
145
146/// Creates a bitset big enough to contain the index of each entity.
147/// Mostly used to create caches.
148pub fn create_bitset() -> BitSetVec {
149    BitSetVec(vec![[0u32; 8]; BITSET_SECTOR_COUNT])
150}