1717
1818use core:: fmt:: { self , Formatter } ;
1919
20- use bevy:: prelude:: * ;
20+ use bevy:: {
21+ ecs:: entity:: { EntityGeneration , EntityRow } ,
22+ prelude:: * ,
23+ } ;
2124use serde:: {
2225 Deserializer , Serialize , Serializer ,
2326 de:: { self , SeqAccess , Visitor } ,
2427} ;
2528
2629/// Serializes an entity by writing its index and generation as separate numbers.
2730///
28- /// This reduces the space used for serializers with varint encoding.
31+ /// This reduces the space required when using serializers with varint encoding.
2932///
30- /// The index is first prepended with a bit flag to indicate if the generation
31- /// is serialized or not. It is not serialized if <= 1; note that generations are [`NonZeroU32`](core::num::NonZeroU32)
32- /// and a value of zero is used in [`Option<Entity>`] to signify [`None`], so generation 1 is the first
33- /// generation.
33+ /// Since the index can never be [`u32::MAX`], we reuse that extra niche to indicate
34+ /// whether the generation isn't [`EntityGeneration::FIRST`]. If it doesn't,
35+ /// the generation is skipped during serialization.
3436///
3537/// See also [`deserialize`] and [`postcard_utils::entity_to_extend_mut`](crate::postcard_utils::entity_to_extend_mut).
3638pub fn serialize < S : Serializer > ( entity : & Entity , serializer : S ) -> Result < S :: Ok , S :: Error > {
37- let mut flagged_index = ( entity. index ( ) as u64 ) << 1 ;
38- let flag = entity. generation ( ) > 1 ;
39- flagged_index |= flag as u64 ;
39+ let mut index = entity. index ( ) << 1 ;
40+ let has_generation = entity. generation ( ) != EntityGeneration :: FIRST ;
41+ index |= has_generation as u32 ;
4042
41- if flag {
42- let generation = entity. generation ( ) - 1 ;
43- ( flagged_index , generation) . serialize ( serializer)
43+ if has_generation {
44+ let generation = entity. generation ( ) . to_bits ( ) ;
45+ ( index , generation) . serialize ( serializer)
4446 } else {
45- flagged_index . serialize ( serializer)
47+ index . serialize ( serializer)
4648 }
4749}
4850
@@ -63,22 +65,23 @@ impl<'de> Visitor<'de> for EntityVisitor {
6365 }
6466
6567 fn visit_seq < A : SeqAccess < ' de > > ( self , mut seq : A ) -> Result < Self :: Value , A :: Error > {
66- let flagged_index : u64 = seq
68+ let index : u32 = seq
6769 . next_element ( ) ?
6870 . ok_or_else ( || de:: Error :: invalid_length ( 0 , & self ) ) ?;
6971
70- let has_generation = ( flagged_index & 1 ) != 0 ;
72+ let has_generation = ( index & 1 ) != 0 ;
7173
7274 let generation = if has_generation {
73- let generation: u32 = seq
74- . next_element ( ) ?
75- . ok_or_else ( || de:: Error :: invalid_length ( 1 , & self ) ) ?;
76- generation as u64 + 1
75+ seq. next_element ( ) ?
76+ . ok_or_else ( || de:: Error :: invalid_length ( 1 , & self ) ) ?
7777 } else {
78- 1
78+ 0
7979 } ;
8080
81- let bits = ( flagged_index >> 1 ) | ( generation << 32 ) ;
82- Ok ( Entity :: from_bits ( bits) )
81+ // SAFETY: `index` is non-max after shift.
82+ let row = unsafe { EntityRow :: from_raw_u32 ( index >> 1 ) . unwrap_unchecked ( ) } ;
83+ let generation = EntityGeneration :: from_bits ( generation) ;
84+
85+ Ok ( Entity :: from_row_and_generation ( row, generation) )
8386 }
8487}
0 commit comments