Skip to content

Commit

Permalink
wip: QueryOne
Browse files Browse the repository at this point in the history
  • Loading branch information
ten3roberts committed Oct 11, 2023
1 parent c9928a2 commit dacb5e1
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 4 deletions.
2 changes: 0 additions & 2 deletions .env

This file was deleted.

7 changes: 6 additions & 1 deletion src/entity_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use crate::{
error::MissingComponent,
format::EntityFormatter,
name,
query::QueryOne,
writer::{EntityWriter, FnWriter, Missing, Replace, SingleComponentWriter, WriteDedup},
Component, ComponentKey, ComponentValue, Entity, RelationExt, World,
Component, ComponentKey, ComponentValue, Entity, Fetch, RelationExt, World,
};
use crate::{RelationIter, RelationIterMut};

Expand Down Expand Up @@ -106,6 +107,10 @@ impl<'a> EntityRefMut<'a> {
})
}

pub fn query_one<Q: Fetch<'a>>(&self, query: Q) -> Option<QueryOne<'a, Q>> {
todo!()
}

/// Attempt concurrently access a component mutably using and fail if the component is already borrowed
pub fn try_get<T: ComponentValue>(
&self,
Expand Down
63 changes: 63 additions & 0 deletions src/fetch/entity_access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use core::ops::Deref;

use atomic_refcell::AtomicRef;

use crate::{Component, ComponentValue, Entity, EntityIds, EntityRef, Mutable, RefMut};

use super::{copied::Copied, Cloned};

/// Generically access an entity in the world
pub trait EntityAccess<'a> {
/// The produced item
type Item;
/// Access the entity
fn get(&'a self, entity: &'a EntityRef) -> Option<Self::Item>;
}

impl<'a, T: ComponentValue> EntityAccess<'a> for Component<T> {
type Item = AtomicRef<'a, T>;

fn get(&self, entity: &'a EntityRef) -> Option<Self::Item> {
entity.get(*self).ok()
}
}

impl<'a, T: ComponentValue> EntityAccess<'a> for Mutable<T> {
type Item = RefMut<'a, T>;

fn get(&self, entity: &'a EntityRef) -> Option<Self::Item> {
entity.get_mut(self.0).ok()
}
}

impl<'a> EntityAccess<'a> for EntityIds {
type Item = Entity;

fn get(&'a self, entity: &'a EntityRef) -> Option<Self::Item> {
Some(entity.id())
}
}

impl<'a, T: EntityAccess<'a>, V> EntityAccess<'a> for Cloned<T>
where
T::Item: Deref<Target = V>,
V: 'a + Clone,
{
type Item = V;

fn get(&'a self, entity: &'a EntityRef) -> Option<Self::Item> {
Some(self.0.get(entity)?.clone())
}
}

impl<'a, T: EntityAccess<'a>, V> EntityAccess<'a> for Copied<T>
where
T::Item: Deref<Target = V>,
V: 'a + Copy,
{
type Item = V;

fn get(&'a self, entity: &'a EntityRef) -> Option<Self::Item> {
Some(*self.0.get(entity)?)
}
}
19 changes: 18 additions & 1 deletion src/fetch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod cloned;
mod component;
mod component_mut;
mod copied;
mod entity_access;
mod entity_ref;
mod ext;
mod map;
Expand All @@ -19,7 +20,7 @@ use crate::{
filter::{RefFetch, StaticFilter},
system::Access,
util::Ptr,
ArchetypeId, ArchetypeSearcher, Entity, World,
ArchetypeId, ArchetypeSearcher, Entity, EntityRef, World,
};
use alloc::vec::Vec;
use core::fmt::Debug;
Expand All @@ -29,6 +30,7 @@ pub use as_deref::*;
pub use cloned::*;
pub use component::*;
pub use component_mut::*;
pub use entity_access::EntityAccess;
pub use entity_ref::*;
pub use ext::FetchExt;
pub use map::Map;
Expand Down Expand Up @@ -347,6 +349,21 @@ macro_rules! tuple_impl {

}

impl<'q, $($ty, )*> EntityAccess<'q> for ($($ty,)*)
where $($ty: EntityAccess<'q>,)*
{
type Item = ($($ty::Item,)*);

fn get(&'q self, entity: &'q EntityRef) -> Option<Self::Item> {
Some(
($(
(self.$idx).get(entity)?,
)*)
)
}


}
impl<'q, $($ty, )*> RandomFetch<'q> for ($($ty,)*)
where $($ty: RandomFetch<'q>,)*
{
Expand Down
2 changes: 2 additions & 0 deletions src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod dfs;
mod difference;
mod entity;
mod iter;
mod one;
mod planar;
mod searcher;
mod topo;
Expand All @@ -28,6 +29,7 @@ pub use data::*;
pub use dfs::*;
pub use entity::EntityBorrow;
pub(crate) use iter::*;
pub use one::QueryOne;
pub use planar::*;
pub use searcher::ArchetypeSearcher;
pub use topo::{Topo, TopoBorrow, TopoIter};
Expand Down
45 changes: 45 additions & 0 deletions src/query/one.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use core::mem;

use crate::{
archetype::{Archetype, Slice},
entity::EntityLocation,
fetch::{FetchPrepareData, PreparedFetch},
EntityRef, Fetch, World,
};

pub struct QueryOne<'w, Q: Fetch<'w>> {
prepared: Q::Prepared,
item: <Q::Prepared as PreparedFetch<'static>>::Item,
}

impl<'w, Q: Fetch<'w>> QueryOne<'w, Q> {
pub(crate) fn new(
fetch: &'w Q,
world: &'w World,
arch: &'w Archetype,
loc: EntityLocation,
) -> Option<Self> {
let mut prepared = fetch.prepare(FetchPrepareData {
world,
arch,
arch_id: loc.arch_id,
old_tick: 0,
new_tick: world.advance_change_tick(),
})?;

let item = {
let mut chunk = unsafe { prepared.create_chunk(Slice::single(loc.slot)) };

unsafe { <Q::Prepared as PreparedFetch<'_>>::fetch_next(&mut chunk) }
};

let item = unsafe {
mem::transmute::<
<Q::Prepared as PreparedFetch<'_>>::Item,
<Q::Prepared as PreparedFetch<'static>>::Item,
>(item)
};

Some(Self { prepared, item })
}
}
19 changes: 19 additions & 0 deletions tests/entity_access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use flax::{component, name, Entity, World};

#[test]
fn entity_access() {
component! {
a: i32,
b: String,
}

let mut world = World::new();

let id = Entity::builder()
.set(name(), "a".into())
.set(a(), 5)
.set(b(), "Foo".into())
.spawn(&mut world);

let entity = world.entity(id).unwrap();
}

0 comments on commit dacb5e1

Please sign in to comment.