1use crate::stabletypeid::StableTypeId;
10use core::{
11 marker::PhantomData,
12 mem,
13 ops::{Deref, DerefMut},
14 ptr::NonNull,
15 slice::Iter as SliceIter,
16};
17
18use crate::{
19 alloc::{boxed::Box, vec::Vec},
20 archetype::Archetype,
21 entities::EntityMeta,
22 Component, Entity, World,
23};
24
25pub trait Query {
29 #[doc(hidden)]
30 type Fetch: for<'a> Fetch<'a>;
31}
32
33#[allow(clippy::missing_safety_doc)]
36pub unsafe trait QueryShared {}
37
38pub type QueryItem<'a, Q> = <<Q as Query>::Fetch as Fetch<'a>>::Item;
43
44#[allow(clippy::missing_safety_doc)]
46pub unsafe trait Fetch<'a>: Sized {
47 type Item;
49
50 type State: Copy;
53
54 fn dangling() -> Self;
56
57 fn access(archetype: &Archetype) -> Option<Access>;
59
60 fn borrow(archetype: &Archetype, state: Self::State);
62 fn prepare(archetype: &Archetype) -> Option<Self::State>;
64 fn execute(archetype: &'a Archetype, state: Self::State) -> Self;
66 fn release(archetype: &Archetype, state: Self::State);
68
69 fn for_each_borrow(f: impl FnMut(StableTypeId, bool));
72
73 unsafe fn get(&self, n: usize) -> Self::Item;
82}
83
84#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
86pub enum Access {
87 Iterate,
89 Read,
91 Write,
93}
94
95impl<T: Component> Query for &T {
96 type Fetch = FetchRead<T>;
97}
98
99unsafe impl<T> QueryShared for &T {}
100
101#[doc(hidden)]
102pub struct FetchRead<T>(NonNull<T>);
103
104unsafe impl<'a, T: Component> Fetch<'a> for FetchRead<T> {
105 type Item = &'a T;
106
107 type State = usize;
108
109 fn dangling() -> Self {
110 Self(NonNull::dangling())
111 }
112
113 fn access(archetype: &Archetype) -> Option<Access> {
114 if archetype.has::<T>() {
115 Some(Access::Read)
116 } else {
117 None
118 }
119 }
120
121 fn borrow(archetype: &Archetype, state: Self::State) {
122 archetype.borrow::<T>(state);
123 }
124 fn prepare(archetype: &Archetype) -> Option<Self::State> {
125 archetype.get_state::<T>()
126 }
127 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
128 Self(archetype.get_base(state))
129 }
130 fn release(archetype: &Archetype, state: Self::State) {
131 archetype.release::<T>(state);
132 }
133
134 fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
135 f(StableTypeId::of::<T>(), false);
136 }
137
138 unsafe fn get(&self, n: usize) -> Self::Item {
139 &*self.0.as_ptr().add(n)
140 }
141}
142
143pub struct Mut<'a, T: Component> {
145 pub(crate) value: &'a mut T,
146 pub(crate) mutated: &'a mut bool,
147}
148
149impl<'a, T: Component> Mut<'a, T> {
150 pub unsafe fn new(value: &'a mut T, mutated: &'a mut bool) -> Self {
156 Mut { value, mutated }
157 }
158}
159
160unsafe impl<T: Component> Send for Mut<'_, T> {}
161unsafe impl<T: Component> Sync for Mut<'_, T> {}
162
163impl<T: Component> Deref for Mut<'_, T> {
164 type Target = T;
165
166 #[inline]
167 fn deref(&self) -> &T {
168 self.value
169 }
170}
171
172impl<T: Component> DerefMut for Mut<'_, T> {
173 #[inline]
174 fn deref_mut(&mut self) -> &mut T {
175 *self.mutated = true;
176 self.value
177 }
178}
179
180impl<T: Component + core::fmt::Debug> core::fmt::Debug for Mut<'_, T> {
181 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182 self.value.fmt(f)
183 }
184}
185
186impl<T: Component> Query for &mut T {
187 type Fetch = FetchWrite<T>;
188}
189
190#[doc(hidden)]
191pub struct FetchWrite<T>(NonNull<T>, NonNull<bool>);
192
193unsafe impl<'a, T: Component> Fetch<'a> for FetchWrite<T> {
194 type Item = Mut<'a, T>;
195
196 type State = usize;
197
198 fn dangling() -> Self {
199 Self(NonNull::dangling(), NonNull::dangling())
200 }
201
202 fn access(archetype: &Archetype) -> Option<Access> {
203 if archetype.has::<T>() {
204 Some(Access::Write)
205 } else {
206 None
207 }
208 }
209
210 fn borrow(archetype: &Archetype, state: Self::State) {
211 archetype.borrow_mut::<T>(state);
212 }
213 #[allow(clippy::needless_question_mark)]
214 fn prepare(archetype: &Archetype) -> Option<Self::State> {
215 Some(archetype.get_state::<T>()?)
216 }
217 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
218 Self(archetype.get_base::<T>(state), archetype.get_mutated(state))
219 }
220 fn release(archetype: &Archetype, state: Self::State) {
221 archetype.release_mut::<T>(state);
222 }
223
224 fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
225 f(StableTypeId::of::<T>(), true);
226 }
227
228 unsafe fn get(&self, n: usize) -> Self::Item {
229 Mut::new(&mut *self.0.as_ptr().add(n), &mut *self.1.as_ptr().add(n))
230 }
231}
232
233impl<T: Query> Query for Option<T> {
234 type Fetch = TryFetch<T::Fetch>;
235}
236
237unsafe impl<T: QueryShared> QueryShared for Option<T> {}
238
239#[doc(hidden)]
240pub struct TryFetch<T>(Option<T>);
241
242unsafe impl<'a, T: Fetch<'a>> Fetch<'a> for TryFetch<T> {
243 type Item = Option<T::Item>;
244
245 type State = Option<T::State>;
246
247 fn dangling() -> Self {
248 Self(None)
249 }
250
251 fn access(archetype: &Archetype) -> Option<Access> {
252 Some(T::access(archetype).unwrap_or(Access::Iterate))
253 }
254
255 fn borrow(archetype: &Archetype, state: Self::State) {
256 if let Some(state) = state {
257 T::borrow(archetype, state);
258 }
259 }
260 fn prepare(archetype: &Archetype) -> Option<Self::State> {
261 Some(T::prepare(archetype))
262 }
263 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
264 Self(state.map(|state| T::execute(archetype, state)))
265 }
266 fn release(archetype: &Archetype, state: Self::State) {
267 if let Some(state) = state {
268 T::release(archetype, state);
269 }
270 }
271
272 fn for_each_borrow(f: impl FnMut(StableTypeId, bool)) {
273 T::for_each_borrow(f);
274 }
275
276 unsafe fn get(&self, n: usize) -> Option<T::Item> {
277 Some(self.0.as_ref()?.get(n))
278 }
279}
280
281#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
283pub enum Or<L, R> {
284 Left(L),
286 Right(R),
288 Both(L, R),
290}
291
292impl<L, R> Or<L, R> {
293 pub fn new(l: Option<L>, r: Option<R>) -> Option<Self> {
295 match (l, r) {
296 (None, None) => None,
297 (Some(l), None) => Some(Or::Left(l)),
298 (None, Some(r)) => Some(Or::Right(r)),
299 (Some(l), Some(r)) => Some(Or::Both(l, r)),
300 }
301 }
302
303 pub fn split(self) -> (Option<L>, Option<R>) {
305 match self {
306 Or::Left(l) => (Some(l), None),
307 Or::Right(r) => (None, Some(r)),
308 Or::Both(l, r) => (Some(l), Some(r)),
309 }
310 }
311
312 #[allow(clippy::match_wildcard_for_single_variants)]
314 pub fn left(self) -> Option<L> {
315 match self {
316 Or::Both(l, _) | Or::Left(l) => Some(l),
318 _ => None,
319 }
320 }
321
322 #[allow(clippy::match_wildcard_for_single_variants)]
324 pub fn right(self) -> Option<R> {
325 match self {
326 Or::Both(_, r) | Or::Right(r) => Some(r),
328 _ => None,
329 }
330 }
331
332 pub fn map<L1, R1, F, G>(self, f: F, g: G) -> Or<L1, R1>
334 where
335 F: FnOnce(L) -> L1,
336 G: FnOnce(R) -> R1,
337 {
338 match self {
339 Or::Left(l) => Or::Left(f(l)),
340 Or::Right(r) => Or::Right(g(r)),
341 Or::Both(l, r) => Or::Both(f(l), g(r)),
342 }
343 }
344
345 pub fn as_ref(&self) -> Or<&L, &R> {
347 match *self {
348 Or::Left(ref l) => Or::Left(l),
349 Or::Right(ref r) => Or::Right(r),
350 Or::Both(ref l, ref r) => Or::Both(l, r),
351 }
352 }
353
354 pub fn as_mut(&mut self) -> Or<&mut L, &mut R> {
356 match *self {
357 Or::Left(ref mut l) => Or::Left(l),
358 Or::Right(ref mut r) => Or::Right(r),
359 Or::Both(ref mut l, ref mut r) => Or::Both(l, r),
360 }
361 }
362}
363
364impl<L, R> Or<&'_ L, &'_ R>
365where
366 L: Clone,
367 R: Clone,
368{
369 pub fn cloned(self) -> Or<L, R> {
371 self.map(Clone::clone, Clone::clone)
372 }
373}
374
375impl<L: Query, R: Query> Query for Or<L, R> {
376 type Fetch = FetchOr<L::Fetch, R::Fetch>;
377}
378
379unsafe impl<L: QueryShared, R: QueryShared> QueryShared for Or<L, R> {}
380
381#[doc(hidden)]
382pub struct FetchOr<L, R>(Or<L, R>);
383
384unsafe impl<'a, L: Fetch<'a>, R: Fetch<'a>> Fetch<'a> for FetchOr<L, R> {
385 type Item = Or<L::Item, R::Item>;
386
387 type State = Or<L::State, R::State>;
388
389 fn dangling() -> Self {
390 Self(Or::Left(L::dangling()))
391 }
392
393 fn access(archetype: &Archetype) -> Option<Access> {
394 L::access(archetype).max(R::access(archetype))
395 }
396
397 fn borrow(archetype: &Archetype, state: Self::State) {
398 state.map(|l| L::borrow(archetype, l), |r| R::borrow(archetype, r));
399 }
400
401 fn prepare(archetype: &Archetype) -> Option<Self::State> {
402 Or::new(L::prepare(archetype), R::prepare(archetype))
403 }
404
405 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
406 Self(state.map(|l| L::execute(archetype, l), |r| R::execute(archetype, r)))
407 }
408
409 fn release(archetype: &Archetype, state: Self::State) {
410 state.map(|l| L::release(archetype, l), |r| R::release(archetype, r));
411 }
412
413 fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
414 L::for_each_borrow(&mut f);
415 R::for_each_borrow(&mut f);
416 }
417
418 unsafe fn get(&self, n: usize) -> Self::Item {
419 self.0.as_ref().map(|l| l.get(n), |r| r.get(n))
420 }
421}
422
423pub struct Without<Q, R>(PhantomData<(Q, fn(R))>);
442
443impl<Q: Query, R: Query> Query for Without<Q, R> {
444 type Fetch = FetchWithout<Q::Fetch, R::Fetch>;
445}
446
447unsafe impl<Q: QueryShared, R> QueryShared for Without<Q, R> {}
448
449#[doc(hidden)]
450pub struct FetchWithout<F, G>(F, PhantomData<fn(G)>);
451
452unsafe impl<'a, F: Fetch<'a>, G: Fetch<'a>> Fetch<'a> for FetchWithout<F, G> {
453 type Item = F::Item;
454
455 type State = F::State;
456
457 fn dangling() -> Self {
458 Self(F::dangling(), PhantomData)
459 }
460
461 fn access(archetype: &Archetype) -> Option<Access> {
462 if G::access(archetype).is_some() {
463 None
464 } else {
465 F::access(archetype)
466 }
467 }
468
469 fn borrow(archetype: &Archetype, state: Self::State) {
470 F::borrow(archetype, state);
471 }
472 fn prepare(archetype: &Archetype) -> Option<Self::State> {
473 if G::access(archetype).is_some() {
474 return None;
475 }
476 F::prepare(archetype)
477 }
478 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
479 Self(F::execute(archetype, state), PhantomData)
480 }
481 fn release(archetype: &Archetype, state: Self::State) {
482 F::release(archetype, state);
483 }
484
485 fn for_each_borrow(f: impl FnMut(StableTypeId, bool)) {
486 F::for_each_borrow(f);
487 }
488
489 unsafe fn get(&self, n: usize) -> F::Item {
490 self.0.get(n)
491 }
492}
493
494pub struct With<Q, R>(PhantomData<(Q, fn(R))>);
515
516impl<Q: Query, R: Query> Query for With<Q, R> {
517 type Fetch = FetchWith<Q::Fetch, R::Fetch>;
518}
519
520unsafe impl<Q: QueryShared, R> QueryShared for With<Q, R> {}
521
522#[doc(hidden)]
523pub struct FetchWith<F, G>(F, PhantomData<fn(G)>);
524
525unsafe impl<'a, F: Fetch<'a>, G: Fetch<'a>> Fetch<'a> for FetchWith<F, G> {
526 type Item = F::Item;
527
528 type State = F::State;
529
530 fn dangling() -> Self {
531 Self(F::dangling(), PhantomData)
532 }
533
534 fn access(archetype: &Archetype) -> Option<Access> {
535 if G::access(archetype).is_some() {
536 F::access(archetype)
537 } else {
538 None
539 }
540 }
541
542 fn borrow(archetype: &Archetype, state: Self::State) {
543 F::borrow(archetype, state);
544 }
545 fn prepare(archetype: &Archetype) -> Option<Self::State> {
546 G::access(archetype)?;
547 F::prepare(archetype)
548 }
549 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
550 Self(F::execute(archetype, state), PhantomData)
551 }
552 fn release(archetype: &Archetype, state: Self::State) {
553 F::release(archetype, state);
554 }
555
556 fn for_each_borrow(f: impl FnMut(StableTypeId, bool)) {
557 F::for_each_borrow(f);
558 }
559
560 unsafe fn get(&self, n: usize) -> F::Item {
561 self.0.get(n)
562 }
563}
564
565pub struct Satisfies<Q>(PhantomData<Q>);
589
590impl<Q: Query> Query for Satisfies<Q> {
591 type Fetch = FetchSatisfies<Q::Fetch>;
592}
593
594unsafe impl<Q> QueryShared for Satisfies<Q> {}
595
596#[doc(hidden)]
597pub struct FetchSatisfies<F>(bool, PhantomData<F>);
598
599unsafe impl<'a, F: Fetch<'a>> Fetch<'a> for FetchSatisfies<F> {
600 type Item = bool;
601
602 type State = bool;
603
604 fn dangling() -> Self {
605 Self(false, PhantomData)
606 }
607
608 fn access(_archetype: &Archetype) -> Option<Access> {
609 Some(Access::Iterate)
610 }
611
612 fn borrow(_archetype: &Archetype, _state: Self::State) {}
613 fn prepare(archetype: &Archetype) -> Option<Self::State> {
614 Some(F::prepare(archetype).is_some())
615 }
616 fn execute(_archetype: &'a Archetype, state: Self::State) -> Self {
617 Self(state, PhantomData)
618 }
619 fn release(_archetype: &Archetype, _state: Self::State) {}
620
621 fn for_each_borrow(_: impl FnMut(StableTypeId, bool)) {}
622
623 unsafe fn get(&self, _: usize) -> bool {
624 self.0
625 }
626}
627
628pub struct QueryBorrow<'w, Q: Query> {
632 meta: &'w [EntityMeta],
633 archetypes: &'w [Archetype],
634 borrowed: bool,
635 _marker: PhantomData<Q>,
636}
637
638impl<'w, Q: Query> QueryBorrow<'w, Q> {
639 pub(crate) fn new(meta: &'w [EntityMeta], archetypes: &'w [Archetype]) -> Self {
640 Self {
641 meta,
642 archetypes,
643 borrowed: false,
644 _marker: PhantomData,
645 }
646 }
647
648 pub fn iter(&mut self) -> QueryIter<'_, Q> {
651 self.borrow();
652 unsafe { QueryIter::new(self.meta, self.archetypes.iter()) }
653 }
654
655 pub fn view(&mut self) -> View<'_, Q> {
657 self.borrow();
658 unsafe { View::new(self.meta, self.archetypes) }
659 }
660
661 pub fn iter_batched(&mut self, batch_size: u32) -> BatchedIter<'_, Q> {
667 self.borrow();
668 unsafe { BatchedIter::new(self.meta, self.archetypes.iter(), batch_size) }
669 }
670
671 fn borrow(&mut self) {
672 if self.borrowed {
673 return;
674 }
675 for x in self.archetypes {
676 if x.is_empty() {
677 continue;
678 }
679 if let Some(state) = Q::Fetch::prepare(x) {
681 Q::Fetch::borrow(x, state);
682 }
683 }
684 self.borrowed = true;
685 }
686
687 pub fn with<R: Query>(self) -> QueryBorrow<'w, With<Q, R>> {
712 self.transform()
713 }
714
715 pub fn without<R: Query>(self) -> QueryBorrow<'w, Without<Q, R>> {
735 self.transform()
736 }
737
738 fn transform<R: Query>(mut self) -> QueryBorrow<'w, R> {
740 let x = QueryBorrow {
741 meta: self.meta,
742 archetypes: self.archetypes,
743 borrowed: self.borrowed,
744 _marker: PhantomData,
745 };
746 self.borrowed = false;
748 x
749 }
750}
751
752unsafe impl<'w, Q: Query> Send for QueryBorrow<'w, Q> where <Q::Fetch as Fetch<'w>>::Item: Send {}
753unsafe impl<'w, Q: Query> Sync for QueryBorrow<'w, Q> where <Q::Fetch as Fetch<'w>>::Item: Send {}
754
755impl<Q: Query> Drop for QueryBorrow<'_, Q> {
756 fn drop(&mut self) {
757 if self.borrowed {
758 for x in self.archetypes {
759 if x.is_empty() {
760 continue;
761 }
762 if let Some(state) = Q::Fetch::prepare(x) {
763 Q::Fetch::release(x, state);
764 }
765 }
766 }
767 }
768}
769
770#[allow(clippy::into_iter_without_iter)]
771impl<'q, Q: Query> IntoIterator for &'q mut QueryBorrow<'_, Q> {
772 type Item = (Entity, QueryItem<'q, Q>);
773 type IntoIter = QueryIter<'q, Q>;
774
775 fn into_iter(self) -> Self::IntoIter {
776 self.iter()
777 }
778}
779
780pub struct QueryIter<'q, Q: Query> {
782 meta: &'q [EntityMeta],
783 archetypes: SliceIter<'q, Archetype>,
784 iter: ChunkIter<Q>,
785}
786
787impl<'q, Q: Query> QueryIter<'q, Q> {
788 unsafe fn new(meta: &'q [EntityMeta], archetypes: SliceIter<'q, Archetype>) -> Self {
794 Self {
795 meta,
796 archetypes,
797 iter: ChunkIter::empty(),
798 }
799 }
800}
801
802unsafe impl<'q, Q: Query> Send for QueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
803unsafe impl<'q, Q: Query> Sync for QueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
804
805#[allow(clippy::inline_always)]
806impl<'q, Q: Query> Iterator for QueryIter<'q, Q> {
807 type Item = (Entity, QueryItem<'q, Q>);
808
809 #[inline(always)]
810 fn next(&mut self) -> Option<Self::Item> {
811 loop {
812 match unsafe { self.iter.next() } {
813 None => {
814 let archetype = self.archetypes.next()?;
815 let state = Q::Fetch::prepare(archetype);
816 let fetch = state.map(|state| Q::Fetch::execute(archetype, state));
817 self.iter = fetch.map_or(ChunkIter::empty(), |fetch| ChunkIter {
818 entities: archetype.entities(),
819 fetch,
820 position: 0,
821 len: archetype.len() as usize,
822 });
823 continue;
824 }
825 Some((id, components)) => {
826 return Some((
827 Entity {
828 id,
829 generation: unsafe { self.meta.get_unchecked(id as usize).generation },
830 },
831 components,
832 ));
833 }
834 }
835 }
836 }
837
838 fn size_hint(&self) -> (usize, Option<usize>) {
839 let n = self.len();
840 (n, Some(n))
841 }
842}
843
844impl<Q: Query> ExactSizeIterator for QueryIter<'_, Q> {
845 fn len(&self) -> usize {
846 self.archetypes
847 .clone()
848 .filter(|&x| Q::Fetch::access(x).is_some())
849 .map(|x| x.len() as usize)
850 .sum::<usize>()
851 + self.iter.remaining()
852 }
853}
854
855pub struct QueryMut<'q, Q: Query> {
857 iter: QueryIter<'q, Q>,
858}
859
860impl<'q, Q: Query> QueryMut<'q, Q> {
861 pub(crate) fn new(meta: &'q [EntityMeta], archetypes: &'q mut [Archetype]) -> Self {
862 assert_borrow::<Q>();
863
864 Self {
865 iter: unsafe { QueryIter::new(meta, archetypes.iter()) },
866 }
867 }
868
869 pub fn view(&mut self) -> View<'_, Q> {
871 unsafe { View::new(self.iter.meta, self.iter.archetypes.as_slice()) }
872 }
873
874 pub fn with<R: Query>(self) -> QueryMut<'q, With<Q, R>> {
878 self.transform()
879 }
880
881 pub fn without<R: Query>(self) -> QueryMut<'q, Without<Q, R>> {
885 self.transform()
886 }
887
888 fn transform<R: Query>(self) -> QueryMut<'q, R> {
890 QueryMut {
891 iter: unsafe { QueryIter::new(self.iter.meta, self.iter.archetypes) },
892 }
893 }
894
895 pub fn into_iter_batched(self, batch_size: u32) -> BatchedIter<'q, Q> {
900 unsafe { BatchedIter::new(self.iter.meta, self.iter.archetypes, batch_size) }
901 }
902}
903
904impl<'q, Q: Query> IntoIterator for QueryMut<'q, Q> {
905 type Item = <QueryIter<'q, Q> as Iterator>::Item;
906 type IntoIter = QueryIter<'q, Q>;
907
908 #[inline]
909 fn into_iter(self) -> Self::IntoIter {
910 self.iter
911 }
912}
913
914pub(crate) fn assert_borrow<Q: Query>() {
915 let mut i = 0;
918 Q::Fetch::for_each_borrow(|a, unique| {
919 if unique {
920 let mut j = 0;
921 Q::Fetch::for_each_borrow(|b, _| {
922 if i != j {
923 core::assert!(a != b, "query violates a unique borrow");
924 }
925 j += 1;
926 });
927 }
928 i += 1;
929 });
930}
931
932struct ChunkIter<Q: Query> {
933 entities: NonNull<u32>,
934 fetch: Q::Fetch,
935 position: usize,
936 len: usize,
937}
938
939impl<Q: Query> ChunkIter<Q> {
940 fn empty() -> Self {
941 Self {
942 entities: NonNull::dangling(),
943 fetch: Q::Fetch::dangling(),
944 position: 0,
945 len: 0,
946 }
947 }
948
949 #[inline]
950 unsafe fn next<'a>(&mut self) -> Option<(u32, <Q::Fetch as Fetch<'a>>::Item)> {
951 if self.position == self.len {
952 return None;
953 }
954 let entity = self.entities.as_ptr().add(self.position);
955 let item = self.fetch.get(self.position);
956 self.position += 1;
957 Some((*entity, item))
958 }
959
960 fn remaining(&self) -> usize {
961 self.len - self.position
962 }
963}
964
965pub struct BatchedIter<'q, Q: Query> {
967 _marker: PhantomData<&'q Q>,
968 meta: &'q [EntityMeta],
969 archetypes: SliceIter<'q, Archetype>,
970 batch_size: u32,
971 batch: u32,
972}
973
974impl<'q, Q: Query> BatchedIter<'q, Q> {
975 unsafe fn new(meta: &'q [EntityMeta], archetypes: SliceIter<'q, Archetype>, batch_size: u32) -> Self {
981 Self {
982 _marker: PhantomData,
983 meta,
984 archetypes,
985 batch_size,
986 batch: 0,
987 }
988 }
989}
990
991unsafe impl<'q, Q: Query> Send for BatchedIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
992unsafe impl<'q, Q: Query> Sync for BatchedIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
993
994impl<'q, Q: Query> Iterator for BatchedIter<'q, Q> {
995 type Item = Batch<'q, Q>;
996
997 fn next(&mut self) -> Option<Self::Item> {
998 loop {
999 let mut archetypes = self.archetypes.clone();
1000 let archetype = archetypes.next()?;
1001 let offset = self.batch_size * self.batch;
1002 if offset >= archetype.len() {
1003 self.archetypes = archetypes;
1004 self.batch = 0;
1005 continue;
1006 }
1007 let state = Q::Fetch::prepare(archetype);
1008 let fetch = state.map(|state| Q::Fetch::execute(archetype, state));
1009 if let Some(fetch) = fetch {
1010 self.batch += 1;
1011 return Some(Batch {
1012 meta: self.meta,
1013 state: ChunkIter {
1014 entities: archetype.entities(),
1015 fetch,
1016 len: (offset + self.batch_size.min(archetype.len() - offset)) as usize,
1017 position: offset as usize,
1018 },
1019 });
1020 }
1021 self.archetypes = archetypes;
1022 debug_assert_eq!(self.batch, 0, "query fetch should always reject at the first batch or not at all");
1023 }
1025 }
1026}
1027
1028pub struct Batch<'q, Q: Query> {
1030 meta: &'q [EntityMeta],
1031 state: ChunkIter<Q>,
1032}
1033
1034impl<'q, Q: Query> Iterator for Batch<'q, Q> {
1035 type Item = (Entity, QueryItem<'q, Q>);
1036
1037 fn next(&mut self) -> Option<Self::Item> {
1038 let (id, components) = unsafe { self.state.next()? };
1039 Some((
1040 Entity {
1041 id,
1042 generation: self.meta[id as usize].generation,
1043 },
1044 components,
1045 ))
1046 }
1047}
1048
1049unsafe impl<'q, Q: Query> Send for Batch<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1050unsafe impl<'q, Q: Query> Sync for Batch<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1051
1052macro_rules! tuple_impl {
1053 ($($name: ident),*) => {
1054 unsafe impl<'a, $($name: Fetch<'a>),*> Fetch<'a> for ($($name,)*) {
1055 type Item = ($($name::Item,)*);
1056
1057 type State = ($($name::State,)*);
1058
1059 #[allow(clippy::unused_unit)]
1060 fn dangling() -> Self {
1061 ($($name::dangling(),)*)
1062 }
1063
1064 #[allow(unused_variables, unused_mut)]
1065 fn access(archetype: &Archetype) -> Option<Access> {
1066 let mut access = Access::Iterate;
1067 $(
1068 access = access.max($name::access(archetype)?);
1069 )*
1070 Some(access)
1071 }
1072
1073 #[allow(unused_variables, non_snake_case, clippy::unused_unit)]
1074 fn borrow(archetype: &Archetype, state: Self::State) {
1075 let ($($name,)*) = state;
1076 $($name::borrow(archetype, $name);)*
1077 }
1078 #[allow(unused_variables)]
1079 fn prepare(archetype: &Archetype) -> Option<Self::State> {
1080 Some(($($name::prepare(archetype)?,)*))
1081 }
1082 #[allow(unused_variables, non_snake_case, clippy::unused_unit)]
1083 fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
1084 let ($($name,)*) = state;
1085 ($($name::execute(archetype, $name),)*)
1086 }
1087 #[allow(unused_variables, non_snake_case, clippy::unused_unit)]
1088 fn release(archetype: &Archetype, state: Self::State) {
1089 let ($($name,)*) = state;
1090 $($name::release(archetype, $name);)*
1091 }
1092
1093 #[allow(unused_variables, unused_mut, clippy::unused_unit)]
1094 fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
1095 $($name::for_each_borrow(&mut f);)*
1096 }
1097
1098 #[allow(unused_variables, clippy::unused_unit)]
1099 unsafe fn get(&self, n: usize) -> Self::Item {
1100 #[allow(non_snake_case)]
1101 let ($($name,)*) = self;
1102 ($($name.get(n),)*)
1103 }
1104 }
1105
1106 impl<$($name: Query),*> Query for ($($name,)*) {
1107 type Fetch = ($($name::Fetch,)*);
1108 }
1109
1110 unsafe impl<$($name: QueryShared),*> QueryShared for ($($name,)*) {}
1111 };
1112}
1113
1114smaller_tuples_too!(tuple_impl, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A);
1116
1117pub struct PreparedQuery<Q: Query> {
1120 memo: (u64, u32),
1121 state: Box<[(usize, <Q::Fetch as Fetch<'static>>::State)]>,
1122 fetch: Box<[Option<Q::Fetch>]>,
1123}
1124
1125impl<Q: Query> Default for PreparedQuery<Q> {
1126 fn default() -> Self {
1127 Self::new()
1128 }
1129}
1130
1131impl<Q: Query> PreparedQuery<Q> {
1132 pub fn new() -> Self {
1134 Self {
1135 memo: (0, 0),
1137 state: Box::default(),
1138 fetch: Box::default(),
1139 }
1140 }
1141
1142 #[cold]
1143 fn prepare(world: &World) -> Self {
1144 let memo = world.memo();
1145
1146 let state = world
1147 .archetypes()
1148 .enumerate()
1149 .filter_map(|(idx, x)| Q::Fetch::prepare(x).map(|state| (idx, state)))
1150 .collect();
1151
1152 let fetch = world.archetypes().map(|_| None).collect();
1153
1154 Self { memo, state, fetch }
1155 }
1156
1157 pub fn query<'q>(&'q mut self, world: &'q World) -> PreparedQueryBorrow<'q, Q> {
1162 if self.memo != world.memo() {
1163 *self = Self::prepare(world);
1164 }
1165
1166 let meta = world.entities_meta();
1167 let archetypes = world.archetypes_inner();
1168
1169 PreparedQueryBorrow::new(meta, archetypes, &self.state, &mut self.fetch)
1170 }
1171
1172 pub fn query_mut<'q>(&'q mut self, world: &'q mut World) -> PreparedQueryIter<'q, Q> {
1177 assert_borrow::<Q>();
1178
1179 if self.memo != world.memo() {
1180 *self = Self::prepare(world);
1181 }
1182
1183 let meta = world.entities_meta();
1184 let archetypes = world.archetypes_inner();
1185
1186 let state: &'q [(usize, <Q::Fetch as Fetch<'q>>::State)] = unsafe { mem::transmute(&*self.state) };
1187
1188 unsafe { PreparedQueryIter::new(meta, archetypes, state.iter()) }
1189 }
1190
1191 pub fn view_mut<'q>(&'q mut self, world: &'q mut World) -> PreparedView<'q, Q> {
1193 assert_borrow::<Q>();
1194
1195 if self.memo != world.memo() {
1196 *self = Self::prepare(world);
1197 }
1198
1199 let meta = world.entities_meta();
1200 let archetypes = world.archetypes_inner();
1201
1202 let state: &'q [(usize, <Q::Fetch as Fetch<'q>>::State)] = unsafe { mem::transmute(&*self.state) };
1203
1204 unsafe { PreparedView::new(meta, archetypes, state.iter(), &mut self.fetch) }
1205 }
1206}
1207
1208pub struct PreparedQueryBorrow<'q, Q: Query> {
1210 meta: &'q [EntityMeta],
1211 archetypes: &'q [Archetype],
1212 state: &'q [(usize, <Q::Fetch as Fetch<'static>>::State)],
1213 fetch: &'q mut [Option<Q::Fetch>],
1214}
1215
1216impl<'q, Q: Query> PreparedQueryBorrow<'q, Q> {
1217 fn new(
1218 meta: &'q [EntityMeta],
1219 archetypes: &'q [Archetype],
1220 state: &'q [(usize, <Q::Fetch as Fetch<'static>>::State)],
1221 fetch: &'q mut [Option<Q::Fetch>],
1222 ) -> Self {
1223 for (idx, state) in state {
1224 if archetypes[*idx].is_empty() {
1225 continue;
1226 }
1227 Q::Fetch::borrow(&archetypes[*idx], *state);
1228 }
1229
1230 Self {
1231 meta,
1232 archetypes,
1233 state,
1234 fetch,
1235 }
1236 }
1237
1238 pub fn iter<'i>(&'i mut self) -> PreparedQueryIter<'i, Q> {
1241 let state: &'i [(usize, <Q::Fetch as Fetch<'i>>::State)] = unsafe { mem::transmute(self.state) };
1242
1243 unsafe { PreparedQueryIter::new(self.meta, self.archetypes, state.iter()) }
1244 }
1245
1246 pub fn view<'i>(&'i mut self) -> PreparedView<'i, Q> {
1248 let state: &'i [(usize, <Q::Fetch as Fetch<'i>>::State)] = unsafe { mem::transmute(self.state) };
1249
1250 unsafe { PreparedView::new(self.meta, self.archetypes, state.iter(), self.fetch) }
1251 }
1252}
1253
1254impl<Q: Query> Drop for PreparedQueryBorrow<'_, Q> {
1255 fn drop(&mut self) {
1256 for (idx, state) in self.state {
1257 if self.archetypes[*idx].is_empty() {
1258 continue;
1259 }
1260 Q::Fetch::release(&self.archetypes[*idx], *state);
1261 }
1262 }
1263}
1264
1265pub struct PreparedQueryIter<'q, Q: Query> {
1267 meta: &'q [EntityMeta],
1268 archetypes: &'q [Archetype],
1269 state: SliceIter<'q, (usize, <Q::Fetch as Fetch<'q>>::State)>,
1270 iter: ChunkIter<Q>,
1271}
1272
1273impl<'q, Q: Query> PreparedQueryIter<'q, Q> {
1274 unsafe fn new(meta: &'q [EntityMeta], archetypes: &'q [Archetype], state: SliceIter<'q, (usize, <Q::Fetch as Fetch<'q>>::State)>) -> Self {
1280 Self {
1281 meta,
1282 archetypes,
1283 state,
1284 iter: ChunkIter::empty(),
1285 }
1286 }
1287}
1288
1289unsafe impl<'q, Q: Query> Send for PreparedQueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1290unsafe impl<'q, Q: Query> Sync for PreparedQueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1291
1292#[allow(clippy::inline_always)]
1293impl<'q, Q: Query> Iterator for PreparedQueryIter<'q, Q> {
1294 type Item = (Entity, QueryItem<'q, Q>);
1295
1296 #[inline(always)]
1297 fn next(&mut self) -> Option<Self::Item> {
1298 loop {
1299 match unsafe { self.iter.next() } {
1300 None => {
1301 let (idx, state) = self.state.next()?;
1302 let archetype = &self.archetypes[*idx];
1303 self.iter = ChunkIter {
1304 entities: archetype.entities(),
1305 fetch: Q::Fetch::execute(archetype, *state),
1306 position: 0,
1307 len: archetype.len() as usize,
1308 };
1309 continue;
1310 }
1311 Some((id, components)) => {
1312 return Some((
1313 Entity {
1314 id,
1315 generation: unsafe { self.meta.get_unchecked(id as usize).generation },
1316 },
1317 components,
1318 ));
1319 }
1320 }
1321 }
1322 }
1323
1324 fn size_hint(&self) -> (usize, Option<usize>) {
1325 let n = self.len();
1326 (n, Some(n))
1327 }
1328}
1329
1330impl<Q: Query> ExactSizeIterator for PreparedQueryIter<'_, Q> {
1331 fn len(&self) -> usize {
1332 self.state.clone().map(|(idx, _)| self.archetypes[*idx].len() as usize).sum::<usize>() + self.iter.remaining()
1333 }
1334}
1335
1336pub struct View<'q, Q: Query> {
1338 meta: &'q [EntityMeta],
1339 fetch: Vec<Option<Q::Fetch>>,
1340}
1341
1342unsafe impl<'q, Q: Query> Send for View<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1343unsafe impl<'q, Q: Query> Sync for View<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1344
1345impl<'q, Q: Query> View<'q, Q> {
1346 unsafe fn new(meta: &'q [EntityMeta], archetypes: &'q [Archetype]) -> Self {
1352 let fetch = archetypes
1353 .iter()
1354 .map(|archetype| Q::Fetch::prepare(archetype).map(|state| Q::Fetch::execute(archetype, state)))
1355 .collect();
1356
1357 Self { meta, fetch }
1358 }
1359
1360 pub fn get(&self, entity: Entity) -> Option<QueryItem<'_, Q>>
1368 where
1369 Q: QueryShared,
1370 {
1371 let meta = self.meta.get(entity.id as usize)?;
1372 if meta.generation != entity.generation {
1373 return None;
1374 }
1375
1376 self.fetch[meta.location.archetype as usize]
1377 .as_ref()
1378 .map(|fetch| unsafe { fetch.get(meta.location.index as usize) })
1379 }
1380
1381 pub fn get_mut(&mut self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1386 unsafe { self.get_unchecked(entity) }
1387 }
1388
1389 pub unsafe fn get_unchecked(&self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1396 let meta = self.meta.get(entity.id as usize)?;
1397 if meta.generation != entity.generation {
1398 return None;
1399 }
1400
1401 self.fetch[meta.location.archetype as usize]
1402 .as_ref()
1403 .map(|fetch| fetch.get(meta.location.index as usize))
1404 }
1405
1406 pub fn get_mut_n<const N: usize>(&mut self, entities: [Entity; N]) -> [Option<QueryItem<'_, Q>>; N] {
1431 assert_distinct(&entities);
1432
1433 let mut items = [(); N].map(|()| None);
1434
1435 for (item, entity) in items.iter_mut().zip(entities) {
1436 unsafe {
1437 *item = self.get_unchecked(entity);
1438 }
1439 }
1440
1441 items
1442 }
1443}
1444
1445pub struct PreparedView<'q, Q: Query> {
1447 meta: &'q [EntityMeta],
1448 fetch: &'q mut [Option<Q::Fetch>],
1449}
1450
1451unsafe impl<'q, Q: Query> Send for PreparedView<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1452unsafe impl<'q, Q: Query> Sync for PreparedView<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1453
1454impl<'q, Q: Query> PreparedView<'q, Q> {
1455 unsafe fn new(
1461 meta: &'q [EntityMeta],
1462 archetypes: &'q [Archetype],
1463 state: SliceIter<'q, (usize, <Q::Fetch as Fetch<'q>>::State)>,
1464 fetch: &'q mut [Option<Q::Fetch>],
1465 ) -> Self {
1466 fetch.iter_mut().for_each(|fetch| *fetch = None);
1467
1468 for (idx, state) in state {
1469 let archetype = &archetypes[*idx];
1470 fetch[*idx] = Some(Q::Fetch::execute(archetype, *state));
1471 }
1472
1473 Self { meta, fetch }
1474 }
1475
1476 pub fn get(&self, entity: Entity) -> Option<QueryItem<'_, Q>>
1484 where
1485 Q: QueryShared,
1486 {
1487 let meta = self.meta.get(entity.id as usize)?;
1488 if meta.generation != entity.generation {
1489 return None;
1490 }
1491
1492 self.fetch[meta.location.archetype as usize]
1493 .as_ref()
1494 .map(|fetch| unsafe { fetch.get(meta.location.index as usize) })
1495 }
1496
1497 pub fn get_mut(&mut self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1502 unsafe { self.get_unchecked(entity) }
1503 }
1504
1505 pub unsafe fn get_unchecked(&self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1512 let meta = self.meta.get(entity.id as usize)?;
1513 if meta.generation != entity.generation {
1514 return None;
1515 }
1516
1517 self.fetch[meta.location.archetype as usize]
1518 .as_ref()
1519 .map(|fetch| fetch.get(meta.location.index as usize))
1520 }
1521
1522 pub fn get_mut_n<const N: usize>(&mut self, entities: [Entity; N]) -> [Option<QueryItem<'_, Q>>; N] {
1527 assert_distinct(&entities);
1528
1529 let mut items = [(); N].map(|()| None);
1530
1531 for (item, entity) in items.iter_mut().zip(entities) {
1532 unsafe {
1533 *item = self.get_unchecked(entity);
1534 }
1535 }
1536
1537 items
1538 }
1539}
1540
1541fn assert_distinct<const N: usize>(entities: &[Entity; N]) {
1542 match N {
1543 1 => (),
1544 2 => assert_ne!(entities[0], entities[1]),
1545 3 => {
1546 assert_ne!(entities[0], entities[1]);
1547 assert_ne!(entities[1], entities[2]);
1548 assert_ne!(entities[2], entities[0]);
1549 }
1550 _ => {
1551 let mut entities = *entities;
1552 entities.sort_unstable();
1553 for index in 0..N - 1 {
1554 assert_ne!(entities[index], entities[index + 1]);
1555 }
1556 }
1557 }
1558}
1559#[cfg(test)]
1560mod tests {
1561 use super::*;
1562
1563 #[test]
1564 fn access_order() {
1565 assert!(Access::Write > Access::Read);
1566 assert!(Access::Read > Access::Iterate);
1567 assert!(Some(Access::Iterate) > None);
1568 }
1569}