diff --git a/src/archetype.rs b/src/archetype.rs index 2f01899..f14120a 100644 --- a/src/archetype.rs +++ b/src/archetype.rs @@ -241,23 +241,23 @@ impl Archetype { } fn grow(&mut self, increment: u32) { - unsafe { - let old_count = self.len as usize; - let new_cap = self.entities.len() + increment as usize; - let mut new_entities = vec![!0; new_cap].into_boxed_slice(); - new_entities[0..old_count].copy_from_slice(&self.entities[0..old_count]); - self.entities = new_entities; - - let old_data_size = mem::replace(&mut self.data_size, 0); - let mut state = HashMap::with_capacity_and_hasher(self.types.len(), Default::default()); - for ty in &self.types { - self.data_size = align(self.data_size, ty.layout.align()); - state.insert(ty.id, TypeState::new(self.data_size)); - self.data_size += ty.layout.size() * new_cap; - } - let new_data = if self.data_size == 0 { - NonNull::dangling() - } else { + let old_count = self.len as usize; + let new_cap = self.entities.len() + increment as usize; + let mut new_entities = vec![!0; new_cap].into_boxed_slice(); + new_entities[0..old_count].copy_from_slice(&self.entities[0..old_count]); + self.entities = new_entities; + + let old_data_size = mem::replace(&mut self.data_size, 0); + let mut state = HashMap::with_capacity_and_hasher(self.types.len(), Default::default()); + for ty in &self.types { + self.data_size = align(self.data_size, ty.layout.align()); + state.insert(ty.id, TypeState::new(self.data_size)); + self.data_size += ty.layout.size() * new_cap; + } + let new_data = if self.data_size == 0 { + NonNull::dangling() + } else { + unsafe { NonNull::new(alloc( Layout::from_size_align( self.data_size, @@ -266,17 +266,21 @@ impl Archetype { .unwrap(), )) .unwrap() - }; - if old_data_size != 0 { - for ty in &self.types { - let old_off = self.state.get(&ty.id).unwrap().offset; - let new_off = state.get(&ty.id).unwrap().offset; + } + }; + if old_data_size != 0 { + for ty in &self.types { + let old_off = self.state.get(&ty.id).unwrap().offset; + let new_off = state.get(&ty.id).unwrap().offset; + unsafe { ptr::copy_nonoverlapping( (*self.data.get()).as_ptr().add(old_off), new_data.as_ptr().add(new_off), ty.layout.size() * old_count, ); } + } + unsafe { dealloc( (*self.data.get()).as_ptr().cast(), Layout::from_size_align_unchecked( @@ -285,10 +289,10 @@ impl Archetype { ), ); } - - self.data = UnsafeCell::new(new_data); - self.state = state; } + + self.data = UnsafeCell::new(new_data); + self.state = state; } /// Returns the ID of the entity moved into `index`, if any @@ -396,7 +400,7 @@ impl Archetype { .find(|typ| typ.id == component_type) .map(|info| info.layout) } - + /// Add components from another archetype with identical components /// /// # Safety diff --git a/src/query_one.rs b/src/query_one.rs index bfd6792..ecd51cc 100644 --- a/src/query_one.rs +++ b/src/query_one.rs @@ -37,10 +37,10 @@ impl<'a, Q: Query> QueryOne<'a, Q> { if self.borrowed { panic!("called QueryOnce::get twice; construct a new query instead"); } + let fetch = Q::Fetch::new(self.archetype)?; + self.borrowed = true; + Q::Fetch::borrow(self.archetype); unsafe { - let fetch = Q::Fetch::new(self.archetype)?; - self.borrowed = true; - Q::Fetch::borrow(self.archetype); Some(fetch.get(self.index as usize)) } } diff --git a/src/world.rs b/src/world.rs index 83343ea..a79d4a2 100644 --- a/src/world.rs +++ b/src/world.rs @@ -144,16 +144,16 @@ impl World { }); let archetype = &mut self.archetypes[archetype_id as usize]; + let index = unsafe { archetype.allocate(entity.id) }; unsafe { - let index = archetype.allocate(entity.id); components.put(|ptr, ty| { archetype.put_dynamic(ptr, ty.id(), ty.layout().size(), index); }); - self.entities.meta[entity.id as usize].location = Location { - archetype: archetype_id, - index, - }; } + self.entities.meta[entity.id as usize].location = Location { + archetype: archetype_id, + index, + }; } /// Efficiently spawn a large number of entities with the same components @@ -542,13 +542,12 @@ impl World { self.flush(); let loc = self.entities.get_mut(entity)?; - unsafe { // Assemble Vec for the final entity let arch = &mut self.archetypes[loc.archetype as usize]; let mut info = arch.types().to_vec(); for ty in components.type_info() { - if let Some(ptr) = arch.get_dynamic(ty.id(), ty.layout().size(), loc.index) { - ty.drop(ptr.as_ptr()); + if let Some(ptr) = unsafe { arch.get_dynamic(ty.id(), ty.layout().size(), loc.index) }{ + unsafe { ty.drop(ptr.as_ptr()) }; } else { info.push(ty); } @@ -571,9 +570,11 @@ impl World { if target == loc.archetype { // Update components in the current archetype let arch = &mut self.archetypes[loc.archetype as usize]; - components.put(|ptr, ty| { - arch.put_dynamic(ptr, ty.id(), ty.layout().size(), loc.index); - }); + unsafe { + components.put(|ptr, ty| { + arch.put_dynamic(ptr, ty.id(), ty.layout().size(), loc.index); + }); + } return Ok(()); } @@ -583,18 +584,19 @@ impl World { loc.archetype as usize, target as usize, ); - let target_index = target_arch.allocate(entity.id); + let target_index = unsafe { target_arch.allocate(entity.id) }; loc.archetype = target; let old_index = mem::replace(&mut loc.index, target_index); - if let Some(moved) = source_arch.move_to(old_index, |ptr, ty, size| { + if let Some(moved) = unsafe { source_arch.move_to(old_index, |ptr, ty, size| { target_arch.put_dynamic(ptr, ty, size, target_index); - }) { + }) }{ self.entities.meta[moved as usize].location.index = old_index; } - components.put(|ptr, ty| { - target_arch.put_dynamic(ptr, ty.id(), ty.layout().size(), target_index); - }); - } + unsafe { + components.put(|ptr, ty| { + target_arch.put_dynamic(ptr, ty.id(), ty.layout().size(), target_index); + }); + } Ok(()) }