1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Bitset implementation.
//!
//! Bitsets are powered by the [`bitset_core`] crate.
//!
//! A Bones bitset is a vector of 32-byte sectors. The size of a bitset can be controlled by the
//! `keysize*` features (note that they are all mutually exclusive with each other). The `keysize`
//! is exponentially correlated to the number of bits, or entities, that the set can track; where
//! the number of bits equals two raised to the power of `keysize`. Below are the available
//! `keysize`s and the size of their resulting bitsets.
//!
//! | Keysize | Bit Count  | Sectors    | Memory |
//! | ------- | ---------- | ---------- | ------ |
//! |      32 |  4 billion | 16 million | 512 MB |
//! |      24 | 16 million |      65536 |   2 MB |
//! |      20 |  1 million |       4096 | 128 KB |
//! |      16 |      65536 |        256 |   8 KB |
//! |      12 |       4096 |         16 | 512  B |
//! |      10 |       1024 |          4 | 128  B |
//!
//! Keysize (`K`) refers to the name of the feature. A keysize of 16 refers to the `keysize16`
//! feature.
//!
//! Bit Count is the total number of bits in the bitset (`2^K`). Due to the nature of binary
//! numbers this means that a value with more than `K` bits should not be used to index into the
//! bitset since e.g. `u16::MAX` is the index of the last bit in a `keysize16` bitset.
//!
//! Sectors is the number of sub-arrays within the bitset `Vec`. Sectors are 256 bits as they are
//! comprised of 8 `u32`s. Note that SIMD instructions process 256 bits/entities at a time.
//!
//! Memory is the total amount of memory that the bitset will occupy.
//!
//! [`bitset_core`]: https://docs.rs/bitset_core

use crate::prelude::*;

#[cfg(all(
    feature = "keysize10",
    not(feature = "keysize12"),
    not(feature = "keysize16"),
    not(feature = "keysize20"),
    not(feature = "keysize24"),
    not(feature = "keysize32")
))]
#[allow(missing_docs)]
pub const BITSET_EXP: u32 = 10;

#[cfg(all(
    feature = "keysize12",
    not(feature = "keysize10"),
    not(feature = "keysize16"),
    not(feature = "keysize20"),
    not(feature = "keysize24"),
    not(feature = "keysize32")
))]
#[allow(missing_docs)]
pub const BITSET_EXP: u32 = 12;

// 16 is the default, if no `keysize*` features are enabled then use this one.
#[cfg(any(
    feature = "keysize16",
    all(
        not(feature = "keysize10"),
        not(feature = "keysize12"),
        not(feature = "keysize20"),
        not(feature = "keysize24"),
        not(feature = "keysize32")
    )
))]
#[allow(missing_docs)]
pub const BITSET_EXP: u32 = 16;

#[cfg(all(
    feature = "keysize20",
    not(feature = "keysize10"),
    not(feature = "keysize12"),
    not(feature = "keysize16"),
    not(feature = "keysize24"),
    not(feature = "keysize32")
))]
#[allow(missing_docs)]
pub const BITSET_EXP: u32 = 20;

#[cfg(all(
    feature = "keysize24",
    not(feature = "keysize10"),
    not(feature = "keysize12"),
    not(feature = "keysize16"),
    not(feature = "keysize20"),
    not(feature = "keysize32")
))]
#[allow(missing_docs)]
pub const BITSET_EXP: u32 = 24;

#[cfg(all(
    feature = "keysize32",
    not(feature = "keysize10"),
    not(feature = "keysize12"),
    not(feature = "keysize16"),
    not(feature = "keysize20"),
    not(feature = "keysize24")
))]
#[allow(missing_docs)]
pub const BITSET_EXP: u32 = 32;

pub use bitset_core::*;

/// The number of bits in a bitset.
pub(crate) const BITSET_SIZE: usize = 2usize.saturating_pow(BITSET_EXP);

/// The number of bits in a bitset "sector" (one of the sub-arrays).
///
/// A sector is an array of 8 `u32` values, so there are `8 * 32` bits in a sector.
///
/// This value is constant, as a sector is appropriately sized to fit into a vector register for
/// SIMD instructions.
const BITSET_SECTOR_SIZE: usize = 32 * 8;

const BITSET_SECTOR_COUNT: usize = BITSET_SIZE / BITSET_SECTOR_SIZE;

/// The type of bitsets used to track entities in component storages.
/// Mostly used to create caches.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Deref, DerefMut, Clone, Debug)]
pub struct BitSetVec(pub Vec<[u32; 8]>);

impl Default for BitSetVec {
    fn default() -> Self {
        create_bitset()
    }
}

impl BitSetVec {
    /// Check whether or not the bitset contains the given entity.
    #[inline]
    pub fn contains(&self, entity: Entity) -> bool {
        self.bit_test(entity.index() as usize)
    }

    /// Set an entity on the the bitset.
    #[inline]
    pub fn set(&mut self, entity: Entity) {
        self.bit_set(entity.index() as usize);
    }
}

/// Creates a bitset big enough to contain the index of each entity.
/// Mostly used to create caches.
pub fn create_bitset() -> BitSetVec {
    BitSetVec(vec![[0u32; 8]; BITSET_SECTOR_COUNT])
}