1use super::*;
2
3pub unsafe trait Fetch<'a>: Sized {
4 type Output;
5 type WorldBorrows;
6 unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows>;
7 unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output>;
8 type DirectBorrows;
9 unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows>;
10 unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output;
11}
12
13pub struct FetchRead<T>(PhantomData<T>);
14
15impl<T> Default for FetchRead<T> {
16 fn default() -> Self {
17 Self(PhantomData)
18 }
19}
20
21unsafe impl<'a, T: Component> Fetch<'a> for FetchRead<T> {
22 type Output = &'a T;
23 type WorldBorrows = storage::world::Borrow<'a, T>;
24 unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
25 world.borrow::<T>()
26 }
27 unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<&'a T> {
28 borrows.get(id)
29 }
30 type DirectBorrows = storage::entity::Borrow<'a, T>;
31 unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
32 entity.borrow::<T>()
33 }
34 unsafe fn get(&self, borrows: &Self::DirectBorrows) -> &'a T {
35 borrows.get()
36 }
37}
38
39pub struct FetchWrite<T>(PhantomData<T>);
40
41impl<T> Default for FetchWrite<T> {
42 fn default() -> Self {
43 Self(PhantomData)
44 }
45}
46
47unsafe impl<'a, T: Component> Fetch<'a> for FetchWrite<T> {
48 type Output = &'a mut T;
49 type WorldBorrows = storage::world::BorrowMut<'a, T>;
50 unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
51 world.borrow_mut::<T>()
52 }
53 unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<&'a mut T> {
54 borrows.get(id)
55 }
56 type DirectBorrows = storage::entity::BorrowMut<'a, T>;
57 unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
58 entity.borrow_mut::<T>()
59 }
60 unsafe fn get(&self, borrows: &Self::DirectBorrows) -> &'a mut T {
61 borrows.get()
62 }
63}
64
65#[derive(Default)]
66pub struct OptionFetch<T>(T);
67
68unsafe impl<'a, F: Fetch<'a>> Fetch<'a> for OptionFetch<F> {
69 type Output = Option<F::Output>;
70 type WorldBorrows = Option<F::WorldBorrows>;
71 unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
72 Some(F::borrow_world(&self.0, world))
73 }
74 unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output> {
75 borrows
76 .as_ref()
77 .map(|borrows| F::get_world(&self.0, borrows, id))
78 }
79 type DirectBorrows = Option<F::DirectBorrows>;
80 unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
81 Some(F::borrow_direct(&self.0, entity))
82 }
83 unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output {
84 borrows.as_ref().map(|borrows| F::get(&self.0, borrows))
85 }
86}
87
88pub struct FilterFetch<F: Filter>(pub F::Fetch);
89
90impl<F: Filter + Default> Default for FilterFetch<F> {
91 fn default() -> Self {
92 Self(F::default().fetch())
93 }
94}
95
96unsafe impl<'a, F: Filter> Fetch<'a> for FilterFetch<F> {
97 type Output = bool;
98 type WorldBorrows = <F::Fetch as Fetch<'a>>::WorldBorrows;
99 unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
100 self.0.borrow_world(world)
101 }
102 unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output> {
103 Some(F::get_world(&self.0, borrows, id))
104 }
105 type DirectBorrows = <F::Fetch as Fetch<'a>>::DirectBorrows;
106 unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
107 self.0.borrow_direct(entity)
108 }
109 unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output {
110 F::get(&self.0, borrows)
111 }
112}
113
114macro_rules! impl_for_tuple {
115 ($($name:ident),*) => {
116 #[allow(non_camel_case_types)]
117 #[allow(unused_variables)]
118 #[allow(clippy::unused_unit)]
119 unsafe impl<'a, $($name: Fetch<'a>),*> Fetch<'a> for ($($name,)*) {
120 type Output = ($($name::Output,)*);
121 type WorldBorrows = ($($name::WorldBorrows,)*);
122 unsafe fn borrow_world(&self, world: &'a World) -> Option<Self::WorldBorrows> {
123 let ($($name,)*) = self;
124 $(let $name = $name::borrow_world($name, world)?;)*
125 Some(($($name,)*))
126 }
127 unsafe fn get_world(&self, borrows: &Self::WorldBorrows, id: Id) -> Option<Self::Output> {
128 let ($($name,)*) = ZipExt::<<&Self::WorldBorrows as AsRefExt>::Output>::zip(self.as_ref(), borrows.as_ref());
129 $(
130 let (fetch, borrows) = $name;
131 let $name = $name::get_world(fetch, borrows, id)?;
132 )*
133 Some(($($name,)*))
134 }
135 type DirectBorrows = ($($name::DirectBorrows,)*);
136 unsafe fn borrow_direct(&self, entity: &'a Entity) -> Option<Self::DirectBorrows> {
137 let ($($name,)*) = self;
138 $(let $name = $name::borrow_direct($name, entity)?;)*
139 Some(($($name,)*))
140 }
141 unsafe fn get(&self, borrows: &Self::DirectBorrows) -> Self::Output {
142 let ($($name,)*) = ZipExt::zip(self.as_ref(), borrows.as_ref());
143 ($({
144 let (fetch, borrows) = $name;
145 $name::get(fetch, borrows)
146 },)*)
147 }
148 }
149 };
150}
151
152impl_tuples!(impl_for_tuple);