1use crate::{
2 archetype::{Archetype, Slice},
3 fetch::{FetchAccessData, FetchPrepareData, FmtQuery, PreparedFetch, UnionFilter},
4 filter::StaticFilter,
5 system::Access,
6 Fetch, FetchItem,
7};
8use alloc::vec::Vec;
9use core::{
10 fmt::{self, Formatter},
11 ops,
12};
13
14#[derive(Debug, Clone)]
21pub struct And<L, R>(pub L, pub R);
22
23impl<'q, L, R> FetchItem<'q> for And<L, R>
24where
25 L: FetchItem<'q>,
26 R: FetchItem<'q>,
27{
28 type Item = (L::Item, R::Item);
29}
30
31impl<'w, L, R> Fetch<'w> for And<L, R>
32where
33 L: Fetch<'w>,
34 R: Fetch<'w>,
35{
36 const MUTABLE: bool = false;
37
38 type Prepared = And<L::Prepared, R::Prepared>;
39
40 #[inline]
41 fn prepare(&'w self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
42 Some(And(self.0.prepare(data)?, self.1.prepare(data)?))
43 }
44
45 fn filter_arch(&self, data: FetchAccessData) -> bool {
46 self.0.filter_arch(data) && self.1.filter_arch(data)
47 }
48
49 fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
50 self.0.access(data, dst);
51 self.1.access(data, dst);
52 }
53
54 fn describe(&self, f: &mut Formatter<'_>) -> fmt::Result {
55 self.0.describe(f)?;
56 f.write_str(" & ")?;
57 self.1.describe(f)?;
58
59 Ok(())
60 }
61
62 fn searcher(&self, searcher: &mut crate::ArchetypeSearcher) {
63 self.0.searcher(searcher);
64 self.1.searcher(searcher);
65 }
66}
67
68impl<'q, L, R> PreparedFetch<'q> for And<L, R>
69where
70 L: PreparedFetch<'q>,
71 R: PreparedFetch<'q>,
72{
73 type Item = (L::Item, R::Item);
74 type Chunk = (L::Chunk, R::Chunk);
75
76 const HAS_FILTER: bool = L::HAS_FILTER || R::HAS_FILTER;
77
78 #[inline]
79 unsafe fn filter_slots(&mut self, slots: Slice) -> Slice {
80 let l = self.0.filter_slots(slots);
81
82 self.1.filter_slots(l)
83 }
84
85 unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk {
86 (self.0.create_chunk(slots), self.1.create_chunk(slots))
87 }
88
89 #[inline]
90 unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item {
91 (L::fetch_next(&mut chunk.0), R::fetch_next(&mut chunk.1))
92 }
93}
94
95#[derive(Debug, Clone)]
96pub struct Or<T>(pub T);
98
99#[derive(Debug, Clone)]
100pub struct Not<T>(pub T);
102
103impl<'q, T> FetchItem<'q> for Not<T> {
104 type Item = ();
105}
106
107impl<'w, T> Fetch<'w> for Not<T>
108where
109 T: Fetch<'w>,
110{
111 const MUTABLE: bool = true;
112
113 type Prepared = Not<Option<T::Prepared>>;
114
115 fn prepare(&'w self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
116 Some(Not(self.0.prepare(data)))
117 }
118
119 fn filter_arch(&self, data: FetchAccessData) -> bool {
120 !self.0.filter_arch(data)
121 }
122
123 #[inline]
124 fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
125 self.0.access(data, dst)
126 }
127
128 fn describe(&self, f: &mut Formatter<'_>) -> fmt::Result {
129 write!(f, "!{:?}", FmtQuery(&self.0))
130 }
131}
132
133impl<'q, F> PreparedFetch<'q> for Not<Option<F>>
134where
135 F: PreparedFetch<'q>,
136{
137 type Item = ();
138 type Chunk = ();
139
140 const HAS_FILTER: bool = F::HAS_FILTER;
141
142 #[inline]
143 unsafe fn filter_slots(&mut self, slots: Slice) -> Slice {
144 if let Some(fetch) = &mut self.0 {
145 let v = fetch.filter_slots(slots);
146
147 slots.difference(v).unwrap()
148 } else {
149 slots
150 }
151 }
152
153 #[inline]
154 unsafe fn create_chunk(&'q mut self, _: Slice) -> Self::Chunk {}
155
156 #[inline]
157 unsafe fn fetch_next(_: &mut Self::Chunk) -> Self::Item {}
158}
159
160impl<R, T> ops::BitOr<R> for Not<T> {
161 type Output = Or<(Self, R)>;
162
163 fn bitor(self, rhs: R) -> Self::Output {
164 Or((self, rhs))
165 }
166}
167
168impl<R, T> ops::BitAnd<R> for Not<T> {
169 type Output = (Self, R);
170
171 fn bitand(self, rhs: R) -> Self::Output {
172 (self, rhs)
173 }
174}
175
176impl<T> ops::Not for Not<T> {
177 type Output = T;
178
179 fn not(self) -> Self::Output {
180 self.0
181 }
182}
183
184#[derive(Debug, Clone)]
196pub struct Union<T>(pub T);
197
198impl<'q, T> FetchItem<'q> for Union<T>
199where
200 T: FetchItem<'q>,
201{
202 type Item = T::Item;
203}
204
205impl<'w, T> Fetch<'w> for Union<T>
206where
207 T: Fetch<'w>,
208 T::Prepared: UnionFilter,
209{
210 const MUTABLE: bool = T::MUTABLE;
211
212 type Prepared = Union<T::Prepared>;
213
214 fn prepare(&'w self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
215 Some(Union(self.0.prepare(data)?))
216 }
217
218 fn filter_arch(&self, data: FetchAccessData) -> bool {
219 self.0.filter_arch(data)
220 }
221
222 fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
223 self.0.access(data, dst)
224 }
225
226 fn describe(&self, f: &mut Formatter<'_>) -> fmt::Result {
227 f.debug_tuple("Union").field(&FmtQuery(&self.0)).finish()
228 }
229}
230
231impl<T> UnionFilter for Union<T>
232where
233 T: UnionFilter,
234{
235 const HAS_UNION_FILTER: bool = T::HAS_UNION_FILTER;
236
237 unsafe fn filter_union(&mut self, slots: Slice) -> Slice {
238 self.0.filter_union(slots)
239 }
240}
241
242impl<'q, T> PreparedFetch<'q> for Union<T>
243where
244 T: PreparedFetch<'q> + UnionFilter,
245{
246 type Item = T::Item;
247 const HAS_FILTER: bool = T::HAS_UNION_FILTER;
248
249 #[inline]
250 unsafe fn filter_slots(&mut self, slots: Slice) -> Slice {
251 self.filter_union(slots)
252 }
253
254 type Chunk = T::Chunk;
255
256 #[inline]
257 unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk {
258 self.0.create_chunk(slots)
259 }
260
261 #[inline]
262 unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item {
263 T::fetch_next(chunk)
264 }
265}
266
267macro_rules! tuple_impl {
268 ($($idx: tt => $ty: ident),*) => {
269 impl<'w, 'q, $($ty, )*> FetchItem<'q> for Or<($($ty,)*)> {
271 type Item = ();
272 }
273
274 impl<'w, $($ty, )*> Fetch<'w> for Or<($($ty,)*)>
275 where $($ty: Fetch<'w>,)*
276 {
277 const MUTABLE: bool = $($ty::MUTABLE )||*;
278 type Prepared = Or<($(Option<$ty::Prepared>,)*)>;
279
280 fn prepare(&'w self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
281 let inner = &self.0;
282 Some( Or(($(inner.$idx.prepare(data),)*)) )
283 }
284
285 fn filter_arch(&self, data: FetchAccessData) -> bool {
286 let inner = &self.0;
287 $(inner.$idx.filter_arch(data))||*
288 }
289
290 fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
291 $(self.0.$idx.access(data, dst);)*
292 }
293
294 fn describe(&self, f: &mut Formatter<'_>) -> fmt::Result {
295 let mut s = f.debug_tuple("Or");
296 let inner = &self.0;
297 $(
298 s.field(&FmtQuery(&inner.$idx));
299 )*
300 s.finish()
301 }
302 }
303
304 impl<$($ty: StaticFilter, )*> StaticFilter for Or<($($ty,)*)> {
305 fn filter_static(&self, arch: &Archetype) -> bool {
306 let inner = &self.0;
307 $(inner.$idx.filter_static(arch))||*
308 }
309 }
310
311 impl<'w, 'q, $($ty, )*> PreparedFetch<'q> for Or<($(Option<$ty>,)*)>
312 where 'w: 'q, $($ty: PreparedFetch<'q>,)*
313 {
314 type Item = ();
315 type Chunk = ();
316
317 const HAS_FILTER: bool = $($ty::HAS_FILTER )&&*;
319
320 unsafe fn filter_slots(&mut self, slots: Slice) -> Slice {
321 let inner = &mut self.0;
322 let end = Slice::new(slots.end, slots.end);
323
324 [
325 $( inner.$idx.as_mut().map(|v| v.filter_slots(slots)).unwrap_or(end)),*
326 ]
327 .into_iter()
328 .min()
329 .unwrap_or_default()
330
331 }
332
333 #[inline]
334 unsafe fn fetch_next(_: &mut Self::Chunk) -> Self::Item {}
335
336 #[inline]
337 unsafe fn create_chunk(&mut self, _: Slice) -> Self::Chunk {}
338
339 }
340
341 impl<'q, $($ty, )*> UnionFilter for Or<($(Option<$ty>,)*)>
342 where $($ty: PreparedFetch<'q>,)*
343 {
344 const HAS_UNION_FILTER: bool = $($ty::HAS_FILTER )&&*;
345
346 unsafe fn filter_union(&mut self, slots: Slice) -> Slice {
347 let inner = &mut self.0;
348 let end = Slice::new(slots.end, slots.end);
349
350 [
351 $( inner.$idx.as_mut().map(|v| v.filter_slots(slots)).unwrap_or(end)),*
352 ]
353 .into_iter()
354 .min()
355 .unwrap_or_default()
356 }
357 }
358 };
359
360
361}
362
363tuple_impl! { 0 => A }
364tuple_impl! { 0 => A, 1 => B }
365tuple_impl! { 0 => A, 1 => B, 2 => C }
366tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D }
367tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E }
368tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E, 5 => F }
369tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E, 5 => F, 6 => H }
370
371#[cfg(test)]
372mod tests {
373 use itertools::Itertools;
374
375 use crate::filter::{FilterIter, Nothing};
376
377 use super::*;
378
379 #[test]
380 fn union() {
381 let fetch = Union((
382 Slice::new(0, 2),
383 Nothing,
384 Slice::new(7, 16),
385 Slice::new(3, 10),
386 ));
387
388 let fetch = FilterIter::new(Slice::new(0, 100), fetch);
389
390 assert_eq!(
391 fetch.collect_vec(),
392 [Slice::new(0, 2), Slice::new(3, 10), Slice::new(10, 16)]
393 );
394 }
395}