1use core::{any::TypeId, marker::PhantomData, ptr::NonNull};
2
3use crate::{
4 archetype::Archetype,
5 component::ComponentInfo,
6 entity::{EntityBound, EntityId},
7 epoch::EpochId,
8 query::{
9 AsQuery, DefaultQuery, Fetch, ImmutableQuery, IntoQuery, Query, Read, SendQuery, Write,
10 WriteAlias,
11 },
12 relation::{OriginComponent, Relation, RelationTarget},
13 system::QueryArg,
14 type_id, Access,
15};
16
17marker_type! {
18 pub struct Relates<R>;
22}
23
24#[derive(Clone)]
26pub struct RelatesReadIter<'a, R> {
27 iter: core::slice::Iter<'a, RelationTarget<R>>,
28}
29
30impl<'a, R> Iterator for RelatesReadIter<'a, R> {
31 type Item = (&'a R, EntityBound<'a>);
32
33 #[inline(always)]
34 fn size_hint(&self) -> (usize, Option<usize>) {
35 self.iter.size_hint()
36 }
37
38 #[inline(always)]
39 fn next(&mut self) -> Option<(&'a R, EntityBound<'a>)> {
40 let origin = self.iter.next()?;
41 Some((&origin.relation, EntityBound::new(origin.target)))
42 }
43
44 #[inline(always)]
45 fn nth(&mut self, n: usize) -> Option<(&'a R, EntityBound<'a>)> {
46 let origin = self.iter.nth(n)?;
47 Some((&origin.relation, EntityBound::new(origin.target)))
48 }
49
50 #[inline(always)]
51 fn fold<B, F>(self, init: B, mut f: F) -> B
52 where
53 Self: Sized,
54 F: FnMut(B, Self::Item) -> B,
55 {
56 self.iter.fold(init, |acc, origin| {
57 f(acc, (&origin.relation, EntityBound::new(origin.target)))
58 })
59 }
60}
61
62impl<'a, R> DoubleEndedIterator for RelatesReadIter<'a, R> {
63 #[inline(always)]
64 fn next_back(&mut self) -> Option<(&'a R, EntityBound<'a>)> {
65 let origin = self.iter.next_back()?;
66 Some((&origin.relation, EntityBound::new(origin.target)))
67 }
68
69 #[inline(always)]
70 fn nth_back(&mut self, n: usize) -> Option<(&'a R, EntityBound<'a>)> {
71 let origin = self.iter.nth_back(n)?;
72 Some((&origin.relation, EntityBound::new(origin.target)))
73 }
74
75 #[inline(always)]
76 fn rfold<B, F>(self, init: B, mut f: F) -> B
77 where
78 Self: Sized,
79 F: FnMut(B, Self::Item) -> B,
80 {
81 self.iter.rfold(init, |acc, origin| {
82 f(acc, (&origin.relation, EntityBound::new(origin.target)))
83 })
84 }
85}
86
87impl<'a, R> ExactSizeIterator for RelatesReadIter<'a, R> {
88 #[inline(always)]
89 fn len(&self) -> usize {
90 self.iter.len()
91 }
92}
93
94pub struct FetchRelatesRead<'a, R: Relation> {
96 ptr: NonNull<OriginComponent<R>>,
97 marker: PhantomData<&'a OriginComponent<R>>,
98}
99
100unsafe impl<'a, R> Fetch<'a> for FetchRelatesRead<'a, R>
101where
102 R: Relation,
103{
104 type Item = RelatesReadIter<'a, R>;
105
106 #[inline(always)]
107 fn dangling() -> Self {
108 FetchRelatesRead {
109 ptr: NonNull::dangling(),
110 marker: PhantomData,
111 }
112 }
113
114 #[inline(always)]
115 unsafe fn get_item(&mut self, idx: u32) -> RelatesReadIter<'a, R> {
116 let origin_component = unsafe { &*self.ptr.as_ptr().add(idx as usize) };
117
118 RelatesReadIter {
119 iter: origin_component.relations().iter(),
120 }
121 }
122}
123
124impl<R> AsQuery for Relates<&R>
125where
126 R: Relation,
127{
128 type Query = Relates<Read<R>>;
129}
130
131impl<R> DefaultQuery for Relates<&R>
132where
133 R: Relation,
134{
135 #[inline(always)]
136 fn default_query() -> Relates<Read<R>> {
137 Relates
138 }
139}
140
141impl<R> AsQuery for Relates<Read<R>>
142where
143 R: Relation,
144{
145 type Query = Self;
146}
147
148impl<R> IntoQuery for Relates<Read<R>>
149where
150 R: Relation,
151{
152 #[inline(always)]
153 fn into_query(self) -> Self::Query {
154 self
155 }
156}
157
158impl<R> DefaultQuery for Relates<Read<R>>
159where
160 R: Relation,
161{
162 #[inline(always)]
163 fn default_query() -> Self {
164 Relates
165 }
166}
167
168impl<R> QueryArg for Relates<Read<R>>
169where
170 R: Sync + Relation,
171{
172 #[inline(always)]
173 fn new() -> Self {
174 Relates
175 }
176}
177
178unsafe impl<R> Query for Relates<Read<R>>
179where
180 R: Relation,
181{
182 type Item<'a> = RelatesReadIter<'a, R>;
183 type Fetch<'a> = FetchRelatesRead<'a, R>;
184
185 const MUTABLE: bool = false;
186
187 #[inline(always)]
188 fn component_access(&self, comp: &ComponentInfo) -> Result<Option<Access>, WriteAlias> {
189 if comp.id() == type_id::<OriginComponent<R>>() {
190 Ok(Some(Access::Read))
191 } else {
192 Ok(None)
193 }
194 }
195
196 #[inline(always)]
197 fn visit_archetype(&self, archetype: &Archetype) -> bool {
198 archetype.has_component(type_id::<OriginComponent<R>>())
199 }
200
201 #[inline(always)]
202 unsafe fn access_archetype(&self, _archetype: &Archetype, mut f: impl FnMut(TypeId, Access)) {
203 f(type_id::<OriginComponent<R>>(), Access::Read)
204 }
205
206 #[inline(always)]
207 unsafe fn fetch<'a>(
208 &self,
209 _arch_idx: u32,
210 archetype: &'a Archetype,
211 _epoch: EpochId,
212 ) -> FetchRelatesRead<'a, R> {
213 let component = unsafe {
214 archetype
215 .component(type_id::<OriginComponent<R>>())
216 .unwrap_unchecked()
217 };
218
219 debug_assert_eq!(component.id(), type_id::<OriginComponent<R>>());
220
221 let data = unsafe { component.data() };
222
223 FetchRelatesRead {
224 ptr: data.ptr.cast(),
225 marker: PhantomData,
226 }
227 }
228}
229
230unsafe impl<R> ImmutableQuery for Relates<Read<R>> where R: Relation {}
231unsafe impl<R> SendQuery for Relates<Read<R>> where R: Relation + Sync {}
232
233pub struct RelatesWriteIter<'a, R> {
235 iter: core::slice::IterMut<'a, RelationTarget<R>>,
236}
237
238impl<'a, R> Iterator for RelatesWriteIter<'a, R> {
239 type Item = (&'a mut R, EntityId);
240
241 #[inline(always)]
242 fn size_hint(&self) -> (usize, Option<usize>) {
243 self.iter.size_hint()
244 }
245
246 #[inline(always)]
247 fn next(&mut self) -> Option<(&'a mut R, EntityId)> {
248 let origin = self.iter.next()?;
249 Some((&mut origin.relation, origin.target))
250 }
251
252 #[inline(always)]
253 fn nth(&mut self, n: usize) -> Option<(&'a mut R, EntityId)> {
254 let origin = self.iter.nth(n)?;
255 Some((&mut origin.relation, origin.target))
256 }
257
258 #[inline(always)]
259 fn fold<B, F>(self, init: B, mut f: F) -> B
260 where
261 Self: Sized,
262 F: FnMut(B, Self::Item) -> B,
263 {
264 self.iter.fold(init, |acc, origin| {
265 f(acc, (&mut origin.relation, origin.target))
266 })
267 }
268}
269
270impl<'a, R> DoubleEndedIterator for RelatesWriteIter<'a, R> {
271 #[inline(always)]
272 fn next_back(&mut self) -> Option<(&'a mut R, EntityId)> {
273 let origin = self.iter.next_back()?;
274 Some((&mut origin.relation, origin.target))
275 }
276
277 #[inline(always)]
278 fn nth_back(&mut self, n: usize) -> Option<(&'a mut R, EntityId)> {
279 let origin = self.iter.nth_back(n)?;
280 Some((&mut origin.relation, origin.target))
281 }
282
283 #[inline(always)]
284 fn rfold<B, F>(self, init: B, mut f: F) -> B
285 where
286 Self: Sized,
287 F: FnMut(B, Self::Item) -> B,
288 {
289 self.iter.rfold(init, |acc, origin| {
290 f(acc, (&mut origin.relation, origin.target))
291 })
292 }
293}
294
295impl<'a, R> ExactSizeIterator for RelatesWriteIter<'a, R> {
296 #[inline(always)]
297 fn len(&self) -> usize {
298 self.iter.len()
299 }
300}
301
302pub struct FetchRelatesWrite<'a, R: Relation> {
304 epoch: EpochId,
305 ptr: NonNull<OriginComponent<R>>,
306 entity_epochs: NonNull<EpochId>,
307 chunk_epochs: NonNull<EpochId>,
308 marker: PhantomData<&'a mut OriginComponent<R>>,
309}
310
311unsafe impl<'a, R> Fetch<'a> for FetchRelatesWrite<'a, R>
312where
313 R: Relation,
314{
315 type Item = RelatesWriteIter<'a, R>;
316
317 #[inline(always)]
318 fn dangling() -> Self {
319 FetchRelatesWrite {
320 epoch: EpochId::start(),
321 ptr: NonNull::dangling(),
322 entity_epochs: NonNull::dangling(),
323 chunk_epochs: NonNull::dangling(),
324 marker: PhantomData,
325 }
326 }
327
328 #[inline(always)]
329 unsafe fn touch_chunk(&mut self, chunk_idx: u32) {
330 let chunk_epoch = unsafe { &mut *self.chunk_epochs.as_ptr().add(chunk_idx as usize) };
331 chunk_epoch.bump(self.epoch);
332 }
333
334 #[inline(always)]
335 unsafe fn get_item(&mut self, idx: u32) -> RelatesWriteIter<'a, R> {
336 let entity_epoch = unsafe { &mut *self.entity_epochs.as_ptr().add(idx as usize) };
337 entity_epoch.bump(self.epoch);
338
339 let origin_component = unsafe { &mut *self.ptr.as_ptr().add(idx as usize) };
340
341 RelatesWriteIter {
342 iter: origin_component.relations_mut().iter_mut(),
343 }
344 }
345}
346
347impl<R> AsQuery for Relates<&mut R>
348where
349 R: Relation,
350{
351 type Query = Relates<Write<R>>;
352}
353
354impl<R> DefaultQuery for Relates<&mut R>
355where
356 R: Relation,
357{
358 #[inline(always)]
359 fn default_query() -> Relates<Write<R>> {
360 Relates
361 }
362}
363
364impl<R> AsQuery for Relates<Write<R>>
365where
366 R: Relation,
367{
368 type Query = Self;
369}
370
371impl<R> IntoQuery for Relates<Write<R>>
372where
373 R: Relation,
374{
375 #[inline(always)]
376 fn into_query(self) -> Self {
377 self
378 }
379}
380
381impl<R> DefaultQuery for Relates<Write<R>>
382where
383 R: Relation,
384{
385 #[inline(always)]
386 fn default_query() -> Self {
387 Relates
388 }
389}
390
391impl<R> QueryArg for Relates<Write<R>>
392where
393 R: Send + Relation,
394{
395 #[inline(always)]
396 fn new() -> Self {
397 Relates
398 }
399}
400
401unsafe impl<R> Query for Relates<Write<R>>
402where
403 R: Relation,
404{
405 type Item<'a> = RelatesWriteIter<'a, R>;
406 type Fetch<'a> = FetchRelatesWrite<'a, R>;
407
408 const MUTABLE: bool = true;
409
410 #[inline(always)]
411 fn component_access(&self, comp: &ComponentInfo) -> Result<Option<Access>, WriteAlias> {
412 if comp.id() == type_id::<OriginComponent<R>>() {
413 Ok(Some(Access::Write))
414 } else {
415 Ok(None)
416 }
417 }
418
419 #[inline(always)]
420 fn visit_archetype(&self, archetype: &Archetype) -> bool {
421 archetype.has_component(type_id::<OriginComponent<R>>())
422 }
423
424 #[inline(always)]
425 unsafe fn access_archetype(&self, _archetype: &Archetype, mut f: impl FnMut(TypeId, Access)) {
426 f(type_id::<OriginComponent<R>>(), Access::Write)
427 }
428
429 #[inline(always)]
430 unsafe fn fetch<'a>(
431 &self,
432 _arch_idx: u32,
433 archetype: &'a Archetype,
434 epoch: EpochId,
435 ) -> FetchRelatesWrite<'a, R> {
436 let component = unsafe {
437 archetype
438 .component(type_id::<OriginComponent<R>>())
439 .unwrap_unchecked()
440 };
441 debug_assert_eq!(component.id(), type_id::<OriginComponent<R>>());
442
443 let data = unsafe { component.data_mut() };
444 data.epoch.bump(epoch);
445
446 FetchRelatesWrite {
447 epoch,
448 ptr: data.ptr.cast(),
449 entity_epochs: unsafe { NonNull::new_unchecked(data.entity_epochs.as_mut_ptr()) },
450 chunk_epochs: unsafe { NonNull::new_unchecked(data.chunk_epochs.as_mut_ptr()) },
451 marker: PhantomData,
452 }
453 }
454}
455
456unsafe impl<R> SendQuery for Relates<Write<R>> where R: Relation + Send {}