Skip to content

Commit

Permalink
Removing BorrowHas and making borrows also operate on ArchetypeHas, s…
Browse files Browse the repository at this point in the history
…ame as View
  • Loading branch information
recatek committed Jan 22, 2025
1 parent e1223aa commit 04ab9bc
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 84 deletions.
6 changes: 3 additions & 3 deletions macros/src/generate/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,13 +535,13 @@ fn iter_bind_borrow(param: &ParseQueryParam) -> TokenStream {
}
}
ParseQueryParamType::Entity(_) => {
quote!(&archetype.get_slice_entities()[idx])
quote!(&archetype.entities()[idx])
}
ParseQueryParamType::EntityAny => {
quote!(&archetype.get_slice_entities()[idx].into())
quote!(&archetype.entities()[idx].into())
}
ParseQueryParamType::EntityWild => {
quote!(&archetype.get_slice_entities()[idx])
quote!(&archetype.entities()[idx])
}
ParseQueryParamType::EntityDirect(_) => {
quote!(&::gecs::__internal::new_entity_direct::<MatchedArchetype>(idx, version))
Expand Down
54 changes: 18 additions & 36 deletions macros/src/generate/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,8 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
let StorageN = format_ident!("Storage{}", count_str);
let BorrowN = format_ident!("Borrow{}", count_str);

let IterArgs = quote!((&'a Entity<#Archetype>, #(&'a #Component,)*));
let IterMutArgs = quote!((&'a Entity<#Archetype>, #(&'a mut #Component,)*));
let IterItem = quote!((&'a Entity<#Archetype>, #(&'a #Component,)*));
let IterItemMut = quote!((&'a Entity<#Archetype>, #(&'a mut #Component,)*));

// Function names
let get_slice = (0..count)
Expand Down Expand Up @@ -773,12 +773,13 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
const ARCHETYPE_ID: u8 = #ARCHETYPE_ID;

type Components = #ArchetypeComponents;

type IterItem<'a> = #IterItem;
type IterItemMut<'a> = #IterItemMut;

type Slices<'a> = #ArchetypeSlices<'a>;
type View<'a> = #ArchetypeView<'a>;
type Borrow<'a> = #ArchetypeBorrow<'a>;
type Slices<'a> = #ArchetypeSlices<'a>;

type IterArgs<'a> = #IterArgs;
type IterMutArgs<'a> = #IterMutArgs;

// Will only appear if we have the events feature enabled.
#section_events
Expand Down Expand Up @@ -835,24 +836,19 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
}

#[inline(always)]
fn iter(&mut self) -> impl Iterator<Item = Self::IterArgs<'_>> {
fn iter(&mut self) -> impl Iterator<Item = Self::IterItem<'_>> {
self.data.iter()
}

#[inline(always)]
fn iter_mut(&mut self) -> impl Iterator<Item = Self::IterMutArgs<'_>> {
fn iter_mut(&mut self) -> impl Iterator<Item = Self::IterItemMut<'_>> {
self.data.iter_mut()
}

#[inline(always)]
fn get_all_slices_mut(&mut self) -> #ArchetypeSlices {
self.data.get_all_slices_mut()
}

#[inline(always)]
fn get_slice_entities(&self) -> &[Entity<#Archetype>] {
self.data.get_slice_entities()
}
}

#(
Expand Down Expand Up @@ -880,13 +876,13 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
}

#[inline(always)]
fn resolve_borrow_component<'a>(borrow: &'a #ArchetypeBorrow<'a>) -> Ref<'a, #Component> {
borrow.0.#borrow_component()
fn resolve_extract_components(components: &Self::Components) -> &#Component {
&components.#component
}

#[inline(always)]
fn resolve_borrow_component_mut<'a>(borrow: &'a #ArchetypeBorrow<'a>) -> RefMut<'a, #Component> {
borrow.0.#borrow_component_mut()
fn resolve_extract_components_mut(components: &mut Self::Components) -> &mut #Component {
&mut components.#component
}

#[inline(always)]
Expand All @@ -900,13 +896,13 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
}

#[inline(always)]
fn resolve_extract_components(components: &Self::Components) -> &#Component {
&components.#component
fn resolve_extract_borrow<'a>(borrow: &'a Self::Borrow<'_>) -> Ref<'a, #Component> {
borrow.0.#borrow_component()
}

#[inline(always)]
fn resolve_extract_components_mut(components: &mut Self::Components) -> &mut #Component {
&mut components.#component
fn resolve_extract_borrow_mut<'a>(borrow: &'a Self::Borrow<'_>) -> RefMut<'a, #Component> {
borrow.0.#borrow_component_mut()
}
}
)*
Expand Down Expand Up @@ -1040,7 +1036,7 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
#[derive(Clone, Copy)]
pub struct #ArchetypeBorrow<'a>(#BorrowN<'a, #Archetype, #(#Component),*>);

