hecs_schedule/
subworld_impls.rs1use 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 pub fn native_query(&self) -> QueryBorrow<'_, T> {
17 self.world.query::<T>()
18 }
19}
20
21impl<A: ExternalClone, T: ComponentBorrow> SubWorldRaw<A, T> {
22 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
36pub trait ExternalClone {
38 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
137pub trait GenericWorld {
139 fn to_empty(&self) -> EmptyWorld {
142 self.to_ref()
143 }
144
145 fn to_ref<T: ComponentBorrow + Subset>(&self) -> SubWorldRef<T>;
147 fn try_query<Q: Query + Subset>(&self) -> Result<QueryBorrow<Q>>;
149 fn try_query_one<Q: Query + Subset>(&self, entity: Entity) -> Result<QueryOne<Q>>;
151
152 fn try_get<C: Component>(&self, entity: Entity) -> Result<hecs::Ref<C>>;
156
157 fn try_get_mut<C: Component>(&self, entity: Entity) -> Result<hecs::RefMut<C>>;
161
162 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 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 fn reserve(&self) -> Entity {
239 self.reserve_entity()
240 }
241}