1#![deny(missing_docs)]
33#![no_std]
34
35extern crate alloc;
36
37#[doc(hidden)]
39pub extern crate core as __core;
40
41use core::iter::FusedIterator;
42use core::ops::Range;
43
44pub trait EntityRef: Copy + Eq {
47 fn new(_: usize) -> Self;
50
51 fn index(self) -> usize;
53}
54
55#[inline]
57pub fn iter_entity_range<E>(range: Range<E>) -> IterEntityRange<E>
58where
59 E: EntityRef,
60{
61 IterEntityRange {
62 range: range.start.index()..range.end.index(),
63 _phantom: core::marker::PhantomData,
64 }
65}
66
67pub struct IterEntityRange<E> {
69 range: Range<usize>,
70 _phantom: core::marker::PhantomData<E>,
71}
72
73impl<E> Iterator for IterEntityRange<E>
74where
75 E: EntityRef,
76{
77 type Item = E;
78
79 #[inline]
80 fn next(&mut self) -> Option<Self::Item> {
81 let i = self.range.next()?;
82 Some(E::new(i))
83 }
84
85 #[inline]
86 fn size_hint(&self) -> (usize, Option<usize>) {
87 self.range.size_hint()
88 }
89}
90
91impl<E> DoubleEndedIterator for IterEntityRange<E>
92where
93 E: EntityRef,
94{
95 #[inline]
96 fn next_back(&mut self) -> Option<Self::Item> {
97 let i = self.range.next_back()?;
98 Some(E::new(i))
99 }
100}
101
102impl<E> FusedIterator for IterEntityRange<E>
103where
104 E: EntityRef,
105 Range<usize>: FusedIterator,
106{
107}
108
109impl<E> ExactSizeIterator for IterEntityRange<E>
110where
111 E: EntityRef,
112 Range<usize>: ExactSizeIterator,
113{
114}
115
116#[macro_export]
118macro_rules! entity_impl {
119 ($entity:ident) => {
121 impl $crate::EntityRef for $entity {
122 #[inline]
123 fn new(index: usize) -> Self {
124 debug_assert!(index < ($crate::__core::u32::MAX as usize));
125 $entity(index as u32)
126 }
127
128 #[inline]
129 fn index(self) -> usize {
130 self.0 as usize
131 }
132 }
133
134 impl $crate::packed_option::ReservedValue for $entity {
135 #[inline]
136 fn reserved_value() -> $entity {
137 $entity($crate::__core::u32::MAX)
138 }
139
140 #[inline]
141 fn is_reserved_value(&self) -> bool {
142 self.0 == $crate::__core::u32::MAX
143 }
144 }
145
146 impl $entity {
147 #[allow(dead_code)]
149 #[inline]
150 pub fn from_u32(x: u32) -> Self {
151 debug_assert!(x < $crate::__core::u32::MAX);
152 $entity(x)
153 }
154
155 #[allow(dead_code)]
157 #[inline]
158 pub fn as_u32(self) -> u32 {
159 self.0
160 }
161
162 #[allow(dead_code)]
164 #[inline]
165 pub fn as_bits(self) -> u32 {
166 self.0
167 }
168
169 #[allow(dead_code)]
171 #[inline]
172 pub fn from_bits(x: u32) -> Self {
173 $entity(x)
174 }
175 }
176 };
177
178 ($entity:ident, $display_prefix:expr) => {
181 entity_impl!($entity);
182
183 impl $crate::__core::fmt::Display for $entity {
184 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
185 write!(f, concat!($display_prefix, "{}"), self.0)
186 }
187 }
188
189 impl $crate::__core::fmt::Debug for $entity {
190 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
191 (self as &dyn $crate::__core::fmt::Display).fmt(f)
192 }
193 }
194 };
195
196 ($entity:ident, $display_prefix:expr, $arg:ident, $to_expr:expr, $from_expr:expr) => {
199 impl $crate::EntityRef for $entity {
200 #[inline]
201 fn new(index: usize) -> Self {
202 debug_assert!(index < ($crate::__core::u32::MAX as usize));
203 let $arg = index as u32;
204 $to_expr
205 }
206
207 #[inline]
208 fn index(self) -> usize {
209 let $arg = self;
210 $from_expr as usize
211 }
212 }
213
214 impl $crate::packed_option::ReservedValue for $entity {
215 #[inline]
216 fn reserved_value() -> $entity {
217 $entity::from_u32($crate::__core::u32::MAX)
218 }
219
220 #[inline]
221 fn is_reserved_value(&self) -> bool {
222 self.as_u32() == $crate::__core::u32::MAX
223 }
224 }
225
226 impl $entity {
227 #[allow(dead_code)]
229 #[inline]
230 pub fn from_u32(x: u32) -> Self {
231 debug_assert!(x < $crate::__core::u32::MAX);
232 let $arg = x;
233 $to_expr
234 }
235
236 #[allow(dead_code)]
238 #[inline]
239 pub fn as_u32(self) -> u32 {
240 let $arg = self;
241 $from_expr
242 }
243 }
244
245 impl $crate::__core::fmt::Display for $entity {
246 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
247 write!(f, concat!($display_prefix, "{}"), self.as_u32())
248 }
249 }
250
251 impl $crate::__core::fmt::Debug for $entity {
252 fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
253 (self as &dyn $crate::__core::fmt::Display).fmt(f)
254 }
255 }
256 };
257}
258
259pub mod packed_option;
260
261mod boxed_slice;
262mod iter;
263mod keys;
264mod list;
265mod map;
266mod primary;
267mod set;
268mod sparse;
269mod unsigned;
270
271pub use self::boxed_slice::BoxedSlice;
272pub use self::iter::{Iter, IterMut};
273pub use self::keys::Keys;
274pub use self::list::{EntityList, ListPool};
275pub use self::map::SecondaryMap;
276pub use self::primary::PrimaryMap;
277pub use self::set::EntitySet;
278pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
279pub use self::unsigned::Unsigned;
280
281#[cfg(test)]
284mod tests {
285 macro_rules! entity_test {
287 ($entity:ident) => {
288 #[test]
289 fn from_usize_to_u32() {
290 let e = $entity::new(42);
291 assert_eq!(e.as_u32(), 42_u32);
292 }
293
294 #[test]
295 fn from_u32_to_usize() {
296 let e = $entity::from_u32(42);
297 assert_eq!(e.index(), 42_usize);
298 }
299
300 #[test]
301 fn comparisons_work() {
302 let a = $entity::from_u32(42);
303 let b = $entity::new(42);
304 assert_eq!(a, b);
305 }
306
307 #[should_panic]
308 #[cfg(debug_assertions)]
309 #[test]
310 fn cannot_construct_from_reserved_u32() {
311 use crate::packed_option::ReservedValue;
312 let reserved = $entity::reserved_value().as_u32();
313 let _ = $entity::from_u32(reserved); }
315
316 #[should_panic]
317 #[cfg(debug_assertions)]
318 #[test]
319 fn cannot_construct_from_reserved_usize() {
320 use crate::packed_option::ReservedValue;
321 let reserved = $entity::reserved_value().index();
322 let _ = $entity::new(reserved); }
324 };
325 }
326
327 mod basic_entity {
329 use crate::EntityRef;
330 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
331 struct BasicEntity(u32);
332 entity_impl!(BasicEntity);
333 entity_test!(BasicEntity);
334 }
335
336 mod prefix_entity {
338 use crate::EntityRef;
339 #[derive(Clone, Copy, PartialEq, Eq)]
340 struct PrefixEntity(u32);
341 entity_impl!(PrefixEntity, "prefix-");
342 entity_test!(PrefixEntity);
343
344 #[test]
345 fn display_prefix_works() {
346 let e = PrefixEntity::new(0);
347 assert_eq!(alloc::format!("{e}"), "prefix-0");
348 }
349 }
350
351 mod other_entity {
354 mod inner {
355 #[derive(Clone, Copy, PartialEq, Eq)]
356 pub struct InnerEntity(u32);
357
358 impl From<u32> for InnerEntity {
359 fn from(x: u32) -> Self {
360 Self(x)
361 }
362 }
363
364 impl From<InnerEntity> for u32 {
365 fn from(x: InnerEntity) -> Self {
366 x.0
367 }
368 }
369 }
370
371 use {self::inner::InnerEntity, crate::EntityRef};
372 entity_impl!(InnerEntity, "inner-", i, InnerEntity::from(i), u32::from(i));
373 entity_test!(InnerEntity);
374
375 #[test]
376 fn display_prefix_works() {
377 let e = InnerEntity::new(0);
378 assert_eq!(alloc::format!("{e}"), "inner-0");
379 }
380 }
381}