hv_ecs/
entity_ref.rs

1use core::any::TypeId;
2use core::ops::{Deref, DerefMut};
3use core::ptr::NonNull;
4
5use crate::archetype::Archetype;
6use crate::{Component, Entity, MissingComponent, Query, QueryOne};
7
8/// Handle to an entity with any component types
9#[derive(Copy, Clone)]
10pub struct EntityRef<'a> {
11    archetype: &'a Archetype,
12    entity: Entity,
13    index: u32,
14}
15
16impl<'a> EntityRef<'a> {
17    pub(crate) unsafe fn new(archetype: &'a Archetype, entity: Entity, index: u32) -> Self {
18        Self {
19            archetype,
20            entity,
21            index,
22        }
23    }
24
25    /// Get the [`Entity`] handle associated with this entity
26    #[inline]
27    pub fn entity(&self) -> Entity {
28        self.entity
29    }
30
31    /// Determine whether this entity has a `T` component without borrowing it
32    pub fn has<T: Component>(&self) -> bool {
33        self.archetype.has::<T>()
34    }
35
36    /// Borrow the component of type `T`, if it exists
37    ///
38    /// Panics if the component is already uniquely borrowed from another entity with the same
39    /// components.
40    pub fn get<T: Component>(&self) -> Option<Ref<'a, T>> {
41        Some(unsafe { Ref::new(self.archetype, self.index).ok()? })
42    }
43
44    /// Uniquely borrow the component of type `T`, if it exists
45    ///
46    /// Panics if the component is already borrowed from another entity with the same components.
47    pub fn get_mut<T: Component>(&self) -> Option<RefMut<'a, T>> {
48        Some(unsafe { RefMut::new(self.archetype, self.index).ok()? })
49    }
50
51    /// Run a query against this entity
52    ///
53    /// Equivalent to invoking [`World::query_one`](crate::World::query_one) on the entity. May
54    /// outlive `self`.
55    ///
56    /// # Example
57    /// ```
58    /// # use hecs::*;
59    /// let mut world = World::new();
60    /// let a = world.spawn((123, true, "abc"));
61    /// // The returned query must outlive the borrow made by `get`
62    /// let mut query = world.entity(a).unwrap().query::<(&mut i32, &bool)>();
63    /// let (number, flag) = query.get().unwrap();
64    /// if *flag { *number *= 2; }
65    /// assert_eq!(*number, 246);
66    /// ```
67    pub fn query<Q: Query>(&self) -> QueryOne<'a, Q> {
68        unsafe { QueryOne::new(self.archetype, self.index) }
69    }
70
71    /// Enumerate the types of the entity's components
72    ///
73    /// Convenient for dispatching component-specific logic for a single entity. For example, this
74    /// can be combined with a `HashMap<TypeId, Box<dyn Handler>>` where `Handler` is some
75    /// user-defined trait with methods for serialization, or to be called after spawning or before
76    /// despawning to maintain secondary indices.
77    pub fn component_types(&self) -> impl Iterator<Item = TypeId> + 'a {
78        self.archetype.types().iter().map(|ty| ty.id())
79    }
80
81    /// Number of components in this entity
82    pub fn len(&self) -> usize {
83        self.archetype.types().len()
84    }
85
86    /// Shorthand for `self.len() == 0`
87    pub fn is_empty(&self) -> bool {
88        self.len() == 0
89    }
90}
91
92unsafe impl<'a> Send for EntityRef<'a> {}
93unsafe impl<'a> Sync for EntityRef<'a> {}
94
95/// Shared borrow of an entity's component
96#[derive(Clone)]
97pub struct Ref<'a, T: Component> {
98    archetype: &'a Archetype,
99    /// State index for `T` in `archetype`
100    state: usize,
101    target: NonNull<T>,
102}
103
104impl<'a, T: Component> Ref<'a, T> {
105    pub(crate) unsafe fn new(
106        archetype: &'a Archetype,
107        index: u32,
108    ) -> Result<Self, MissingComponent> {
109        let state = archetype
110            .get_state::<T>()
111            .ok_or_else(MissingComponent::new::<T>)?;
112        let target =
113            NonNull::new_unchecked(archetype.get_base::<T>(state).as_ptr().add(index as usize));
114        archetype.borrow::<T>(state);
115        Ok(Self {
116            archetype,
117            state,
118            target,
119        })
120    }
121}
122
123unsafe impl<T: Component> Send for Ref<'_, T> {}
124unsafe impl<T: Component> Sync for Ref<'_, T> {}
125
126impl<'a, T: Component> Drop for Ref<'a, T> {
127    fn drop(&mut self) {
128        self.archetype.release::<T>(self.state);
129    }
130}
131
132impl<'a, T: Component> Deref for Ref<'a, T> {
133    type Target = T;
134    fn deref(&self) -> &T {
135        unsafe { self.target.as_ref() }
136    }
137}
138
139/// Unique borrow of an entity's component
140pub struct RefMut<'a, T: Component> {
141    archetype: &'a Archetype,
142    /// State index for `T` in `archetype`
143    state: usize,
144    target: NonNull<T>,
145}
146
147impl<'a, T: Component> RefMut<'a, T> {
148    pub(crate) unsafe fn new(
149        archetype: &'a Archetype,
150        index: u32,
151    ) -> Result<Self, MissingComponent> {
152        let state = archetype
153            .get_state::<T>()
154            .ok_or_else(MissingComponent::new::<T>)?;
155        let target =
156            NonNull::new_unchecked(archetype.get_base::<T>(state).as_ptr().add(index as usize));
157        archetype.borrow_mut::<T>(state);
158        Ok(Self {
159            archetype,
160            state,
161            target,
162        })
163    }
164}
165
166unsafe impl<T: Component> Send for RefMut<'_, T> {}
167unsafe impl<T: Component> Sync for RefMut<'_, T> {}
168
169impl<'a, T: Component> Drop for RefMut<'a, T> {
170    fn drop(&mut self) {
171        self.archetype.release_mut::<T>(self.state);
172    }
173}
174
175impl<'a, T: Component> Deref for RefMut<'a, T> {
176    type Target = T;
177    fn deref(&self) -> &T {
178        unsafe { self.target.as_ref() }
179    }
180}
181
182impl<'a, T: Component> DerefMut for RefMut<'a, T> {
183    fn deref_mut(&mut self) -> &mut T {
184        unsafe { self.target.as_mut() }
185    }
186}