geng_ecs/
filter.rs

1use super::*;
2
3pub trait Filter {
4    type Fetch: for<'a> Fetch<'a>;
5    fn fetch(self) -> Self::Fetch;
6    unsafe fn get_world<'a>(
7        fetch: &Self::Fetch,
8        borrows: &<Self::Fetch as Fetch<'a>>::WorldBorrows,
9        id: Id,
10    ) -> bool;
11    unsafe fn get<'a>(
12        fetch: &Self::Fetch,
13        borrows: &<Self::Fetch as Fetch<'a>>::DirectBorrows,
14    ) -> bool;
15}
16
17pub trait FetchBool {
18    type Fetch: for<'a> Fetch<'a, Output = bool>;
19    fn fetch(self) -> Self::Fetch;
20}
21
22impl<T: FetchBool> Filter for T {
23    type Fetch = <T as FetchBool>::Fetch;
24
25    fn fetch(self) -> Self::Fetch {
26        <T as FetchBool>::fetch(self)
27    }
28
29    unsafe fn get_world<'a>(
30        fetch: &Self::Fetch,
31        borrows: &<Self::Fetch as Fetch<'a>>::WorldBorrows,
32        id: Id,
33    ) -> bool {
34        fetch.get_world(borrows, id).unwrap()
35    }
36
37    unsafe fn get<'a>(
38        fetch: &Self::Fetch,
39        borrows: &<Self::Fetch as Fetch<'a>>::DirectBorrows,
40    ) -> bool {
41        fetch.get(borrows)
42    }
43}
44
45impl<F: for<'a> Fetch<'a, Output = bool>> FetchBool for F {
46    type Fetch = Self;
47    fn fetch(self) -> Self {
48        self
49    }
50}
51
52#[derive(Default)]
53pub struct Is<F>(pub F);
54
55impl<F: Filter> FetchBool for Is<F> {
56    type Fetch = FilterFetch<F>;
57    fn fetch(self) -> Self::Fetch {
58        FilterFetch(self.0.fetch())
59    }
60}
61
62#[derive(Default)]
63pub struct And<A, B>(pub A, pub B);
64
65unsafe impl<'a, A: Fetch<'a, Output = bool>, B: Fetch<'a, Output = bool>> Fetch<'a> for And<A, B> {
66    type Output = bool;
67    type WorldBorrows = (A::WorldBorrows, B::WorldBorrows);
68    unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
69        Some((self.0.borrow_world(world)?, self.1.borrow_world(world)?))
70    }
71    unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output> {
72        Some(self.0.get_world(&borrows.0, id)? && self.1.get_world(&borrows.1, id)?)
73    }
74    type DirectBorrows = (A::DirectBorrows, B::DirectBorrows);
75    unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
76        Some((self.0.borrow_direct(entity)?, self.1.borrow_direct(entity)?))
77    }
78    unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output {
79        self.0.get(&borrows.0) && self.1.get(&borrows.1)
80    }
81}
82
83impl<A: Filter, B: Filter> std::ops::BitAnd<Is<B>> for Is<A> {
84    type Output = Is<And<A, B>>;
85
86    fn bitand(self, rhs: Is<B>) -> Self::Output {
87        Is(And(self.0, rhs.0))
88    }
89}
90
91#[derive(Default)]
92pub struct Or<A, B>(pub A, pub B);
93
94unsafe impl<'a, A: Fetch<'a, Output = bool>, B: Fetch<'a, Output = bool>> Fetch<'a> for Or<A, B> {
95    type Output = bool;
96    type WorldBorrows = (A::WorldBorrows, B::WorldBorrows);
97    unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
98        Some((self.0.borrow_world(world)?, self.1.borrow_world(world)?))
99    }
100    unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output> {
101        Some(self.0.get_world(&borrows.0, id)? || self.1.get_world(&borrows.1, id)?)
102    }
103    type DirectBorrows = (A::DirectBorrows, B::DirectBorrows);
104    unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
105        Some((self.0.borrow_direct(entity)?, self.1.borrow_direct(entity)?))
106    }
107    unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output {
108        self.0.get(&borrows.0) || self.1.get(&borrows.1)
109    }
110}
111
112impl<A: Filter, B: Filter> std::ops::BitOr<Is<B>> for Is<A> {
113    type Output = Is<Or<A, B>>;
114
115    fn bitor(self, rhs: Is<B>) -> Self::Output {
116        Is(Or(self.0, rhs.0))
117    }
118}
119
120pub struct With<T>(PhantomData<T>);
121
122pub fn with<T: Component>() -> Is<With<T>> {
123    Is(With::default())
124}
125
126impl<T> Default for With<T> {
127    fn default() -> Self {
128        Self(PhantomData)
129    }
130}
131
132unsafe impl<'a, T: Component> Fetch<'a> for With<T> {
133    type Output = bool;
134    type WorldBorrows = Option<storage::world::Borrow<'a, T>>;
135    unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
136        Some(world.borrow::<T>())
137    }
138    unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<bool> {
139        if let Some(borrows) = borrows {
140            Some(borrows.get(id).is_some())
141        } else {
142            Some(false)
143        }
144    }
145    type DirectBorrows = &'a Entity;
146    unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
147        Some(entity)
148    }
149    unsafe fn get(&self, borrows: &Self::DirectBorrows) -> bool {
150        borrows.has::<T>()
151    }
152}
153
154#[derive(Default)]
155pub struct Not<F>(F);
156
157unsafe impl<'a, F: Fetch<'a, Output = bool>> Fetch<'a> for Not<F> {
158    type Output = bool;
159    type WorldBorrows = F::WorldBorrows;
160    unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
161        self.0.borrow_world(world)
162    }
163    unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<bool> {
164        Some(!self.0.get_world(borrows, id)?)
165    }
166    type DirectBorrows = F::DirectBorrows;
167    unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
168        self.0.borrow_direct(entity)
169    }
170    unsafe fn get(&self, borrows: &Self::DirectBorrows) -> bool {
171        !self.0.get(borrows)
172    }
173}
174
175impl<A: Filter> std::ops::Not for Is<A> {
176    type Output = Is<Not<A>>;
177    fn not(self) -> Self::Output {
178        Is(Not(self.0))
179    }
180}
181
182pub type Without<T> = Not<With<T>>;
183
184pub fn without<T: Component>() -> Is<Without<T>> {
185    Is(Without::default())
186}
187
188pub struct Equal<T>(pub T);
189
190pub fn equal<T>(value: T) -> Is<Equal<T>> {
191    Is(Equal(value))
192}
193
194unsafe impl<'a, T: Component + PartialEq> Fetch<'a> for Equal<T> {
195    type Output = bool;
196    type WorldBorrows = <FetchRead<T> as Fetch<'a>>::WorldBorrows;
197    unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
198        <FetchRead<T> as Fetch<'a>>::borrow_world(&FetchRead::default(), world)
199    }
200    unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output> {
201        borrows.get(id).map(|value| *value == self.0)
202    }
203    type DirectBorrows = <FetchRead<T> as Fetch<'a>>::DirectBorrows;
204    unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
205        <FetchRead<T> as Fetch<'a>>::borrow_direct(&FetchRead::default(), entity)
206    }
207    unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output {
208        *borrows.get() == self.0
209    }
210}
211
212macro_rules! impl_for_tuple {
213    ($($name:ident),*) => {
214        #[allow(non_camel_case_types)]
215        #[allow(unused_variables)]
216        #[allow(clippy::unused_unit)]
217        impl<$($name: Filter),*> Filter for ($($name,)*) {
218            type Fetch = ($($name::Fetch,)*);
219            fn fetch(self) -> Self::Fetch {
220                let ($($name,)*) = self;
221                ($($name.fetch(),)*)
222            }
223            unsafe fn get_world<'a>(fetch: &Self::Fetch, borrows: &<Self::Fetch as Fetch<'a>>::WorldBorrows, id: Id) -> bool {
224                let ($($name,)*) = ZipExt::zip(fetch.as_ref(), borrows.as_ref());
225                $(
226                    let (fetch, borrows) = $name;
227                    if !<$name as Filter>::get_world(fetch, borrows, id) {
228                        return false;
229                    }
230                )*
231                true
232            }
233            unsafe fn get<'a>(fetch: &Self::Fetch, borrows: &<Self::Fetch as Fetch<'a>>::DirectBorrows) -> bool {
234                let ($($name,)*) = ZipExt::zip(fetch.as_ref(), borrows.as_ref());
235                $(
236                    let (fetch, borrows) = $name;
237                    if !<$name as Filter>::get(fetch, borrows) {
238                        return false;
239                    }
240                )*
241                true
242            }
243        }
244    };
245}
246
247impl_tuples!(impl_for_tuple);