use crate::stabletypeid::StableTypeId;
use core::{marker::PhantomData, ptr::NonNull};
use crate::{Access, Archetype, Component, Fetch, Query};
pub struct Mutated<T>(PhantomData<fn(T)>);
impl<T: Component> Query for Mutated<T> {
type Fetch = FetchMutated<T>;
}
#[doc(hidden)]
pub struct FetchMutated<T>(NonNull<bool>, PhantomData<fn(T)>);
unsafe impl<'a, T: Component> Fetch<'a> for FetchMutated<T> {
type Item = bool;
type State = usize;
fn dangling() -> Self {
Self(NonNull::dangling(), PhantomData)
}
fn access(archetype: &Archetype) -> Option<Access> {
if archetype.has::<T>() {
Some(Access::Read)
} else {
None
}
}
fn borrow(_archetype: &Archetype, _state: Self::State) {}
fn prepare(archetype: &Archetype) -> Option<Self::State> {
archetype.get_state::<T>()
}
fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
Self(archetype.get_mutated(state), PhantomData)
}
fn release(_archetype: &Archetype, _state: Self::State) {}
fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
f(StableTypeId::of::<T>(), false);
}
unsafe fn get(&self, n: usize) -> Self::Item {
*self.0.as_ptr().add(n)
}
}
pub struct Added<T>(PhantomData<fn(T)>);
impl<T: Component> Query for Added<T> {
type Fetch = FetchAdded<T>;
}
#[doc(hidden)]
pub struct FetchAdded<T>(NonNull<bool>, PhantomData<fn(T)>);
unsafe impl<'a, T: Component> Fetch<'a> for FetchAdded<T> {
type Item = bool;
type State = usize;
fn dangling() -> Self {
Self(NonNull::dangling(), PhantomData)
}
fn access(archetype: &Archetype) -> Option<Access> {
if archetype.has::<T>() {
Some(Access::Read)
} else {
None
}
}
fn borrow(_archetype: &Archetype, _state: Self::State) {}
fn prepare(archetype: &Archetype) -> Option<Self::State> {
archetype.get_state::<T>()
}
fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
Self(archetype.get_added(state), PhantomData)
}
fn release(_archetype: &Archetype, _state: Self::State) {}
fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
f(StableTypeId::of::<T>(), false);
}
unsafe fn get(&self, n: usize) -> Self::Item {
*self.0.as_ptr().add(n)
}
}
pub struct Changed<T>(PhantomData<fn(T)>);
impl<T: Component> Query for Changed<T> {
type Fetch = FetchChanged<T>;
}
#[doc(hidden)]
pub struct FetchChanged<T>(NonNull<bool>, NonNull<bool>, PhantomData<fn(T)>);
unsafe impl<'a, T: Component> Fetch<'a> for FetchChanged<T> {
type Item = bool;
type State = usize;
fn dangling() -> Self {
Self(NonNull::dangling(), NonNull::dangling(), PhantomData)
}
fn access(archetype: &Archetype) -> Option<Access> {
if archetype.has::<T>() {
Some(Access::Read)
} else {
None
}
}
fn borrow(_archetype: &Archetype, _state: Self::State) {}
fn prepare(archetype: &Archetype) -> Option<Self::State> {
archetype.get_state::<T>()
}
fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
Self(archetype.get_mutated(state), archetype.get_added(state), PhantomData)
}
fn release(_archetype: &Archetype, _state: Self::State) {}
fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
f(StableTypeId::of::<T>(), false);
}
unsafe fn get(&self, n: usize) -> Self::Item {
*self.0.as_ptr().add(n) || *self.1.as_ptr().add(n)
}
}