geng_ecs/
fetch.rs

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);