1#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
33#![warn(unused_import_braces)]
34#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
35#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
36#![cfg_attr(
37 feature = "cargo-clippy",
38 warn(
39 clippy::float_arithmetic,
40 clippy::mut_mut,
41 clippy::nonminimal_bool,
42 clippy::map_unwrap_or,
43 clippy::clippy::print_stdout,
44 clippy::unicode_not_nfc,
45 clippy::use_self
46 )
47)]
48#![no_std]
49
50extern crate alloc;
51
52#[doc(hidden)]
54pub extern crate core as __core;
55
56pub trait EntityRef: Copy + Eq {
59 fn new(_: usize) -> Self;
62
63 fn index(self) -> usize;
65}
66
67#[macro_export]
69macro_rules! entity_impl {
70 ($entity:ident) => {
72 impl $crate::EntityRef for $entity {
73 #[inline]
74 fn new(index: usize) -> Self {
75 debug_assert!(index < ($crate::__core::u32::MAX as usize));
76 $entity(index as u32)
77 }
78
79 #[inline]
80 fn index(self) -> usize {
81 self.0 as usize
82 }
83 }
84
85 impl $crate::packed_option::ReservedValue for $entity {
86 #[inline]
87 fn reserved_value() -> $entity {
88 $entity($crate::__core::u32::MAX)
89 }
90
91 #[inline]
92 fn is_reserved_value(&self) -> bool {
93 self.0 == $crate::__core::u32::MAX
94 }
95 }
96
97 impl $entity {
98 #[allow(dead_code)]
100 #[inline]
101 pub fn from_u32(x: u32) -> Self {
102 debug_assert!(x < $crate::__core::u32::MAX);
103 $entity(x)
104 }
105
106 #[allow(dead_code)]
108 #[inline]
109 pub fn as_u32(self) -> u32 {
110 self.0
111 }
112
113 #[allow(dead_code)]
115 #[inline]
116 pub fn as_bits(self) -> u32 {
117 self.0
118 }
119
120 #[allow(dead_code)]
122 #[inline]
123 pub fn from_bits(x: u32) -> Self {
124 $entity(x)
125 }
126 }
127 };
128
129 ($entity:ident, $display_prefix:expr) => {
132 entity_impl!($entity);
133
134 impl $crate::__core::fmt::Display for $entity {
135 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
136 write!(f, concat!($display_prefix, "{}"), self.0)
137 }
138 }
139
140 impl $crate::__core::fmt::Debug for $entity {
141 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
142 (self as &dyn $crate::__core::fmt::Display).fmt(f)
143 }
144 }
145 };
146
147 ($entity:ident, $display_prefix:expr, $arg:ident, $to_expr:expr, $from_expr:expr) => {
150 impl $crate::EntityRef for $entity {
151 #[inline]
152 fn new(index: usize) -> Self {
153 debug_assert!(index < ($crate::__core::u32::MAX as usize));
154 let $arg = index as u32;
155 $to_expr
156 }
157
158 #[inline]
159 fn index(self) -> usize {
160 let $arg = self;
161 $from_expr as usize
162 }
163 }
164
165 impl $crate::packed_option::ReservedValue for $entity {
166 #[inline]
167 fn reserved_value() -> $entity {
168 $entity::from_u32($crate::__core::u32::MAX)
169 }
170
171 #[inline]
172 fn is_reserved_value(&self) -> bool {
173 self.as_u32() == $crate::__core::u32::MAX
174 }
175 }
176
177 impl $entity {
178 #[allow(dead_code)]
180 #[inline]
181 pub fn from_u32(x: u32) -> Self {
182 debug_assert!(x < $crate::__core::u32::MAX);
183 let $arg = x;
184 $to_expr
185 }
186
187 #[allow(dead_code)]
189 #[inline]
190 pub fn as_u32(self) -> u32 {
191 let $arg = self;
192 $from_expr
193 }
194 }
195
196 impl $crate::__core::fmt::Display for $entity {
197 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
198 write!(f, concat!($display_prefix, "{}"), self.as_u32())
199 }
200 }
201
202 impl $crate::__core::fmt::Debug for $entity {
203 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
204 (self as &dyn $crate::__core::fmt::Display).fmt(f)
205 }
206 }
207 };
208}
209
210pub mod packed_option;
211
212mod boxed_slice;
213mod iter;
214mod keys;
215mod list;
216mod map;
217mod primary;
218mod set;
219mod sparse;
220
221pub use self::boxed_slice::BoxedSlice;
222pub use self::iter::{Iter, IterMut};
223pub use self::keys::Keys;
224pub use self::list::{EntityList, ListPool};
225pub use self::map::SecondaryMap;
226pub use self::primary::PrimaryMap;
227pub use self::set::EntitySet;
228pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
229
230#[cfg(test)]
233mod tests {
234 macro_rules! entity_test {
236 ($entity:ident) => {
237 #[test]
238 fn from_usize_to_u32() {
239 let e = $entity::new(42);
240 assert_eq!(e.as_u32(), 42_u32);
241 }
242
243 #[test]
244 fn from_u32_to_usize() {
245 let e = $entity::from_u32(42);
246 assert_eq!(e.index(), 42_usize);
247 }
248
249 #[test]
250 fn comparisons_work() {
251 let a = $entity::from_u32(42);
252 let b = $entity::new(42);
253 assert_eq!(a, b);
254 }
255
256 #[should_panic]
257 #[test]
258 fn cannot_construct_from_reserved_u32() {
259 use crate::packed_option::ReservedValue;
260 let reserved = $entity::reserved_value().as_u32();
261 let _ = $entity::from_u32(reserved); }
263
264 #[should_panic]
265 #[test]
266 fn cannot_construct_from_reserved_usize() {
267 use crate::packed_option::ReservedValue;
268 let reserved = $entity::reserved_value().index();
269 let _ = $entity::new(reserved); }
271 };
272 }
273
274 mod basic_entity {
276 use crate::EntityRef;
277 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
278 struct BasicEntity(u32);
279 entity_impl!(BasicEntity);
280 entity_test!(BasicEntity);
281 }
282
283 mod prefix_entity {
285 use crate::EntityRef;
286 #[derive(Clone, Copy, PartialEq, Eq)]
287 struct PrefixEntity(u32);
288 entity_impl!(PrefixEntity, "prefix-");
289 entity_test!(PrefixEntity);
290
291 #[test]
292 fn display_prefix_works() {
293 let e = PrefixEntity::new(0);
294 assert_eq!(alloc::format!("{}", e), "prefix-0");
295 }
296 }
297
298 mod other_entity {
301 mod inner {
302 #[derive(Clone, Copy, PartialEq, Eq)]
303 pub struct InnerEntity(u32);
304
305 impl From<u32> for InnerEntity {
306 fn from(x: u32) -> Self {
307 Self(x)
308 }
309 }
310
311 impl From<InnerEntity> for u32 {
312 fn from(x: InnerEntity) -> Self {
313 x.0
314 }
315 }
316 }
317
318 use {self::inner::InnerEntity, crate::EntityRef};
319 entity_impl!(InnerEntity, "inner-", i, InnerEntity::from(i), u32::from(i));
320 entity_test!(InnerEntity);
321
322 #[test]
323 fn display_prefix_works() {
324 let e = InnerEntity::new(0);
325 assert_eq!(alloc::format!("{}", e), "inner-0");
326 }
327 }
328}