use crate::{Archetype, World}; use super::{AsQuery, Fetch, Query}; #[derive(Default)] pub struct OptionalFetcher<'a, Q: AsQuery> { fetcher: Option<::Fetch<'a>>, } impl<'a, Q: AsQuery> Fetch<'a> for OptionalFetcher<'a, Q> { type Item = Option<::Item<'a>>; fn dangling() -> Self { unreachable!() } unsafe fn get_item(&mut self, entity: crate::ArchetypeEntityId) -> Self::Item { self.fetcher.as_mut() .map(|f| f.get_item(entity)) } fn can_visit_item(&mut self, entity: crate::ArchetypeEntityId) -> bool { self.fetcher.as_mut() .map(|f| f.can_visit_item(entity)) .unwrap_or(true) } } #[derive(Default)] pub struct Optional { query: Q::Query, } impl Copy for Optional { } impl Clone for Optional { fn clone(&self) -> Self { Self { query: self.query.clone() } } } impl Query for Optional { type Item<'a> = Option<::Item<'a>>; type Fetch<'a> = OptionalFetcher<'a, Q>; fn new() -> Self { Optional { query: Q::Query::new(), } } fn can_visit_archetype(&self, _: &Archetype) -> bool { true } unsafe fn fetch<'a>(&self, world: &'a World, arch: &'a Archetype, tick: crate::Tick) -> Self::Fetch<'a> { let fetcher = if self.query.can_visit_archetype(arch) { Some(self.query.fetch(world, arch, tick)) } else { None }; OptionalFetcher { fetcher, } } } impl AsQuery for Optional { type Query = Self; } impl AsQuery for Option { type Query = Optional; }