1use alloc::rc::Rc;
2use core::{any::TypeId, fmt::Debug, iter::FusedIterator, marker::PhantomData, ptr::NonNull};
3
4use crate::{
5 archetype::Archetype,
6 component::{BorrowFn, BorrowFnMut, ComponentInfo},
7 epoch::EpochId,
8 query::{
9 read::Read, Access, AsQuery, DefaultQuery, Fetch, ImmutableQuery, IntoQuery, Query,
10 SendQuery, Write, WriteAlias,
11 },
12 system::QueryArg,
13 type_id,
14};
15
16#[derive(Clone, Copy, Debug, Default)]
18pub struct QueryBorrowAll<T>(pub T);
19
20struct FetchBorrowAllComponent<T: ?Sized> {
21 ptr: NonNull<u8>,
22 size: usize,
23 borrow_fn: BorrowFn<T>,
24 borrow_mut_fn: Option<BorrowFnMut<T>>,
25 entity_epochs: NonNull<EpochId>,
26 chunk_epochs: NonNull<EpochId>,
27}
28
29impl<T> Clone for FetchBorrowAllComponent<T>
30where
31 T: ?Sized,
32{
33 #[inline(always)]
34 fn clone(&self) -> Self {
35 *self
36 }
37}
38
39impl<T> Copy for FetchBorrowAllComponent<T> where T: ?Sized {}
40
41pub struct BorrowAllRead<'a, T: ?Sized> {
42 idx: u32,
43 comp_idx: usize,
44 components: Rc<[FetchBorrowAllComponent<T>]>,
45 marker: PhantomData<&'a T>,
46}
47
48impl<'a, T> Clone for BorrowAllRead<'a, T>
49where
50 T: ?Sized,
51{
52 #[inline(always)]
53 fn clone(&self) -> Self {
54 BorrowAllRead {
55 idx: self.idx,
56 comp_idx: self.comp_idx,
57 components: self.components.clone(),
58 marker: self.marker,
59 }
60 }
61
62 #[inline(always)]
63 fn clone_from(&mut self, source: &Self) {
64 self.idx = source.idx;
65 self.comp_idx = source.comp_idx;
66 self.components = source.components.clone();
67 }
68}
69
70impl<'a, T> Debug for BorrowAllRead<'a, T>
71where
72 T: Debug + ?Sized,
73{
74 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
75 f.debug_list().entries(self.clone()).finish()
76 }
77}
78
79impl<'a, T> Iterator for BorrowAllRead<'a, T>
80where
81 T: ?Sized,
82{
83 type Item = &'a T;
84
85 #[inline(always)]
86 fn size_hint(&self) -> (usize, Option<usize>) {
87 let len = self.len();
88 (len, Some(len))
89 }
90
91 #[inline(always)]
92 fn next(&mut self) -> Option<&'a T> {
93 let c = &self.components.get(self.comp_idx)?;
94 let r = unsafe {
95 (c.borrow_fn)(
96 NonNull::new_unchecked(c.ptr.as_ptr().add(self.idx as usize * c.size)),
97 self.marker,
98 )
99 };
100 self.comp_idx += 1;
101 Some(r)
102 }
103
104 #[inline(always)]
105 fn nth(&mut self, n: usize) -> Option<&'a T> {
106 if n >= self.components.len() - self.comp_idx {
107 self.comp_idx = self.components.len();
108 } else {
109 self.comp_idx += n;
110 }
111 self.next()
112 }
113
114 fn fold<B, F>(mut self, init: B, mut f: F) -> B
115 where
116 Self: Sized,
117 F: FnMut(B, &'a T) -> B,
118 {
119 let mut accum = init;
120 for comp_idx in self.comp_idx..self.components.len() {
121 let c = &self.components[comp_idx];
122 let r = unsafe {
123 (c.borrow_fn)(
124 NonNull::new_unchecked(c.ptr.as_ptr().add(self.idx as usize * c.size)),
125 self.marker,
126 )
127 };
128 self.comp_idx += 1;
129 accum = f(accum, r);
130 }
131 accum
132 }
133}
134
135impl<'a, T> ExactSizeIterator for BorrowAllRead<'a, T>
136where
137 T: ?Sized,
138{
139 #[inline(always)]
140 fn len(&self) -> usize {
141 self.components.len() - self.comp_idx
142 }
143}
144
145impl<'a, T> FusedIterator for BorrowAllRead<'a, T> where T: ?Sized {}
146
147pub struct FetchBorrowAllRead<'a, T: ?Sized> {
149 components: Rc<[FetchBorrowAllComponent<T>]>,
150 marker: PhantomData<&'a T>,
151}
152
153unsafe impl<'a, T> Fetch<'a> for FetchBorrowAllRead<'a, T>
154where
155 T: ?Sized + 'a,
156{
157 type Item = BorrowAllRead<'a, T>;
158
159 #[inline(always)]
160 fn dangling() -> Self {
161 FetchBorrowAllRead {
162 components: Rc::new([]),
163 marker: PhantomData,
164 }
165 }
166
167 #[inline(always)]
168 unsafe fn get_item(&mut self, idx: u32) -> BorrowAllRead<'a, T> {
169 BorrowAllRead {
170 idx,
171 comp_idx: 0,
172 components: self.components.clone(),
173 marker: self.marker,
174 }
175 }
176}
177
178impl<T> AsQuery for QueryBorrowAll<&T>
179where
180 T: ?Sized + 'static,
181{
182 type Query = QueryBorrowAll<Read<T>>;
183}
184
185impl<T> DefaultQuery for QueryBorrowAll<&T>
186where
187 T: ?Sized + 'static,
188{
189 #[inline(always)]
190 fn default_query() -> QueryBorrowAll<Read<T>> {
191 QueryBorrowAll(Read)
192 }
193}
194
195impl<T> AsQuery for QueryBorrowAll<Read<T>>
196where
197 T: ?Sized + 'static,
198{
199 type Query = Self;
200}
201
202impl<T> IntoQuery for QueryBorrowAll<Read<T>>
203where
204 T: ?Sized + 'static,
205{
206 #[inline(always)]
207 fn into_query(self) -> Self {
208 self
209 }
210}
211
212impl<T> DefaultQuery for QueryBorrowAll<Read<T>>
213where
214 T: ?Sized + 'static,
215{
216 #[inline(always)]
217 fn default_query() -> Self {
218 QueryBorrowAll(Read)
219 }
220}
221
222impl<T> QueryArg for QueryBorrowAll<Read<T>>
223where
224 T: Sync + ?Sized + 'static,
225{
226 #[inline(always)]
227 fn new() -> Self {
228 QueryBorrowAll(Read)
229 }
230}
231
232unsafe impl<T> Query for QueryBorrowAll<Read<T>>
233where
234 T: ?Sized + 'static,
235{
236 type Item<'a> = BorrowAllRead<'a, T>;
237 type Fetch<'a> = FetchBorrowAllRead<'a, T>;
238
239 const MUTABLE: bool = false;
240
241 #[inline(always)]
242 fn component_access(&self, comp: &ComponentInfo) -> Result<Option<Access>, WriteAlias> {
243 if comp.has_borrow(type_id::<T>()) {
244 Ok(Some(Access::Read))
245 } else {
246 Ok(None)
247 }
248 }
249
250 #[inline(always)]
251 fn visit_archetype(&self, archetype: &Archetype) -> bool {
252 archetype.contains_borrow(type_id::<T>())
253 }
254
255 #[inline(always)]
256 unsafe fn access_archetype(&self, archetype: &Archetype, mut f: impl FnMut(TypeId, Access)) {
257 let indices = unsafe { archetype.borrow_indices(type_id::<T>()).unwrap_unchecked() };
258 for (id, _) in indices {
259 f(*id, Access::Read);
260 }
261 }
262
263 #[inline(always)]
264 unsafe fn fetch<'a>(
265 &self,
266 _arch_idx: u32,
267 archetype: &'a Archetype,
268 _epoch: EpochId,
269 ) -> FetchBorrowAllRead<'a, T> {
270 let indices = unsafe { archetype.borrow_indices(type_id::<T>()).unwrap_unchecked() };
271 let components = indices
272 .iter()
273 .map(|&(id, idx)| {
274 let component = unsafe { archetype.component(id).unwrap_unchecked() };
275 debug_assert_eq!(component.borrows()[idx].target(), type_id::<T>());
276
277 let data = unsafe { component.data_mut() };
278
279 FetchBorrowAllComponent {
280 ptr: data.ptr,
281 size: component.layout().size(),
282 borrow_fn: component.borrows()[idx].borrow(),
283 borrow_mut_fn: None,
284 entity_epochs: NonNull::new_unchecked(data.entity_epochs.as_mut_ptr()),
285 chunk_epochs: NonNull::new_unchecked(data.chunk_epochs.as_mut_ptr()),
286 }
287 })
288 .collect();
289
290 FetchBorrowAllRead {
291 components,
292 marker: PhantomData::<&'a T>,
293 }
294 }
295}
296
297unsafe impl<T> ImmutableQuery for QueryBorrowAll<Read<T>> where T: ?Sized + 'static {}
298unsafe impl<T> SendQuery for QueryBorrowAll<Read<T>> where T: Sync + ?Sized + 'static {}
299
300pub struct BorrowAllWrite<'a, T: ?Sized> {
301 idx: u32,
302 epoch: EpochId,
303 comp_idx: usize,
304 components: Rc<[FetchBorrowAllComponent<T>]>,
305 marker: PhantomData<&'a mut T>,
306}
307
308impl<'a, T> BorrowAllWrite<'a, T>
309where
310 T: ?Sized,
311{
312 pub fn read(&self) -> BorrowAllRead<'_, T> {
321 BorrowAllRead {
322 idx: self.idx,
323 comp_idx: self.comp_idx,
324 components: self.components.clone(),
325 marker: PhantomData::<&T>,
326 }
327 }
328
329 pub fn into_read(self) -> BorrowAllRead<'a, T> {
335 BorrowAllRead {
336 idx: self.idx,
337 comp_idx: self.comp_idx,
338 components: self.components.clone(),
339 marker: PhantomData::<&'a T>,
340 }
341 }
342}
343
344impl<T> Debug for BorrowAllWrite<'_, T>
345where
346 T: Debug + ?Sized,
347{
348 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
349 f.debug_list().entries(self.read()).finish()
350 }
351}
352
353impl<'a, T> Iterator for BorrowAllWrite<'a, T>
354where
355 T: ?Sized,
356{
357 type Item = &'a mut T;
358
359 #[inline(always)]
360 fn size_hint(&self) -> (usize, Option<usize>) {
361 let len = self.len();
362 (len, Some(len))
363 }
364
365 #[inline(always)]
366 fn next(&mut self) -> Option<&'a mut T> {
367 let c = &self.components.get(self.comp_idx)?;
368 let r = unsafe {
369 let entity_version = &mut *c.entity_epochs.as_ptr().add(self.idx as usize);
370 entity_version.bump(self.epoch);
371
372 (c.borrow_mut_fn.unwrap_unchecked())(
374 NonNull::new_unchecked(c.ptr.as_ptr().add(self.idx as usize * c.size)),
375 self.marker,
376 )
377 };
378 self.comp_idx += 1;
379 Some(r)
380 }
381
382 #[inline(always)]
383 fn nth(&mut self, n: usize) -> Option<&'a mut T> {
384 if n >= self.components.len() - self.comp_idx {
385 self.comp_idx = self.components.len();
386 } else {
387 self.comp_idx += n;
388 }
389 self.next()
390 }
391
392 fn fold<B, F>(mut self, init: B, mut f: F) -> B
393 where
394 Self: Sized,
395 F: FnMut(B, &'a mut T) -> B,
396 {
397 let mut accum = init;
398 for comp_idx in self.comp_idx..self.components.len() {
399 let c = &self.components[comp_idx];
400
401 let r = unsafe {
402 let entity_version = &mut *c.entity_epochs.as_ptr().add(self.idx as usize);
403 entity_version.bump(self.epoch);
404
405 (c.borrow_mut_fn.unwrap_unchecked())(
407 NonNull::new_unchecked(c.ptr.as_ptr().add(self.idx as usize * c.size)),
408 self.marker,
409 )
410 };
411 self.comp_idx += 1;
412 accum = f(accum, r);
413 }
414 accum
415 }
416}
417
418impl<'a, T> ExactSizeIterator for BorrowAllWrite<'a, T>
419where
420 T: ?Sized,
421{
422 #[inline(always)]
423 fn len(&self) -> usize {
424 self.components.len() - self.comp_idx
425 }
426}
427
428impl<'a, T> FusedIterator for BorrowAllWrite<'a, T> where T: ?Sized {}
429
430pub struct FetchBorrowAllWrite<'a, T: ?Sized> {
432 components: Rc<[FetchBorrowAllComponent<T>]>,
433 epoch: EpochId,
434 marker: PhantomData<&'a mut T>,
435}
436
437unsafe impl<'a, T> Fetch<'a> for FetchBorrowAllWrite<'a, T>
438where
439 T: ?Sized + 'a,
440{
441 type Item = BorrowAllWrite<'a, T>;
442
443 #[inline(always)]
444 fn dangling() -> Self {
445 FetchBorrowAllWrite {
446 components: Rc::new([]),
447 epoch: EpochId::start(),
448 marker: PhantomData,
449 }
450 }
451
452 #[inline(always)]
453 unsafe fn touch_chunk(&mut self, chunk_idx: u32) {
454 self.components.iter().for_each(|c| {
455 let chunk_epoch = &mut *c.chunk_epochs.as_ptr().add(chunk_idx as usize);
456 chunk_epoch.bump(self.epoch);
457 })
458 }
459
460 #[inline(always)]
461 unsafe fn get_item(&mut self, idx: u32) -> BorrowAllWrite<'a, T> {
462 BorrowAllWrite {
463 idx,
464 epoch: self.epoch,
465 comp_idx: 0,
466 components: self.components.clone(),
467 marker: self.marker,
468 }
469 }
470}
471
472impl<T> AsQuery for QueryBorrowAll<&mut T>
473where
474 T: ?Sized + 'static,
475{
476 type Query = QueryBorrowAll<Write<T>>;
477}
478
479impl<T> DefaultQuery for QueryBorrowAll<&mut T>
480where
481 T: ?Sized + 'static,
482{
483 #[inline(always)]
484 fn default_query() -> QueryBorrowAll<Write<T>> {
485 QueryBorrowAll(Write)
486 }
487}
488
489impl<T> AsQuery for QueryBorrowAll<Write<T>>
490where
491 T: ?Sized + 'static,
492{
493 type Query = Self;
494}
495
496impl<T> IntoQuery for QueryBorrowAll<Write<T>>
497where
498 T: ?Sized + 'static,
499{
500 #[inline(always)]
501 fn into_query(self) -> Self {
502 self
503 }
504}
505
506impl<T> DefaultQuery for QueryBorrowAll<Write<T>>
507where
508 T: ?Sized + 'static,
509{
510 #[inline(always)]
511 fn default_query() -> Self {
512 QueryBorrowAll(Write)
513 }
514}
515
516impl<T> QueryArg for QueryBorrowAll<Write<T>>
517where
518 T: Send + ?Sized + 'static,
519{
520 #[inline(always)]
521 fn new() -> Self {
522 QueryBorrowAll(Write)
523 }
524}
525
526unsafe impl<T> Query for QueryBorrowAll<Write<T>>
527where
528 T: ?Sized + 'static,
529{
530 type Item<'a> = BorrowAllWrite<'a, T>;
531 type Fetch<'a> = FetchBorrowAllWrite<'a, T>;
532
533 const MUTABLE: bool = true;
534
535 #[inline(always)]
536 fn component_access(&self, comp: &ComponentInfo) -> Result<Option<Access>, WriteAlias> {
537 if comp.has_borrow_mut(type_id::<T>()) {
538 Ok(Some(Access::Write))
539 } else {
540 Ok(None)
541 }
542 }
543
544 #[inline(always)]
545 fn visit_archetype(&self, archetype: &Archetype) -> bool {
546 archetype.contains_borrow_mut(type_id::<T>())
547 }
548
549 #[inline(always)]
550 unsafe fn access_archetype(&self, archetype: &Archetype, mut f: impl FnMut(TypeId, Access)) {
551 let indices = unsafe {
552 archetype
553 .borrow_mut_indices(type_id::<T>())
554 .unwrap_unchecked()
555 };
556 for (id, _) in indices {
557 f(*id, Access::Write);
558 }
559 }
560
561 #[inline(always)]
562 unsafe fn fetch<'a>(
563 &self,
564 _arch_idx: u32,
565 archetype: &'a Archetype,
566 epoch: EpochId,
567 ) -> FetchBorrowAllWrite<'a, T> {
568 let indices = unsafe {
569 archetype
570 .borrow_mut_indices(type_id::<T>())
571 .unwrap_unchecked()
572 };
573 let components = indices
574 .iter()
575 .map(|&(id, idx)| {
576 let component = unsafe { archetype.component(id).unwrap_unchecked() };
577 debug_assert_eq!(component.borrows()[idx].target(), type_id::<T>());
578 debug_assert!(component.borrows()[idx].borrow_mut::<T>().is_some());
579
580 let data = unsafe { component.data_mut() };
581 data.epoch.bump(epoch);
582
583 FetchBorrowAllComponent {
584 ptr: data.ptr,
585 size: component.layout().size(),
586 borrow_fn: component.borrows()[idx].borrow(),
587 borrow_mut_fn: component.borrows()[idx].borrow_mut(),
588 entity_epochs: NonNull::new_unchecked(data.entity_epochs.as_mut_ptr()),
589 chunk_epochs: NonNull::new_unchecked(data.chunk_epochs.as_mut_ptr()),
590 }
591 })
592 .collect();
593
594 FetchBorrowAllWrite {
595 components,
596 epoch,
597 marker: PhantomData::<&'a mut T>,
598 }
599 }
600}
601
602unsafe impl<T> SendQuery for QueryBorrowAll<Write<T>> where T: Send + ?Sized + 'static {}