shipyard/
get.rs

1use crate::component::Component;
2use crate::entity_id::EntityId;
3use crate::error;
4use crate::r#mut::Mut;
5use crate::sparse_set::SparseSet;
6use crate::tracking::Tracking;
7use crate::views::{View, ViewMut};
8use core::any::type_name;
9
10/// Retrieves components based on their type and entity id.
11pub trait Get {
12    #[allow(missing_docs)]
13    type Out;
14    /// Retrieve components of `entity`.
15    ///
16    /// Multiple components can be queried at the same time using a tuple.
17    ///
18    /// ### Example:
19    /// ```
20    /// use shipyard::{Component, Get, View, World};
21    ///
22    /// #[derive(Component, Debug, PartialEq, Eq)]
23    /// struct U32(u32);
24    ///
25    /// #[derive(Component, Debug, PartialEq, Eq)]
26    /// struct USIZE(usize);
27    ///
28    /// let mut world = World::new();
29    ///
30    /// let entity = world.add_entity((USIZE(0), U32(1)));
31    ///
32    /// let (usizes, u32s) = world.borrow::<(View<USIZE>, View<U32>)>().unwrap();
33    /// assert_eq!((&usizes, &u32s).get(entity), Ok((&USIZE(0), &U32(1))));
34    /// ```
35    fn get(self, entity: EntityId) -> Result<Self::Out, error::MissingComponent>;
36}
37
38impl<'a, T: Component> Get for &'a SparseSet<T> {
39    type Out = &'a T;
40
41    fn get(self, entity: EntityId) -> Result<Self::Out, error::MissingComponent> {
42        self.private_get(entity)
43            .ok_or_else(|| error::MissingComponent {
44                id: entity,
45                name: type_name::<T>(),
46            })
47    }
48}
49
50impl<'a, 'b, T: Component, Track: Tracking> Get for &'b View<'a, T, Track> {
51    type Out = &'b T;
52
53    #[inline]
54    fn get(self, entity: EntityId) -> Result<Self::Out, error::MissingComponent> {
55        (**self)
56            .private_get(entity)
57            .ok_or_else(|| error::MissingComponent {
58                id: entity,
59                name: type_name::<T>(),
60            })
61    }
62}
63
64impl<'a, 'b, T: Component, Track: Tracking> Get for &'b ViewMut<'a, T, Track> {
65    type Out = &'b T;
66
67    #[inline]
68    fn get(self, entity: EntityId) -> Result<Self::Out, error::MissingComponent> {
69        (**self)
70            .private_get(entity)
71            .ok_or_else(|| error::MissingComponent {
72                id: entity,
73                name: type_name::<T>(),
74            })
75    }
76}
77
78impl<'a, 'b, T: Component, Track: Tracking> Get for &'b mut ViewMut<'a, T, Track> {
79    type Out = Mut<'b, T>;
80
81    #[inline]
82    fn get(self, entity: EntityId) -> Result<Self::Out, error::MissingComponent> {
83        let index = self
84            .index_of(entity)
85            .ok_or_else(|| error::MissingComponent {
86                id: entity,
87                name: type_name::<T>(),
88            })?;
89
90        let SparseSet {
91            data,
92            modification_data,
93            is_tracking_modification,
94            ..
95        } = self.sparse_set;
96
97        Ok(Mut {
98            flag: is_tracking_modification
99                .then(|| unsafe { modification_data.get_unchecked_mut(index) }),
100            current: self.current,
101            data: unsafe { data.get_unchecked_mut(index) },
102        })
103    }
104}
105
106macro_rules! impl_get_component {
107    ($(($type: ident, $index: tt))+) => {
108        impl<$($type: Get),+> Get for ($($type,)+) {
109            type Out = ($($type::Out,)+);
110            #[inline]
111            fn get(self, entity: EntityId) -> Result<Self::Out, error::MissingComponent> {
112                Ok(($(self.$index.get(entity)?,)+))
113            }
114        }
115    }
116}
117
118macro_rules! get_component {
119    ($(($type: ident, $index: tt))+; ($type1: ident, $index1: tt) $(($queue_type: ident, $queue_index: tt))*) => {
120        impl_get_component![$(($type, $index))*];
121        get_component![$(($type, $index))* ($type1, $index1); $(($queue_type, $queue_index))*];
122    };
123    ($(($type: ident, $index: tt))+;) => {
124        impl_get_component![$(($type, $index))*];
125    }
126}
127
128#[cfg(not(feature = "extended_tuple"))]
129get_component![(ViewA, 0); (ViewB, 1) (ViewC, 2) (ViewD, 3) (ViewE, 4) (ViewF, 5) (ViewG, 6) (ViewH, 7) (ViewI, 8) (ViewJ, 9)];
130#[cfg(feature = "extended_tuple")]
131get_component![
132    (ViewA, 0); (ViewB, 1) (ViewC, 2) (ViewD, 3) (ViewE, 4) (ViewF, 5) (ViewG, 6) (ViewH, 7) (ViewI, 8) (ViewJ, 9)
133    (ViewK, 10) (ViewL, 11) (ViewM, 12) (ViewN, 13) (ViewO, 14) (ViewP, 15) (ViewQ, 16) (ViewR, 17) (ViewS, 18) (ViewT, 19)
134    (ViewU, 20) (ViewV, 21) (ViewW, 22) (ViewX, 23) (ViewY, 24) (ViewZ, 25) (ViewAA, 26) (ViewBB, 27) (ViewCC, 28) (ViewDD, 29)
135    (ViewEE, 30) (ViewFF, 31)
136];