@@ -47,12 +47,7 @@ use bevy_utils::tracing::warn;
47
47
48
48
use crate :: {
49
49
archetype:: { ArchetypeId , ArchetypeRow } ,
50
- identifier:: {
51
- error:: IdentifierError ,
52
- kinds:: IdKind ,
53
- masks:: { IdentifierMask , HIGH_MASK } ,
54
- Identifier ,
55
- } ,
50
+ identifier:: { error:: IdentifierError , masks:: IdentifierMask , Identifier } ,
56
51
storage:: { SparseSetIndex , TableId , TableRow } ,
57
52
} ;
58
53
use serde:: { Deserialize , Serialize } ;
@@ -217,12 +212,20 @@ pub(crate) enum AllocAtWithoutReplacement {
217
212
218
213
impl Entity {
219
214
/// Construct an [`Entity`] from a raw `index` value and a non-zero `generation` value.
220
- /// Ensure that the generation value is never greater than `0x7FFF_FFFF `.
215
+ /// Ensure that the masked generation value is never greater than `0x3FFF_FFFF `.
221
216
#[ inline( always) ]
222
217
pub ( crate ) const fn from_raw_and_generation ( index : u32 , generation : NonZeroU32 ) -> Entity {
223
- debug_assert ! ( generation. get( ) <= HIGH_MASK ) ;
218
+ // Create an intermediate Identifier to do debug verification
219
+ // This will get optimised away as Identifier and Entity have identical layouts
220
+ let id = Identifier :: from_parts ( index, generation) ;
224
221
225
- Self { index, generation }
222
+ // If the PLACEHOLDER bit flag is set, then it is not a valid generation value for Entity.
223
+ debug_assert ! ( !id. is_placeholder( ) ) ;
224
+
225
+ Self {
226
+ index : id. low ( ) ,
227
+ generation : id. high ( ) ,
228
+ }
226
229
}
227
230
228
231
/// An entity ID with a placeholder value. This may or may not correspond to an actual entity,
@@ -286,7 +289,13 @@ impl Entity {
286
289
/// No particular structure is guaranteed for the returned bits.
287
290
#[ inline( always) ]
288
291
pub const fn to_bits ( self ) -> u64 {
289
- IdentifierMask :: pack_into_u64 ( self . index , self . generation . get ( ) )
292
+ self . to_identifier ( ) . to_bits ( )
293
+ }
294
+
295
+ /// Convert to an [`Identifier`].
296
+ #[ inline( always) ]
297
+ pub const fn to_identifier ( self ) -> Identifier {
298
+ Identifier :: from_parts ( self . index , self . generation )
290
299
}
291
300
292
301
/// Reconstruct an `Entity` previously destructured with [`Entity::to_bits`].
@@ -298,12 +307,19 @@ impl Entity {
298
307
/// This method will likely panic if given `u64` values that did not come from [`Entity::to_bits`].
299
308
#[ inline]
300
309
pub const fn from_bits ( bits : u64 ) -> Self {
310
+ #[ inline( never) ]
311
+ #[ cold]
312
+ #[ track_caller]
313
+ const fn invalid_entity ( ) -> ! {
314
+ panic ! ( "Attempted to initialise invalid bits as an entity" ) ;
315
+ }
316
+
301
317
// Construct an Identifier initially to extract the kind from.
302
318
let id = Self :: try_from_bits ( bits) ;
303
319
304
320
match id {
305
321
Ok ( entity) => entity,
306
- Err ( _) => panic ! ( "Attempted to initialise invalid bits as an entity" ) ,
322
+ Err ( _) => invalid_entity ( ) ,
307
323
}
308
324
}
309
325
@@ -315,9 +331,7 @@ impl Entity {
315
331
#[ inline( always) ]
316
332
pub const fn try_from_bits ( bits : u64 ) -> Result < Self , IdentifierError > {
317
333
if let Ok ( id) = Identifier :: try_from_bits ( bits) {
318
- let kind = id. kind ( ) as u8 ;
319
-
320
- if kind == ( IdKind :: Entity as u8 ) {
334
+ if !id. is_placeholder ( ) {
321
335
return Ok ( Self {
322
336
index : id. low ( ) ,
323
337
generation : id. high ( ) ,
@@ -343,8 +357,7 @@ impl Entity {
343
357
/// given index has been reused (index, generation) pairs uniquely identify a given Entity.
344
358
#[ inline]
345
359
pub const fn generation ( self ) -> u32 {
346
- // Mask so not to expose any flags
347
- IdentifierMask :: extract_value_from_high ( self . generation . get ( ) )
360
+ self . to_identifier ( ) . masked_high ( )
348
361
}
349
362
}
350
363
@@ -353,14 +366,19 @@ impl TryFrom<Identifier> for Entity {
353
366
354
367
#[ inline]
355
368
fn try_from ( value : Identifier ) -> Result < Self , Self :: Error > {
369
+ // Every Entity is an Identifier, but not every Identifier
370
+ // is an Entity.
356
371
Self :: try_from_bits ( value. to_bits ( ) )
357
372
}
358
373
}
359
374
360
375
impl From < Entity > for Identifier {
361
376
#[ inline]
362
377
fn from ( value : Entity ) -> Self {
363
- Identifier :: from_bits ( value. to_bits ( ) )
378
+ // Entity's layout is exactly the same as Identifier, therefore
379
+ // this will remove any panic! path as we know Entity -> Identifier
380
+ // conversions will never panic.
381
+ value. to_identifier ( )
364
382
}
365
383
}
366
384
@@ -684,12 +702,12 @@ impl Entities {
684
702
return None ;
685
703
}
686
704
687
- meta. generation = IdentifierMask :: inc_masked_high_by ( meta. generation , 1 ) ;
705
+ meta. generation = IdentifierMask :: inc_entity_generation_by ( meta. generation , 1 ) ;
688
706
689
707
if meta. generation == NonZeroU32 :: MIN {
690
708
warn ! (
691
709
"Entity({}) generation wrapped on Entities::free, aliasing may occur" ,
692
- entity. index
710
+ entity. index( )
693
711
) ;
694
712
}
695
713
@@ -775,7 +793,8 @@ impl Entities {
775
793
776
794
let meta = & mut self . meta [ index as usize ] ;
777
795
if meta. location . archetype_id == ArchetypeId :: INVALID {
778
- meta. generation = IdentifierMask :: inc_masked_high_by ( meta. generation , generations) ;
796
+ meta. generation =
797
+ IdentifierMask :: inc_entity_generation_by ( meta. generation , generations) ;
779
798
true
780
799
} else {
781
800
false
0 commit comments