1pub use bevy_ecs_macros::MapEntities;
2use indexmap::{IndexMap, IndexSet};
3
4use crate::{
5    entity::{hash_map::EntityHashMap, Entity},
6    world::World,
7};
8
9use alloc::{
10    collections::{BTreeMap, BTreeSet, VecDeque},
11    vec::Vec,
12};
13use bevy_platform::collections::{HashMap, HashSet};
14use core::{
15    hash::{BuildHasher, Hash},
16    mem,
17};
18use smallvec::SmallVec;
19
20use super::EntityIndexSet;
21
22pub trait MapEntities {
57    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E);
62}
63
64impl MapEntities for Entity {
65    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
66        *self = entity_mapper.get_mapped(*self);
67    }
68}
69
70impl<T: MapEntities> MapEntities for Option<T> {
71    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
72        if let Some(entities) = self {
73            entities.map_entities(entity_mapper);
74        }
75    }
76}
77
78impl<K: MapEntities + Eq + Hash, V: MapEntities, S: BuildHasher + Default> MapEntities
79    for HashMap<K, V, S>
80{
81    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
82        *self = self
83            .drain()
84            .map(|(mut key_entities, mut value_entities)| {
85                key_entities.map_entities(entity_mapper);
86                value_entities.map_entities(entity_mapper);
87                (key_entities, value_entities)
88            })
89            .collect();
90    }
91}
92
93impl<T: MapEntities + Eq + Hash, S: BuildHasher + Default> MapEntities for HashSet<T, S> {
94    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
95        *self = self
96            .drain()
97            .map(|mut entities| {
98                entities.map_entities(entity_mapper);
99                entities
100            })
101            .collect();
102    }
103}
104
105impl<K: MapEntities + Eq + Hash, V: MapEntities, S: BuildHasher + Default> MapEntities
106    for IndexMap<K, V, S>
107{
108    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
109        *self = self
110            .drain(..)
111            .map(|(mut key_entities, mut value_entities)| {
112                key_entities.map_entities(entity_mapper);
113                value_entities.map_entities(entity_mapper);
114                (key_entities, value_entities)
115            })
116            .collect();
117    }
118}
119
120impl<T: MapEntities + Eq + Hash, S: BuildHasher + Default> MapEntities for IndexSet<T, S> {
121    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
122        *self = self
123            .drain(..)
124            .map(|mut entities| {
125                entities.map_entities(entity_mapper);
126                entities
127            })
128            .collect();
129    }
130}
131
132impl MapEntities for EntityIndexSet {
133    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
134        *self = self
135            .drain(..)
136            .map(|e| entity_mapper.get_mapped(e))
137            .collect();
138    }
139}
140
141impl<K: MapEntities + Ord, V: MapEntities> MapEntities for BTreeMap<K, V> {
142    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
143        *self = mem::take(self)
144            .into_iter()
145            .map(|(mut key_entities, mut value_entities)| {
146                key_entities.map_entities(entity_mapper);
147                value_entities.map_entities(entity_mapper);
148                (key_entities, value_entities)
149            })
150            .collect();
151    }
152}
153
154impl<T: MapEntities + Ord> MapEntities for BTreeSet<T> {
155    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
156        *self = mem::take(self)
157            .into_iter()
158            .map(|mut entities| {
159                entities.map_entities(entity_mapper);
160                entities
161            })
162            .collect();
163    }
164}
165
166impl<T: MapEntities, const N: usize> MapEntities for [T; N] {
167    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
168        for entities in self.iter_mut() {
169            entities.map_entities(entity_mapper);
170        }
171    }
172}
173
174impl<T: MapEntities> MapEntities for Vec<T> {
175    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
176        for entities in self.iter_mut() {
177            entities.map_entities(entity_mapper);
178        }
179    }
180}
181
182impl<T: MapEntities> MapEntities for VecDeque<T> {
183    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
184        for entities in self.iter_mut() {
185            entities.map_entities(entity_mapper);
186        }
187    }
188}
189
190impl<T: MapEntities, A: smallvec::Array<Item = T>> MapEntities for SmallVec<A> {
191    fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
192        for entities in self.iter_mut() {
193            entities.map_entities(entity_mapper);
194        }
195    }
196}
197
198pub trait EntityMapper {
230    fn get_mapped(&mut self, source: Entity) -> Entity;
232
233    fn set_mapped(&mut self, source: Entity, target: Entity);
236}
237
238impl EntityMapper for () {
239    #[inline]
240    fn get_mapped(&mut self, source: Entity) -> Entity {
241        source
242    }
243
244    #[inline]
245    fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
246}
247
248impl EntityMapper for (Entity, Entity) {
249    #[inline]
250    fn get_mapped(&mut self, source: Entity) -> Entity {
251        if source == self.0 {
252            self.1
253        } else {
254            source
255        }
256    }
257
258    fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
259}
260
261impl EntityMapper for &mut dyn EntityMapper {
262    fn get_mapped(&mut self, source: Entity) -> Entity {
263        (*self).get_mapped(source)
264    }
265
266    fn set_mapped(&mut self, source: Entity, target: Entity) {
267        (*self).set_mapped(source, target);
268    }
269}
270
271impl EntityMapper for SceneEntityMapper<'_> {
272    fn get_mapped(&mut self, source: Entity) -> Entity {
274        if let Some(&mapped) = self.map.get(&source) {
275            return mapped;
276        }
277
278        let new = Entity::from_row_and_generation(
280            self.dead_start.row(),
281            self.dead_start.generation.after_versions(self.generations),
282        );
283        self.generations = self.generations.wrapping_add(1);
284
285        self.map.insert(source, new);
286
287        new
288    }
289
290    fn set_mapped(&mut self, source: Entity, target: Entity) {
291        self.map.insert(source, target);
292    }
293}
294
295impl EntityMapper for EntityHashMap<Entity> {
296    fn get_mapped(&mut self, source: Entity) -> Entity {
298        self.get(&source).cloned().unwrap_or(source)
299    }
300
301    fn set_mapped(&mut self, source: Entity, target: Entity) {
302        self.insert(source, target);
303    }
304}
305
306pub struct SceneEntityMapper<'m> {
312    map: &'m mut EntityHashMap<Entity>,
321    dead_start: Entity,
323    generations: u32,
325}
326
327impl<'m> SceneEntityMapper<'m> {
328    pub fn get_map(&'m self) -> &'m EntityHashMap<Entity> {
330        self.map
331    }
332
333    pub fn get_map_mut(&'m mut self) -> &'m mut EntityHashMap<Entity> {
335        self.map
336    }
337
338    pub fn new(map: &'m mut EntityHashMap<Entity>, world: &mut World) -> Self {
340        world.flush_entities();
343        Self {
344            map,
345            dead_start: unsafe { world.entities_mut().alloc() },
347            generations: 0,
348        }
349    }
350
351    pub fn finish(self, world: &mut World) {
355        let entities = unsafe { world.entities_mut() };
357        assert!(entities.free(self.dead_start).is_some());
358        assert!(entities.reserve_generations(self.dead_start.index(), self.generations));
359    }
360
361    pub fn world_scope<R>(
368        entity_map: &'m mut EntityHashMap<Entity>,
369        world: &mut World,
370        f: impl FnOnce(&mut World, &mut Self) -> R,
371    ) -> R {
372        let mut mapper = Self::new(entity_map, world);
373        let result = f(world, &mut mapper);
374        mapper.finish(world);
375        result
376    }
377}
378
379#[cfg(test)]
380mod tests {
381
382    use crate::{
383        entity::{Entity, EntityHashMap, EntityMapper, SceneEntityMapper},
384        world::World,
385    };
386
387    #[test]
388    fn entity_mapper() {
389        let mut map = EntityHashMap::default();
390        let mut world = World::new();
391        let mut mapper = SceneEntityMapper::new(&mut map, &mut world);
392
393        let mapped_ent = Entity::from_raw_u32(1).unwrap();
394        let dead_ref = mapper.get_mapped(mapped_ent);
395
396        assert_eq!(
397            dead_ref,
398            mapper.get_mapped(mapped_ent),
399            "should persist the allocated mapping from the previous line"
400        );
401        assert_eq!(
402            mapper.get_mapped(Entity::from_raw_u32(2).unwrap()).index(),
403            dead_ref.index(),
404            "should re-use the same index for further dead refs"
405        );
406
407        mapper.finish(&mut world);
408        let entity = world.spawn_empty().id();
410        assert_eq!(entity.index(), dead_ref.index());
411        assert!(entity
412            .generation()
413            .cmp_approx(&dead_ref.generation())
414            .is_gt());
415    }
416
417    #[test]
418    fn world_scope_reserves_generations() {
419        let mut map = EntityHashMap::default();
420        let mut world = World::new();
421
422        let dead_ref = SceneEntityMapper::world_scope(&mut map, &mut world, |_, mapper| {
423            mapper.get_mapped(Entity::from_raw_u32(0).unwrap())
424        });
425
426        let entity = world.spawn_empty().id();
428        assert_eq!(entity.index(), dead_ref.index());
429        assert!(entity
430            .generation()
431            .cmp_approx(&dead_ref.generation())
432            .is_gt());
433    }
434
435    #[test]
436    fn entity_mapper_no_panic() {
437        let mut world = World::new();
438        world.entities.reserve_entity();
440        assert!(world.entities.needs_flush());
441
442        SceneEntityMapper::world_scope(&mut Default::default(), &mut world, |_, m| {
445            m.get_mapped(Entity::PLACEHOLDER);
446        });
447
448        assert!(!world.entities.needs_flush());
450    }
451}