impl<'a> Borrow for #ArchetypeBorrow<'a> {
impl<'a> Borrow<'a> for #ArchetypeBorrow<'a> {
type Archetype = #Archetype;

#[inline(always)]
Expand All @@ -1054,20 +1050,6 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
}
}

#(
impl<'a> BorrowHas<#Component> for #ArchetypeBorrow<'a> {
#[inline(always)]
fn resolve_component(&self) -> Ref<#Component> {
#Archetype::resolve_borrow_component(self)
}

#[inline(always)]
fn resolve_component_mut(&self) -> RefMut<#Component> {
#Archetype::resolve_borrow_component_mut(self)
}
}
)*

impl ArchetypeCanResolve<Entity<#Archetype>> for #Archetype {
#[inline(always)]
fn resolve_for(&self, entity: Entity<#Archetype>) -> Option<usize> {
Expand Down
8 changes: 2 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,9 +793,7 @@ pub mod prelude {

pub use traits::{World, WorldHas};
pub use traits::{Archetype, ArchetypeHas};
pub use traits::Components;
pub use traits::{View};
pub use traits::{Borrow, BorrowHas};
pub use traits::{Components, View, Borrow};
}

#[doc(hidden)]
Expand Down Expand Up @@ -830,7 +828,5 @@ pub mod __internal {

pub use traits::{World, WorldHas};
pub use traits::{Archetype, ArchetypeHas};
pub use traits::Components;
pub use traits::{View};
pub use traits::{Borrow, BorrowHas};
pub use traits::{Components, View, Borrow};
}
59 changes: 25 additions & 34 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,28 +314,28 @@ where
/// A struct with named storage to each component in this archetype.
type Components: Components<Archetype = Self>;

/// The slices type when accessing all of this archetype's slices simultaneously.
type Slices<'a>
/// A struct yielded by iterators on this archetype, including the entity itself.
type IterItem<'a>
where
Self: 'a;

/// The borrow type when performing sequential borrows of an entity's components.
type Borrow<'a>: Borrow
/// A struct yielded by mut iterators on this archetype, including the entity itself.
type IterItemMut<'a>
where
Self: 'a;

/// The view type when accessing a single entity's components simultaneously.
type View<'a>: View<'a, Archetype = Self>
/// The slices type when accessing all of this archetype's slices simultaneously.
type Slices<'a>
where
Self: 'a;

/// The arguments (references to components) when iterating.
type IterArgs<'a>
/// The borrow type when performing sequential borrows of an entity's components.
type Borrow<'a>: Borrow<'a, Archetype = Self>
where
Self: 'a;

/// The arguments (mutable references to components) when mutably iterating.
type IterMutArgs<'a>
/// The view type when accessing a single entity's components simultaneously.
type View<'a>: View<'a, Archetype = Self>
where
Self: 'a;

Expand Down Expand Up @@ -390,10 +390,10 @@ where
) -> Result<Entity<Self>, Self::Components>;

/// Returns an iterator over all of the entities and their data.
fn iter(&mut self) -> impl Iterator<Item = Self::IterArgs<'_>>;
fn iter(&mut self) -> impl Iterator<Item = Self::IterItem<'_>>;

/// Returns a mutable iterator over all of the entities and their data.
fn iter_mut(&mut self) -> impl Iterator<Item = Self::IterMutArgs<'_>>;
fn iter_mut(&mut self) -> impl Iterator<Item = Self::IterItemMut<'_>>;

/// Returns mutable slices to all data for all entities in the archetype. To get the
/// data index for a specific entity using this function, use the `resolve` function.
Expand Down Expand Up @@ -627,9 +627,6 @@ where
/// See [`Archetype::iter_created`].
#[cfg(feature = "events")]
fn clear_events(&mut self);

#[doc(hidden)]
fn get_slice_entities(&self) -> &[Entity<Self>];
}

/// A trait promising that an ECS world has the given archetype.
Expand Down Expand Up @@ -730,18 +727,19 @@ pub trait ArchetypeHas<C>: Archetype {
fn resolve_borrow_slice(&self) -> Ref<[C]>;
#[doc(hidden)]
fn resolve_borrow_slice_mut(&self) -> RefMut<[C]>;

#[doc(hidden)]
fn resolve_borrow_component<'a>(borrow: &'a Self::Borrow<'a>) -> Ref<'a, C>;
fn resolve_extract_components(components: &Self::Components) -> &C;
#[doc(hidden)]
fn resolve_borrow_component_mut<'a>(borrow: &'a Self::Borrow<'a>) -> RefMut<'a, C>;
fn resolve_extract_components_mut(components: &mut Self::Components) -> &mut C;
#[doc(hidden)]
fn resolve_extract_view<'a>(view: &'a Self::View<'_>) -> &'a C;
#[doc(hidden)]
fn resolve_extract_view_mut<'a>(view: &'a mut Self::View<'_>) -> &'a mut C;
#[doc(hidden)]
fn resolve_extract_components(components: &Self::Components) -> &C;
fn resolve_extract_borrow<'a>(borrow: &'a Self::Borrow<'_>) -> Ref<'a, C>;
#[doc(hidden)]
fn resolve_extract_components_mut(components: &mut Self::Components) -> &mut C;
fn resolve_extract_borrow_mut<'a>(borrow: &'a Self::Borrow<'_>) -> RefMut<'a, C>;
}

