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
#[cfg(feature = "serde")]
mod serde;
use core::num::NonZeroU64;
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct EntityId(pub(super) NonZeroU64);
impl EntityId {
pub(crate) const VERSION_LEN: u64 = 16;
const INDEX_MASK: u64 = !0 >> Self::VERSION_LEN;
const VERSION_MASK: u64 = !Self::INDEX_MASK;
#[inline]
pub(crate) fn index(self) -> u64 {
(self.0.get() & Self::INDEX_MASK) - 1
}
#[inline]
pub(crate) fn uindex(self) -> usize {
self.index() as usize
}
#[inline]
pub(crate) fn version(self) -> u64 {
(self.0.get() & Self::VERSION_MASK) >> (64 - Self::VERSION_LEN)
}
#[inline]
pub(crate) fn new(index: u64) -> Self {
assert!(index < Self::INDEX_MASK);
EntityId(unsafe { NonZeroU64::new_unchecked(index + 1) })
}
#[cfg(feature = "serde")]
#[inline]
pub(crate) fn new_from_pair(index: u64, version: u16) -> Self {
assert!(index < Self::INDEX_MASK);
EntityId(unsafe {
NonZeroU64::new_unchecked((index + 1) | ((version as u64) << (64 - Self::VERSION_LEN)))
})
}
#[cfg(not(test))]
#[inline]
pub(super) fn set_index(&mut self, index: u64) {
assert!(index < Self::INDEX_MASK);
self.0 =
unsafe { NonZeroU64::new_unchecked((self.0.get() & Self::VERSION_MASK) | (index + 1)) }
}
#[cfg(test)]
pub(crate) fn set_index(&mut self, index: u64) {
assert!(index + 1 <= Self::INDEX_MASK);
self.0 =
unsafe { NonZeroU64::new_unchecked((self.0.get() & Self::VERSION_MASK) | (index + 1)) }
}
#[inline]
pub(super) fn bump_version(&mut self) -> Result<(), ()> {
if self.0.get() < !(!0 >> (Self::VERSION_LEN - 1)) {
self.0 = unsafe {
NonZeroU64::new_unchecked(
(self.index() + 1) | ((self.version() + 1) << (64 - Self::VERSION_LEN)),
)
};
Ok(())
} else {
Err(())
}
}
#[cfg(test)]
pub(crate) fn zero() -> Self {
EntityId(NonZeroU64::new(1).unwrap())
}
pub fn dead() -> Self {
EntityId(unsafe { NonZeroU64::new_unchecked(core::u64::MAX) })
}
pub(crate) fn bucket(self) -> usize {
self.uindex() / crate::sparse_set::BUCKET_SIZE
}
pub(crate) fn bucket_index(self) -> usize {
self.uindex() % crate::sparse_set::BUCKET_SIZE
}
}
impl core::fmt::Debug for EntityId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"EntityId {{ index: {}, version: {} }}",
self.index(),
self.version()
)
}
}
#[test]
fn entity_id() {
let mut entity_id = EntityId::new(0);
assert_eq!(entity_id.index(), 0);
assert_eq!(entity_id.version(), 0);
entity_id.set_index(701);
assert_eq!(entity_id.index(), 701);
assert_eq!(entity_id.version(), 0);
entity_id.bump_version().unwrap();
entity_id.bump_version().unwrap();
entity_id.bump_version().unwrap();
assert_eq!(entity_id.index(), 701);
assert_eq!(entity_id.version(), 3);
entity_id.set_index(554);
assert_eq!(entity_id.index(), 554);
assert_eq!(entity_id.version(), 3);
}