1use std::{
2 any::{Any, TypeId},
3 collections::HashSet,
4 marker::PhantomData,
5};
6
7use crate::bundle::BundleMeta;
8#[allow(unused_imports)]
9use crate::{bundle::Bundle, tools::WorldFetch};
10pub trait WorldFilter: Any {
14 fn filter(components_ids: &'static [TypeId]) -> bool;
19
20 fn filter_by_meta(meta: &mut BundleMeta) -> bool;
24}
25
26#[derive(Debug, Clone, Copy)]
28pub struct All<B: Bundle>(PhantomData<B>);
29
30#[derive(Debug, Clone, Copy)]
32pub struct AnyOf<B: Bundle>(PhantomData<B>);
33
34#[derive(Debug, Clone, Copy)]
36pub struct Not<B: Bundle>(PhantomData<B>);
37
38impl<B: Bundle> WorldFilter for All<B> {
39 fn filter(components_ids: &'static [TypeId]) -> bool {
40 let set = B::components_ids()
41 .iter()
42 .copied()
43 .fold(HashSet::new(), |mut set, id| {
44 set.insert(id);
45 set
46 });
47 !components_ids.iter().any(|id| !set.contains(id))
48 }
49
50 fn filter_by_meta(meta: &mut BundleMeta) -> bool {
51 meta.filter::<Self>()
52 }
53}
54
55impl<B: Bundle> WorldFilter for AnyOf<B> {
56 fn filter(components_ids: &'static [TypeId]) -> bool {
57 let set = B::components_ids()
58 .iter()
59 .copied()
60 .fold(HashSet::new(), |mut set, id| {
61 set.insert(id);
62 set
63 });
64 components_ids.iter().any(|id| set.contains(id))
65 }
66
67 fn filter_by_meta(meta: &mut BundleMeta) -> bool {
68 meta.filter::<Self>()
69 }
70}
71
72impl<B: Bundle> WorldFilter for Not<B> {
73 fn filter(components_ids: &'static [TypeId]) -> bool {
74 let set = B::components_ids()
75 .iter()
76 .copied()
77 .fold(HashSet::new(), |mut set, id| {
78 set.insert(id);
79 set
80 });
81 !components_ids.iter().any(|id| set.contains(id))
82 }
83
84 fn filter_by_meta(meta: &mut BundleMeta) -> bool {
85 meta.filter::<Self>()
86 }
87}
88
89mod __impl {
90 use super::{BundleMeta, TypeId, WorldFilter};
91 macro_rules! impl_filter {
92 ($($t:ident),*) => {
93 impl<$($t:WorldFilter),*> WorldFilter for ($($t,)*) {
94 fn filter(components_ids : &'static [TypeId]) -> bool{
95 $($t::filter(components_ids))&&*
96 }
97
98 fn filter_by_meta(meta: &mut BundleMeta) -> bool {
99 $($t::filter_by_meta(meta))&&*
100 }
101 }
102 };
103 }
104
105 trecs_proc::all_tuple!(impl_filter, 16);
106
107 impl WorldFilter for () {
108 fn filter(_: &'static [TypeId]) -> bool {
109 true
110 }
111
112 fn filter_by_meta(_meta: &mut BundleMeta) -> bool {
113 true
114 }
115 }
116}