Skip to content

Commit

Permalink
Implementing Clone for world and archetype if all the components in q…
Browse files Browse the repository at this point in the history
…uestion are Clone as well
  • Loading branch information
recatek committed Jan 27, 2025
1 parent cdd469c commit 7f27b03
Show file tree
Hide file tree
Showing 6 changed files with 508 additions and 8 deletions.
2 changes: 2 additions & 0 deletions macros/src/generate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(non_snake_case)] // Allow for type-like names to make quote!() clearer

mod cfg;
mod query;
mod util;
Expand Down
38 changes: 37 additions & 1 deletion macros/src/generate/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use xxhash_rust::xxh3::xxh3_128;
use crate::data::{DataArchetype, DataWorld};
use crate::generate::util::to_snake;

#[allow(non_snake_case)] // Allow for type-like names to make quote!() clearer
#[allow(non_snake_case)]
#[allow(unused_variables)] // For unused feature-controlled generation elements
pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
let world_snake = to_snake(&world_data.name);
Expand Down Expand Up @@ -156,6 +156,24 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
}
}

impl Clone for #World
where
#(for<'a> #Archetype: Clone,)*
{
/// Clones this world, including all of its data.
///
/// # Panics
///
/// This function will panic if any of its components are mutably borrowed,
/// or if there is not enough memory available to perform the clone.
#[inline(always)]
fn clone(&self) -> Self {
Self {
#(#archetype: self.#archetype.clone(),)*
}
}
}

#(
impl WorldHas<#Archetype> for #World {
#[inline(always)]
Expand Down Expand Up @@ -907,6 +925,24 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
}
)*

impl Clone for #Archetype
where
#(for<'a> #Component: Clone,)*
{
/// Clones this archetype, including all of its data.
///
/// # Panics
///
/// This function will panic if any of its components are mutably borrowed,
/// or if there is not enough memory available to perform the clone.
#[inline(always)]
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
}
}
}

/// Struct for named access to all of the components in an archetype's component tuple.
pub struct #ArchetypeComponents {
#(
Expand Down
61 changes: 59 additions & 2 deletions src/archetype/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use std::slice;

use seq_macro::seq;

use crate::archetype::components::*;
use crate::archetype::iter::*;
use crate::archetype::slices::*;
use crate::archetype::slot::{Slot, SlotIndex};
use crate::archetype::view::*;
use crate::archetype::components::*;
use crate::entity::{Entity, EntityDirect};
use crate::index::{TrimmedIndex, MAX_DATA_CAPACITY};
use crate::traits::{Archetype, EntityKey, StorageCanResolve};
Expand Down Expand Up @@ -702,6 +702,63 @@ macro_rules! declare_storage_n {
}
}

impl<A: Archetype, #(T~I,)*> Clone for $name<A, #(T~I,)*>
where
A::Components: $components<#(T~I,)*>,
#(T~I: Clone,)*
{
/// Clones this storage, including all of its data.
///
/// # Panics
///
/// This function will panic if any of its components are mutably borrowed,
/// or if there is not enough memory available to perform the clone.
#[inline]
fn clone(&self) -> Self {
#(let ref_d~I = self.d~I.borrow();)*

let mut new_slots = DataPtr::with_capacity(self.capacity);
let mut new_entities = DataPtr::with_capacity(self.capacity);
#(let mut new_d~I = DataPtr::with_capacity(self.capacity);)*

unsafe {

// SAFETY: We know that the storage is valid up to self.len.
let old_slots = self.slots.slice(self.capacity);
let old_entities = self.entities.slice(self.len);
#(let old_~I = ref_d~I.slice(self.len);)*

for idx in 0..self.capacity {
// SAFETY: We know that the slot storage is valid up to our capacity,
// and the new storage has no data that needs to be dropped first.
new_slots.write(idx, old_slots.get_unchecked(idx).clone());
}

for idx in 0..self.len {
// SAFETY: We know that the slot storage is valid up to our len,
// and the new storage has no data that needs to be dropped first.
new_entities.write(idx, old_entities.get_unchecked(idx).clone());
#(new_d~I.write(idx, old_~I.get_unchecked(idx).clone());)*
}

Self {
len: self.len,
version: self.version,
capacity: self.capacity,
free_head: self.free_head,
slots: new_slots,
entities: new_entities,
#(d~I: RefCell::new(new_d~I),)*

#[cfg(feature = "events")]
created: self.created.clone(),
#[cfg(feature = "events")]
destroyed: self.destroyed.clone(),
}
}
}
}

pub struct $borrow<'a, A: Archetype, #(T~I,)*> {
index: usize,
source: &'a $name<A, #(T~I,)*>,
Expand Down Expand Up @@ -913,7 +970,7 @@ impl<T> DataPtr<T> {
#[inline(always)]
unsafe fn write(&mut self, index: usize, val: T) {
unsafe {
// SAFETY: The caller guarantees that this slot is allocated and invalid.
// SAFETY: The caller guarantees that this cell is allocated and invalid.
(*self.0.as_ptr().add(index)).write(val);
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ pub trait View<'a> {
#[inline(always)]
fn component<'b, C>(&'b self) -> &'b C
where
Self::Archetype: ArchetypeHas<C>
Self::Archetype: ArchetypeHas<C>,
{
<Self::Archetype as ArchetypeHas<C>>::resolve_extract_view(self)
}
Expand All @@ -791,7 +791,7 @@ pub trait View<'a> {
#[inline(always)]
fn component_mut<'b, C>(&'b mut self) -> &'b mut C
where
Self::Archetype: ArchetypeHas<C>
Self::Archetype: ArchetypeHas<C>,
{
<Self::Archetype as ArchetypeHas<C>>::resolve_extract_view_mut(self)
}
Expand Down Expand Up @@ -824,7 +824,7 @@ pub trait Borrow<'a> {
#[inline(always)]
fn component<'b, C>(&'b self) -> Ref<'b, C>
where
Self::Archetype: ArchetypeHas<C>
Self::Archetype: ArchetypeHas<C>,
{
<Self::Archetype as ArchetypeHas<C>>::resolve_extract_borrow(self)
}
Expand All @@ -838,7 +838,7 @@ pub trait Borrow<'a> {
#[inline(always)]
fn component_mut<'b, C>(&'b self) -> RefMut<'b, C>
where
Self::Archetype: ArchetypeHas<C>
Self::Archetype: ArchetypeHas<C>,
{
<Self::Archetype as ArchetypeHas<C>>::resolve_extract_borrow_mut(self)
}
Expand Down
Loading

0 comments on commit 7f27b03

Please sign in to comment.