pub trait Components {
Expand Down Expand Up @@ -808,8 +806,8 @@ pub trait View<'a> {
///
/// The `Borrow` trait should be implemented only by the `ecs_world!` macro.
/// This is not intended for manual implementation by any user data structures.
pub trait Borrow {
type Archetype: Archetype;
pub trait Borrow<'a> {
type Archetype: Archetype<Borrow<'a> = Self> + 'a;

/// Returns the archetype dense index that this borrow refers to.
fn index(&self) -> usize;
Expand All @@ -824,11 +822,11 @@ pub trait Borrow {
/// Panics if any other borrow has exclusive/mut access to any entry for this type of component
/// within this same archetype, even if it is for a different entity.
#[inline(always)]
fn component<C>(&self) -> Ref<C>
fn component<'b, C>(&'b self) -> Ref<'b, C>
where
Self: BorrowHas<C>,
Self::Archetype: ArchetypeHas<C>
{
<Self as BorrowHas<C>>::resolve_component(self)
<Self::Archetype as ArchetypeHas<C>>::resolve_extract_borrow(self)
}

/// Gets the given component mutably from this borrow. Performs a runtime check for safety.
Expand All @@ -838,21 +836,14 @@ pub trait Borrow {
/// Panics if any other borrow has any type of access to any entry for this type of component
/// within this same archetype, even if it is for a different entity.
#[inline(always)]
fn component_mut<C>(&self) -> RefMut<C>
fn component_mut<'b, C>(&'b self) -> RefMut<'b, C>
where
Self: BorrowHas<C>,
Self::Archetype: ArchetypeHas<C>
{
<Self as BorrowHas<C>>::resolve_component_mut(self)
<Self::Archetype as ArchetypeHas<C>>::resolve_extract_borrow_mut(self)
}
}

pub trait BorrowHas<C>: Borrow {
#[doc(hidden)]
fn resolve_component(&self) -> Ref<C>;
#[doc(hidden)]
fn resolve_component_mut(&self) -> RefMut<C>;
}

/// Trait promising that a given ECS world can resolve a type of entity key.
///
/// This is implemented for [`Entity`], [`EntityDirect`]. [`EntityAny`], and [`EntityDirectAny`].
Expand Down
52 changes: 47 additions & 5 deletions tests/test_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ use gecs::prelude::*;

pub struct CompA(pub u32);
pub struct CompB(pub u32);
pub struct CompC(pub u32);

ecs_world! {
ecs_archetype!(
ArchFoo,
CompA,
CompB,
);
ecs_archetype!(ArchFoo, CompA, CompB);
ecs_archetype!(ArchBar, CompA, CompC);
}

#[test]
Expand Down Expand Up @@ -37,6 +35,32 @@ pub fn test_generic_view_get() {
assert_eq!(view.component::<CompB>().0, 2);
}

#[test]
pub fn test_generic_borrow() {
let mut world = EcsWorld::new();

let entity = world.create::<ArchFoo>((CompA(1), CompB(1)));

let mut borrow = world.borrow(entity).unwrap();
borrow_increment(&mut borrow);

assert_eq!(borrow.component::<CompA>().0, 2);
assert_eq!(borrow.component::<CompB>().0, 2);
}

#[test]
pub fn test_generic_borrow_get() {
let mut world = EcsWorld::new();

let entity = world.create::<ArchFoo>((CompA(1), CompB(1)));

borrow_get_increment(&mut world, entity);

let borrow = world.borrow(entity).unwrap();
assert_eq!(borrow.component::<CompA>().0, 2);
assert_eq!(borrow.component::<CompB>().0, 2);
}

fn view_increment<'a, V: View<'a>>(view: &mut V)
where
V::Archetype: ArchetypeHas<CompA> + ArchetypeHas<CompB>,
Expand All @@ -54,3 +78,21 @@ where
view.component_mut::<CompA>().0 += 1;
view.component_mut::<CompB>().0 += 1;
}

fn borrow_increment<'a, B: Borrow<'a>>(borrow: &mut B)
where
B::Archetype: ArchetypeHas<CompA> + ArchetypeHas<CompB>,
{
borrow.component_mut::<CompA>().0 += 1;
borrow.component_mut::<CompB>().0 += 1;
}

fn borrow_get_increment<W, A>(world: &mut W, entity: Entity<A>)
where
W: WorldHas<A>,
A: ArchetypeHas<CompA> + ArchetypeHas<CompB>,
{
let borrow = world.borrow(entity).unwrap();
borrow.component_mut::<CompA>().0 += 1;
borrow.component_mut::<CompB>().0 += 1;
}

0 comments on commit 04ab9bc

Please sign in to comment.