1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use core::{any::TypeId, marker::PhantomData, ptr::NonNull};
use crate::{
archetype::Archetype,
entity::EntityId,
epoch::EpochId,
query::{Access, Fetch, ImmutablePhantomQuery, IntoQuery, PhantomQuery, PhantomQueryFetch},
relation::{Relation, TargetComponent},
};
phantom_newtype! {
pub struct Related<R>
}
pub struct FetchRelated<'a, R> {
ptr: NonNull<TargetComponent<R>>,
marker: PhantomData<&'a TargetComponent<R>>,
}
unsafe impl<'a, R> Fetch<'a> for FetchRelated<'a, R>
where
R: Relation,
{
type Item = &'a [EntityId];
#[inline]
fn dangling() -> Self {
FetchRelated {
ptr: NonNull::dangling(),
marker: PhantomData,
}
}
#[inline]
unsafe fn get_item(&mut self, idx: usize) -> &'a [EntityId] {
let component = &*self.ptr.as_ptr().add(idx);
&component.origins[..]
}
}
impl<'a, R> PhantomQueryFetch<'a> for Related<R>
where
R: Relation,
{
type Item = &'a [EntityId];
type Fetch = FetchRelated<'a, R>;
}
impl<R> IntoQuery for Related<R>
where
R: Relation,
{
type Query = PhantomData<fn() -> Self>;
}
unsafe impl<R> PhantomQuery for Related<R>
where
R: Relation,
{
#[inline]
fn access(ty: TypeId) -> Option<Access> {
if ty == TypeId::of::<TargetComponent<R>>() {
Some(Access::Read)
} else {
None
}
}
#[inline]
fn skip_archetype(archetype: &Archetype) -> bool {
!archetype.has_component(TypeId::of::<TargetComponent<R>>())
}
#[inline]
unsafe fn access_archetype(_archetype: &Archetype, f: &dyn Fn(TypeId, Access)) {
f(TypeId::of::<TargetComponent<R>>(), Access::Read)
}
#[inline]
unsafe fn fetch<'a>(archetype: &'a Archetype, _epoch: EpochId) -> FetchRelated<'a, R> {
let component = archetype
.component(TypeId::of::<TargetComponent<R>>())
.unwrap_unchecked();
debug_assert_eq!(component.id(), TypeId::of::<TargetComponent<R>>());
let data = component.data();
FetchRelated {
ptr: data.ptr.cast(),
marker: PhantomData,
}
}
}
unsafe impl<R> ImmutablePhantomQuery for Related<R> where R: Relation {}