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);