hecs_schedule/
subworld_impls.rs

1use std::{any::type_name, ops::Deref};
2
3use atomic_refcell::AtomicRef;
4use hecs::{Component, Entity, Query, QueryBorrow, World};
5
6use crate::{
7    borrow::{Borrows, ComponentBorrow, ContextBorrow},
8    traits::View,
9    Access, Context, EmptyWorld, Error, IntoAccess, QueryOne, Result, SubWorld, SubWorldRaw,
10    SubWorldRef, Subset,
11};
12
13impl<A: Deref<Target = World>, T: Query> SubWorldRaw<A, T> {
14    /// Query the full access of the subworld. Does not fail as access is
15    /// guaranteed
16    pub fn native_query(&self) -> QueryBorrow<'_, T> {
17        self.world.query::<T>()
18    }
19}
20
21impl<A: ExternalClone, T: ComponentBorrow> SubWorldRaw<A, T> {
22    /// Splits the subworld further into a compatible subworld. Fails if not
23    /// compatible
24    pub fn split<U: ComponentBorrow + Subset>(&self) -> Result<SubWorldRaw<A, U>> {
25        if !self.has_all::<U>() {
26            return Err(Error::IncompatibleSubworld {
27                subworld: type_name::<T>(),
28                query: type_name::<SubWorldRaw<A, U>>(),
29            });
30        }
31
32        Ok(SubWorldRaw::new(A::external_clone(&self.world)))
33    }
34}
35
36/// Helper trait for types which do not implement clone, but has a clone wrapper
37pub trait ExternalClone {
38    /// Clones the internal value
39    fn external_clone(&self) -> Self;
40}
41
42impl<T> ExternalClone for &T {
43    fn external_clone(&self) -> Self {
44        <&T>::clone(self)
45    }
46}
47
48impl<T> ExternalClone for std::cell::Ref<'_, T> {
49    fn external_clone(&self) -> Self {
50        std::cell::Ref::clone(self)
51    }
52}
53
54impl<T> ExternalClone for AtomicRef<'_, T> {
55    fn external_clone(&self) -> Self {
56        AtomicRef::clone(self)
57    }
58}
59
60impl<'a, A, T> View<'a> for SubWorldRaw<A, T>
61where
62    A: Deref<Target = World>,
63    T: ComponentBorrow,
64{
65    type Superset = A;
66
67    fn split(world: Self::Superset) -> Self {
68        Self::new(world)
69    }
70}
71
72impl<'a, T> ContextBorrow<'a> for SubWorld<'a, T> {
73    type Target = Self;
74
75    fn borrow(context: &'a Context) -> Result<Self> {
76        let val = context
77            .cell::<&World>()?
78            .try_borrow()
79            .map_err(|_| Error::Borrow(type_name::<T>()))
80            .map(|cell| AtomicRef::map(cell, |val| unsafe { val.cast().as_ref() }))?;
81
82        Ok(Self::new(val))
83    }
84}
85
86impl<A: ExternalClone, T: ComponentBorrow, U: ComponentBorrow + Subset> From<&SubWorldRaw<A, T>>
87    for SubWorldRaw<A, U>
88{
89    fn from(value: &SubWorldRaw<A, T>) -> Self {
90        value.split().expect("Incompatible subworld")
91    }
92}
93
94impl<A, T> From<A> for SubWorldRaw<A, T> {
95    fn from(world: A) -> Self {
96        Self::new(world)
97    }
98}
99
100impl<'a, T> From<&'a Context<'a>> for SubWorldRaw<AtomicRef<'a, World>, T> {
101    fn from(context: &'a Context) -> Self {
102        let borrow = context
103            .cell::<&World>()
104            .expect("Failed to borrow world from context")
105            .borrow();
106
107        let val = AtomicRef::map(borrow, |val| unsafe { val.cast().as_ref() });
108
109        Self::new(val)
110    }
111}
112
113impl<'a, 'b, T: ComponentBorrow, U: ComponentBorrow + Subset> From<&'b SubWorld<'a, T>>
114    for SubWorldRef<'b, U>
115{
116    fn from(subworld: &'b SubWorld<'a, T>) -> Self {
117        subworld.to_ref()
118    }
119}
120
121impl<A, T: ComponentBorrow + Query> ComponentBorrow for SubWorldRaw<A, T> {
122    fn borrows() -> Borrows {
123        let mut access = T::borrows();
124        access.push(Access::of::<&World>());
125        access
126    }
127
128    fn has<U: IntoAccess>() -> bool {
129        T::has::<U>()
130    }
131
132    fn has_dynamic(id: std::any::TypeId, exclusive: bool) -> bool {
133        T::has_dynamic(id, exclusive)
134    }
135}
136
137/// Trait for allowing function to work on both World and SubWorld
138pub trait GenericWorld {
139    /// Transform this into a subworld which borrows no components.
140    /// This is useful for concurrent access of entities.
141    fn to_empty(&self) -> EmptyWorld {
142        self.to_ref()
143    }
144
145    /// Convert the subworld into another holding an internal reference to the original world.
146    fn to_ref<T: ComponentBorrow + Subset>(&self) -> SubWorldRef<T>;
147    /// Queries the world
148    fn try_query<Q: Query + Subset>(&self) -> Result<QueryBorrow<Q>>;
149    /// Queries the world for a specific entity
150    fn try_query_one<Q: Query + Subset>(&self, entity: Entity) -> Result<QueryOne<Q>>;
151
152    /// Get a single component for an entity
153    /// Returns the contextual result since hecs-schedule is required to be imported
154    /// anyway
155    fn try_get<C: Component>(&self, entity: Entity) -> Result<hecs::Ref<C>>;
156
157    /// Get a single component for an entity
158    /// Returns the contextual result since hecs-schedule is required to be imported
159    /// anyway
160    fn try_get_mut<C: Component>(&self, entity: Entity) -> Result<hecs::RefMut<C>>;
161
162    /// Reserve an entity
163    fn reserve(&self) -> Entity;
164}
165
166impl<A: Deref<Target = World>, T: ComponentBorrow> GenericWorld for SubWorldRaw<A, T> {
167    fn to_ref<U: ComponentBorrow + Subset>(&self) -> SubWorldRef<U> {
168        let world = self.world.deref();
169        SubWorldRef::<T>::new(world).split().unwrap()
170    }
171
172    fn try_query<Q: Query + Subset>(&self) -> Result<QueryBorrow<'_, Q>> {
173        if !self.has_all::<Q>() {
174            return Err(Error::IncompatibleSubworld {
175                subworld: type_name::<T>(),
176                query: type_name::<Q>(),
177            });
178        } else {
179            Ok(self.world.query())
180        }
181    }
182
183    fn try_query_one<Q: Query + Subset>(&self, entity: Entity) -> Result<QueryOne<'_, Q>> {
184        self.query_one(entity)
185    }
186
187    fn try_get<C: Component>(&self, entity: Entity) -> Result<hecs::Ref<C>> {
188        self.get(entity)
189    }
190
191    fn try_get_mut<C: Component>(&self, entity: Entity) -> Result<hecs::RefMut<C>> {
192        self.get_mut(entity)
193    }
194
195    /// Reserve an entity
196    fn reserve(&self) -> Entity {
197        self.world.reserve_entity()
198    }
199}
200
201impl GenericWorld for World {
202    fn to_ref<T: ComponentBorrow + Subset>(&self) -> SubWorldRef<T> {
203        SubWorldRef::new(self)
204    }
205
206    fn try_query<Q: Query + Subset>(&self) -> Result<QueryBorrow<Q>> {
207        Ok(self.query())
208    }
209
210    fn try_query_one<Q: Query + Subset>(&self, entity: Entity) -> Result<QueryOne<Q>> {
211        match self.query_one(entity) {
212            Ok(val) => Ok(QueryOne::new(entity, val)),
213            Err(_) => Err(Error::NoSuchEntity(entity)),
214        }
215    }
216
217    fn try_get<C: Component>(&self, entity: Entity) -> Result<hecs::Ref<C>> {
218        match self.get::<&C>(entity) {
219            Ok(val) => Ok(val),
220            Err(hecs::ComponentError::NoSuchEntity) => Err(Error::NoSuchEntity(entity)),
221            Err(hecs::ComponentError::MissingComponent(name)) => {
222                Err(Error::MissingComponent(entity, name))
223            }
224        }
225    }
226
227    fn try_get_mut<C: Component>(&self, entity: Entity) -> Result<hecs::RefMut<C>> {
228        match self.get::<&mut C>(entity) {
229            Ok(val) => Ok(val),
230            Err(hecs::ComponentError::NoSuchEntity) => Err(Error::NoSuchEntity(entity)),
231            Err(hecs::ComponentError::MissingComponent(name)) => {
232                Err(Error::MissingComponent(entity, name))
233            }
234        }
235    }
236
237    /// Reserve an entity
238    fn reserve(&self) -> Entity {
239        self.reserve_entity()
240    }
241}