use std::marker::PhantomData;
use crate::entity::EntityId;
use crate::world::World;
pub trait WorldQuery {
type Item<'w>;
fn fetch(world: &World, id: EntityId) -> Option<Self::Item<'_>>;
fn contains(world: &World, id: EntityId) -> bool;
}
pub struct Ext<T>(PhantomData<T>);
pub struct ExtMut<T>(PhantomData<T>);
impl WorldQuery for EntityId {
type Item<'w> = Self;
fn fetch(_world: &World, id: EntityId) -> Option<Self::Item<'_>> {
Some(id)
}
fn contains(_world: &World, _id: EntityId) -> bool {
true
}
}
macro_rules! impl_builtin_query {
($comp:ty, $field:ident) => {
impl WorldQuery for &$comp {
type Item<'w> = &'w $comp;
fn fetch(world: &World, id: EntityId) -> Option<Self::Item<'_>> {
world.$field.get(id)
}
fn contains(world: &World, id: EntityId) -> bool {
world.$field.contains_key(id)
}
}
impl WorldQuery for Option<&$comp> {
type Item<'w> = Option<&'w $comp>;
fn fetch(world: &World, id: EntityId) -> Option<Self::Item<'_>> {
Some(world.$field.get(id))
}
fn contains(_world: &World, _id: EntityId) -> bool {
true
}
}
};
}
impl_builtin_query!(crate::components::Position, positions);
impl_builtin_query!(crate::components::Velocity, velocities);
impl_builtin_query!(crate::components::Elevator, elevators);
impl_builtin_query!(crate::components::Stop, stops);
impl_builtin_query!(crate::components::Rider, riders);
impl_builtin_query!(crate::components::Route, routes);
impl_builtin_query!(crate::components::Line, lines);
impl_builtin_query!(crate::components::Patience, patience);
impl_builtin_query!(crate::components::Preferences, preferences);
impl<T: 'static + Send + Sync> WorldQuery for &Ext<T> {
type Item<'w> = &'w T;
fn fetch(world: &World, id: EntityId) -> Option<Self::Item<'_>> {
world.ext_map::<T>()?.get(id)
}
fn contains(world: &World, id: EntityId) -> bool {
world.ext_map::<T>().is_some_and(|m| m.contains_key(id))
}
}
macro_rules! impl_tuple_query {
($($name:ident),+) => {
#[allow(non_snake_case)]
impl<$($name: WorldQuery),+> WorldQuery for ($($name,)+) {
type Item<'w> = ($($name::Item<'w>,)+);
fn fetch(world: &World, id: EntityId) -> Option<Self::Item<'_>> {
Some(($($name::fetch(world, id)?,)+))
}
fn contains(world: &World, id: EntityId) -> bool {
$($name::contains(world, id) &&)+ true
}
}
};
}
impl_tuple_query!(A);
impl_tuple_query!(A, B);
impl_tuple_query!(A, B, C);
impl_tuple_query!(A, B, C, D);
impl_tuple_query!(A, B, C, D, E);
impl_tuple_query!(A, B, C, D, E, F);
impl_tuple_query!(A, B, C, D, E, F, G);
impl_tuple_query!(A, B, C, D, E, F, G, H);