edict/relation/query/
relates.rs

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    /// Query for origins of relation.
19    ///
20    /// Yields iterator of pairs - relation instance and target.
21    pub struct Relates<R>;
22}
23
24/// Iterator over relations of a given type on one entity.
25#[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
94/// Fetch for the [`Relates<&R>`] query.
95pub 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
233/// Iterator over relations of a given type on one entity.
234pub 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
302/// Fetch for the [`Relates<&mut R>`] query.
303pub 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 {}