shipyard/
world.rs

1mod builder;
2mod run_batches;
3
4pub use builder::WorldBuilder;
5
6use crate::all_storages::{AllStorages, CustomStorageAccess, TupleDeleteAny, TupleRetainStorage};
7use crate::atomic_refcell::{ARef, ARefMut, AtomicRefCell};
8use crate::borrow::WorldBorrow;
9use crate::component::{Component, Unique};
10use crate::entities::Entities;
11use crate::entity_id::EntityId;
12use crate::error;
13use crate::get_component::GetComponent;
14use crate::get_unique::GetUnique;
15use crate::info::WorkloadsInfo;
16use crate::iter_component::{IntoIterRef, IterComponent};
17use crate::memory_usage::WorldMemoryUsage;
18use crate::r#mut::Mut;
19use crate::reserve::BulkEntityIter;
20use crate::scheduler::Label;
21use crate::scheduler::{AsLabel, Batches, Scheduler};
22use crate::sparse_set::{BulkAddEntity, TupleAddComponent, TupleDelete, TupleRemove};
23use crate::storage::{Storage, StorageId};
24use crate::system::System;
25use crate::tracking::{TrackingTimestamp, TupleTrack};
26use crate::views::EntitiesViewMut;
27use alloc::boxed::Box;
28use alloc::format;
29use alloc::sync::Arc;
30use core::sync::atomic::AtomicU32;
31
32/// `World` contains all data this library will manipulate.
33pub struct World {
34    pub(crate) all_storages: AtomicRefCell<AllStorages>,
35    pub(crate) scheduler: AtomicRefCell<Scheduler>,
36    counter: Arc<AtomicU32>,
37    #[cfg(feature = "parallel")]
38    thread_pool: Option<rayon::ThreadPool>,
39}
40
41#[cfg(feature = "std")]
42impl Default for World {
43    /// Creates an empty `World`.
44    fn default() -> Self {
45        let counter = Arc::new(AtomicU32::new(1));
46        World {
47            #[cfg(not(feature = "thread_local"))]
48            all_storages: AtomicRefCell::new(AllStorages::new(counter.clone())),
49            #[cfg(feature = "thread_local")]
50            all_storages: AtomicRefCell::new_non_send(
51                AllStorages::new(counter.clone()),
52                Arc::new(crate::std_thread_id_generator),
53            ),
54            scheduler: AtomicRefCell::new(Default::default()),
55            counter,
56            #[cfg(feature = "parallel")]
57            thread_pool: None,
58        }
59    }
60}
61
62impl World {
63    /// Creates an empty `World`.
64    #[cfg(feature = "std")]
65    pub fn new() -> World {
66        Default::default()
67    }
68    /// Removes the local [`ThreadPool`](rayon::ThreadPool).
69    #[cfg(feature = "parallel")]
70    pub fn remove_local_thread_pool(&mut self) -> Option<rayon::ThreadPool> {
71        self.thread_pool.take()
72    }
73    /// Adds a new unique storage, unique storages store a single value.
74    /// To access a unique storage value, use [`UniqueView`] or [`UniqueViewMut`].
75    ///
76    /// ### Borrows
77    ///
78    /// - [`AllStorages`] (shared)
79    ///
80    /// ### Panics
81    ///
82    /// - [`AllStorages`] borrow failed.
83    ///
84    /// ### Example
85    ///
86    /// ```
87    /// use shipyard::{Unique, UniqueView, World};
88    ///
89    /// #[derive(Unique)]
90    /// struct U32(u32);
91    ///
92    /// let world = World::new();
93    ///
94    /// world.add_unique(U32(0));
95    ///
96    /// let i = world.borrow::<UniqueView<U32>>().unwrap();
97    /// assert_eq!(i.0, 0);
98    /// ```
99    ///
100    /// [`AllStorages`]: crate::AllStorages
101    /// [`UniqueView`]: crate::UniqueView
102    /// [`UniqueViewMut`]: crate::UniqueViewMut
103    #[track_caller]
104    pub fn add_unique<T: Send + Sync + Unique>(&self, component: T) {
105        self.all_storages.borrow().unwrap().add_unique(component);
106    }
107    /// Adds a new unique storage, unique storages store a single value.
108    /// To access a `!Send` unique storage value, use [`NonSend`] with [`UniqueView`] or [`UniqueViewMut`].
109    /// Does nothing if the storage already exists.
110    ///
111    /// ### Borrows
112    ///
113    /// - [`AllStorages`] (shared)
114    ///
115    /// ### Panics
116    ///
117    /// - [`AllStorages`] borrow failed.
118    ///
119    /// ### Example
120    ///
121    /// ```
122    /// use shipyard::{NonSend, Unique, UniqueView, World};
123    ///
124    /// #[derive(Unique)]
125    /// struct U32(u32);
126    ///
127    /// let world = World::new();
128    ///
129    /// // I'm using `u32` here but imagine it's a `!Send` type
130    /// world.add_unique_non_send(U32(0));
131    ///
132    /// let i = world.borrow::<NonSend<UniqueView<U32>>>().unwrap();
133    /// assert_eq!(i.0, 0);
134    /// ```
135    ///
136    /// [`AllStorages`]: crate::AllStorages
137    /// [`UniqueView`]: crate::UniqueView
138    /// [`UniqueViewMut`]: crate::UniqueViewMut
139    /// [`NonSend`]: crate::NonSend
140    #[cfg(feature = "thread_local")]
141    #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
142    #[track_caller]
143    pub fn add_unique_non_send<T: Sync + Unique>(&self, component: T) {
144        self.all_storages
145            .borrow()
146            .unwrap()
147            .add_unique_non_send(component);
148    }
149    /// Adds a new unique storage, unique storages store a single value.
150    /// To access a `!Sync` unique storage value, use [`NonSync`] with [`UniqueView`] or [`UniqueViewMut`].
151    /// Does nothing if the storage already exists.
152    ///
153    /// ### Borrows
154    ///
155    /// - [`AllStorages`] (shared)
156    ///
157    /// ### Panics
158    ///
159    /// - [`AllStorages`] borrow failed.
160    ///
161    /// ### Example
162    ///
163    /// ```
164    /// use shipyard::{NonSync, Unique, UniqueView, World};
165    ///
166    /// #[derive(Unique)]
167    /// struct U32(u32);
168    ///
169    /// let world = World::new();
170    ///
171    /// // I'm using `u32` here but imagine it's a `!Sync` type
172    /// world.add_unique_non_sync(U32(0));
173    ///
174    /// let i = world.borrow::<NonSync<UniqueView<U32>>>().unwrap();
175    /// assert_eq!(i.0, 0);
176    /// ```
177    ///
178    /// [`AllStorages`]: crate::AllStorages
179    /// [`UniqueView`]: crate::UniqueView
180    /// [`UniqueViewMut`]: crate::UniqueViewMut
181    /// [`NonSync`]: crate::NonSync
182    #[cfg(feature = "thread_local")]
183    #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
184    #[track_caller]
185    pub fn add_unique_non_sync<T: Send + Unique>(&self, component: T) {
186        self.all_storages
187            .borrow()
188            .unwrap()
189            .add_unique_non_sync(component);
190    }
191    /// Adds a new unique storage, unique storages store a single value.
192    /// To access a `!Send + !Sync` unique storage value, use [`NonSendSync`] with [`UniqueView`] or [`UniqueViewMut`].
193    /// Does nothing if the storage already exists.
194    ///
195    /// ### Borrows
196    ///
197    /// - [`AllStorages`] (shared)
198    ///
199    /// ### Panics
200    ///
201    /// - [`AllStorages`] borrow failed.
202    ///
203    /// ### Example
204    ///
205    /// ```
206    /// use shipyard::{NonSendSync, Unique, UniqueView, World};
207    ///
208    /// let world = World::new();
209    ///
210    /// #[derive(Unique)]
211    /// struct U32(u32);
212    ///
213    /// // I'm using `u32` here but imagine it's a `!Send + !Sync` type
214    /// world.add_unique_non_send_sync(U32(0));
215    ///
216    /// let i = world.borrow::<NonSendSync<UniqueView<U32>>>().unwrap();
217    /// assert_eq!(i.0, 0);
218    /// ```
219    ///
220    /// [`AllStorages`]: crate::AllStorages
221    /// [`UniqueView`]: crate::UniqueView
222    /// [`UniqueViewMut`]: crate::UniqueViewMut
223    /// [`NonSendSync`]: crate::NonSync
224    #[cfg(feature = "thread_local")]
225    #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
226    #[track_caller]
227    pub fn add_unique_non_send_sync<T: Unique>(&self, component: T) {
228        self.all_storages
229            .borrow()
230            .unwrap()
231            .add_unique_non_send_sync(component);
232    }
233    /// Removes a unique storage.
234    ///
235    /// ### Borrows
236    ///
237    /// - [`AllStorages`] (shared)
238    /// - `Unique<T>` storage (exclusive)
239    ///
240    /// ### Errors
241    ///
242    /// - [`AllStorages`] borrow failed.
243    /// - `Unique<T>` storage borrow failed.
244    /// - `Unique<T>` storage did not exist.
245    ///
246    /// ### Example
247    ///
248    /// ```
249    /// use shipyard::{Unique, UniqueView, World};
250    ///
251    /// #[derive(Unique, Debug)]
252    /// struct U32(u32);
253    ///
254    /// let world = World::new();
255    ///
256    /// world.add_unique(U32(0));
257    ///
258    /// let i = world.remove_unique::<U32>().unwrap();
259    /// assert_eq!(i.0, 0);
260    /// ```
261    ///
262    /// [`AllStorages`]: crate::AllStorages
263    pub fn remove_unique<T: Unique>(&self) -> Result<T, error::UniqueRemove> {
264        self.all_storages
265            .borrow()
266            .map_err(|_| error::UniqueRemove::AllStorages)?
267            .remove_unique::<T>()
268    }
269    #[doc = "Borrows the requested storages, if they don't exist they'll get created.
270You can use a tuple to get multiple storages at once.
271
272You can use:
273* [View]\\<T\\> for a shared access to `T` storage
274* [ViewMut]\\<T\\> for an exclusive access to `T` storage
275* [EntitiesView] for a shared access to the entity storage
276* [EntitiesViewMut] for an exclusive reference to the entity storage
277* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
278* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
279* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
280* `Option<V>` with one or multiple views for fallible access to one or more storages"]
281    #[cfg_attr(
282        all(feature = "thread_local", docsrs),
283        doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
284    )]
285    #[cfg_attr(
286        all(feature = "thread_local", docsrs),
287        doc = "    * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
288    * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
289[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
290    )]
291    #[cfg_attr(
292        all(feature = "thread_local", not(docsrs)),
293        doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
294* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
295[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
296    )]
297    #[cfg_attr(
298        not(feature = "thread_local"),
299        doc = "* NonSend: must activate the *thread_local* feature"
300    )]
301    #[cfg_attr(
302        all(feature = "thread_local", docsrs),
303        doc = "    * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
304    * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
305[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
306    )]
307    #[cfg_attr(
308        all(feature = "thread_local", not(docsrs)),
309        doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
310* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
311[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
312    )]
313    #[cfg_attr(
314        not(feature = "thread_local"),
315        doc = "* NonSync: must activate the *thread_local* feature"
316    )]
317    #[cfg_attr(
318        all(feature = "thread_local", docsrs),
319        doc = "    * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
320    * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
321[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
322    )]
323    #[cfg_attr(
324        all(feature = "thread_local", not(docsrs)),
325        doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
326* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
327[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
328    )]
329    #[cfg_attr(
330        not(feature = "thread_local"),
331        doc = "* NonSendSync: must activate the *thread_local* feature"
332    )]
333    #[doc = "
334### Borrows
335
336- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
337- [AllStorages] (shared) + storage (exclusive or shared) for all other views
338
339### Errors
340
341- [AllStorages] borrow failed.
342- Storage borrow failed.
343- Unique storage did not exist.
344
345### Example
346```
347use shipyard::{Component, EntitiesView, View, ViewMut, World};
348
349#[derive(Component)]
350struct U32(u32);
351
352#[derive(Component)]
353struct USIZE(usize);
354
355let world = World::new();
356
357let u32s = world.borrow::<View<U32>>().unwrap();
358let (entities, mut usizes) = world
359    .borrow::<(EntitiesView, ViewMut<USIZE>)>()
360    .unwrap();
361```
362[AllStorages]: crate::AllStorages
363[EntitiesView]: crate::Entities
364[EntitiesViewMut]: crate::Entities
365[AllStoragesViewMut]: crate::AllStorages
366[World]: crate::World
367[View]: crate::View
368[ViewMut]: crate::ViewMut
369[UniqueView]: crate::UniqueView
370[UniqueViewMut]: crate::UniqueViewMut"]
371    #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::NonSend")]
372    #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::NonSync")]
373    #[cfg_attr(feature = "thread_local", doc = "[NonSendSync]: crate::NonSendSync")]
374    pub fn borrow<V: WorldBorrow>(&self) -> Result<V::WorldView<'_>, error::GetStorage> {
375        let current = self.get_current();
376
377        V::world_borrow(self, None, current)
378    }
379    #[doc = "Borrows the requested storages, runs the function and evaluates to the function's return value.
380Data can be passed to the function, this always has to be a single type but you can use a tuple if needed.
381
382You can use:
383* [View]\\<T\\> for a shared access to `T` storage
384* [ViewMut]\\<T\\> for an exclusive access to `T` storage
385* [EntitiesView] for a shared access to the entity storage
386* [EntitiesViewMut] for an exclusive reference to the entity storage
387* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
388* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
389* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
390* `Option<V>` with one or multiple views for fallible access to one or more storages"]
391    #[cfg_attr(
392        all(feature = "thread_local", docsrs),
393        doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
394    )]
395    #[cfg_attr(
396        all(feature = "thread_local", docsrs),
397        doc = "    * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
398    * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
399[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
400    )]
401    #[cfg_attr(
402        all(feature = "thread_local", not(docsrs)),
403        doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
404* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
405[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
406    )]
407    #[cfg_attr(
408        not(feature = "thread_local"),
409        doc = "* NonSend: must activate the *thread_local* feature"
410    )]
411    #[cfg_attr(
412        all(feature = "thread_local", docsrs),
413        doc = "    * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
414    * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
415[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
416    )]
417    #[cfg_attr(
418        all(feature = "thread_local", not(docsrs)),
419        doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
420* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
421[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
422    )]
423    #[cfg_attr(
424        not(feature = "thread_local"),
425        doc = "* NonSync: must activate the *thread_local* feature"
426    )]
427    #[cfg_attr(
428        all(feature = "thread_local", docsrs),
429        doc = "    * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
430    * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
431[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
432    )]
433    #[cfg_attr(
434        all(feature = "thread_local", not(docsrs)),
435        doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
436* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
437[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
438    )]
439    #[cfg_attr(
440        not(feature = "thread_local"),
441        doc = "* NonSendSync: must activate the *thread_local* feature"
442    )]
443    #[doc = "
444### Borrows
445
446- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
447- [AllStorages] (shared) + storage (exclusive or shared) for all other views
448
449### Panics
450
451- [AllStorages] borrow failed.
452- Storage borrow failed.
453- Unique storage did not exist.
454- Error returned by user.
455
456### Example
457```
458use shipyard::{Component, EntityId, Get, ViewMut, World};
459
460#[derive(Component)]
461struct Position([f32; 2]);
462
463fn sys1((entity, [x, y]): (EntityId, [f32; 2]), mut positions: ViewMut<Position>) {
464    if let Ok(mut pos) = (&mut positions).get(entity) {
465        pos.0 = [x, y];
466    }
467}
468
469let world = World::new();
470
471world.run_with_data(sys1, (EntityId::dead(), [0., 0.]));
472```
473[AllStorages]: crate::AllStorages
474[EntitiesView]: crate::Entities
475[EntitiesViewMut]: crate::Entities
476[AllStoragesViewMut]: crate::AllStorages
477[World]: crate::World
478[View]: crate::View
479[ViewMut]: crate::ViewMut
480[UniqueView]: crate::UniqueView
481[UniqueViewMut]: crate::UniqueViewMut"]
482    #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::NonSend")]
483    #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::NonSync")]
484    #[cfg_attr(feature = "thread_local", doc = "[NonSendSync]: crate::NonSendSync")]
485    #[track_caller]
486    pub fn run_with_data<Data, B, S: System<(Data,), B>>(
487        &self,
488        system: S,
489        data: Data,
490    ) -> S::Return {
491        #[cfg(feature = "tracing")]
492        let system_span = tracing::info_span!("system", name = ?core::any::type_name::<S>());
493        #[cfg(feature = "tracing")]
494        let _system_span = system_span.enter();
495
496        system
497            .run((data,), self)
498            .map_err(error::Run::GetStorage)
499            .unwrap()
500    }
501    #[doc = "Borrows the requested storages, runs the function and evaluates to the function's return value.
502
503You can use:
504* [View]\\<T\\> for a shared access to `T` storage
505* [ViewMut]\\<T\\> for an exclusive access to `T` storage
506* [EntitiesView] for a shared access to the entity storage
507* [EntitiesViewMut] for an exclusive reference to the entity storage
508* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
509* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
510* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
511* `Option<V>` with one or multiple views for fallible access to one or more storages"]
512    #[cfg_attr(
513        all(feature = "thread_local", docsrs),
514        doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
515    )]
516    #[cfg_attr(
517        all(feature = "thread_local", docsrs),
518        doc = "    * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
519    * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
520[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
521    )]
522    #[cfg_attr(
523        all(feature = "thread_local", not(docsrs)),
524        doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
525* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
526[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
527    )]
528    #[cfg_attr(
529        not(feature = "thread_local"),
530        doc = "* NonSend: must activate the *thread_local* feature"
531    )]
532    #[cfg_attr(
533        all(feature = "thread_local", docsrs),
534        doc = "    * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
535    * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
536[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
537    )]
538    #[cfg_attr(
539        all(feature = "thread_local", not(docsrs)),
540        doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
541* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
542[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
543    )]
544    #[cfg_attr(
545        not(feature = "thread_local"),
546        doc = "* NonSync: must activate the *thread_local* feature"
547    )]
548    #[cfg_attr(
549        all(feature = "thread_local", docsrs),
550        doc = "    * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
551    * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
552[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
553    )]
554    #[cfg_attr(
555        all(feature = "thread_local", not(docsrs)),
556        doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
557* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
558[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
559    )]
560    #[cfg_attr(
561        not(feature = "thread_local"),
562        doc = "* NonSendSync: must activate the *thread_local* feature"
563    )]
564    #[doc = "
565### Borrows
566
567- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
568- [AllStorages] (shared) + storage (exclusive or shared) for all other views
569
570### Panics
571
572- [AllStorages] borrow failed.
573- Storage borrow failed.
574- Unique storage did not exist.
575- Error returned by user.
576
577### Example
578```
579use shipyard::{Component, View, ViewMut, World};
580
581#[derive(Component)]
582struct I32(i32);
583
584#[derive(Component)]
585struct USIZE(usize);
586
587#[derive(Component)]
588struct U32(u32);
589
590fn sys1(i32s: View<I32>) -> i32 {
591    0
592}
593
594let world = World::new();
595
596world
597    .run(|usizes: View<USIZE>, mut u32s: ViewMut<U32>| {
598        // -- snip --
599    });
600
601let i = world.run(sys1);
602```
603[AllStorages]: crate::AllStorages
604[EntitiesView]: crate::Entities
605[EntitiesViewMut]: crate::Entities
606[AllStoragesViewMut]: crate::AllStorages
607[World]: crate::World
608[View]: crate::View
609[ViewMut]: crate::ViewMut
610[UniqueView]: crate::UniqueView
611[UniqueViewMut]: crate::UniqueViewMut"]
612    #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::NonSend")]
613    #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::NonSync")]
614    #[cfg_attr(feature = "thread_local", doc = "[NonSendSync]: crate::NonSendSync")]
615    #[track_caller]
616    pub fn run<B, S: System<(), B>>(&self, system: S) -> S::Return {
617        #[cfg(feature = "tracing")]
618        let system_span = tracing::info_span!("system", name = ?core::any::type_name::<S>());
619        #[cfg(feature = "tracing")]
620        let _system_span = system_span.enter();
621
622        system
623            .run((), self)
624            .map_err(error::Run::GetStorage)
625            .unwrap()
626    }
627    /// Modifies the current default workload to `name`.
628    ///
629    /// ### Borrows
630    ///
631    /// - Scheduler (exclusive)
632    ///
633    /// ### Errors
634    ///
635    /// - Scheduler borrow failed.
636    /// - Workload did not exist.
637    pub fn set_default_workload<T>(
638        &self,
639        name: impl AsLabel<T>,
640    ) -> Result<(), error::SetDefaultWorkload> {
641        self.scheduler
642            .borrow_mut()
643            .map_err(|_| error::SetDefaultWorkload::Borrow)?
644            .set_default(name.as_label())
645    }
646    /// Changes the name of a workload if it exists.
647    ///
648    /// ### Borrows
649    ///
650    /// - Scheduler (exclusive)
651    ///
652    /// ### Panics
653    ///
654    /// - Scheduler borrow failed.
655    #[track_caller]
656    pub fn rename_workload<T, U>(&self, old_name: impl AsLabel<T>, new_name: impl AsLabel<U>) {
657        let old_label = old_name.as_label();
658        let new_label = new_name.as_label();
659
660        self.scheduler
661            .borrow_mut()
662            .unwrap()
663            .rename(&old_label, Box::new(new_label));
664    }
665    /// Runs the `name` workload.
666    ///
667    /// ### Borrows
668    ///
669    /// - Scheduler (shared)
670    /// - Systems' borrow as they are executed
671    ///
672    /// ### Errors
673    ///
674    /// - Scheduler borrow failed.
675    /// - Workload did not exist.
676    /// - Storage borrow failed.
677    /// - User error returned by system.
678    pub fn run_workload<T>(&self, label: impl AsLabel<T>) -> Result<(), error::RunWorkload> {
679        let scheduler = self
680            .scheduler
681            .borrow()
682            .map_err(|_| error::RunWorkload::Scheduler)?;
683
684        let label = label.as_label();
685        let batches = scheduler.workload(&*label)?;
686
687        self.run_batches(
688            &scheduler.systems,
689            &scheduler.system_names,
690            batches,
691            &*label,
692        )
693    }
694    /// Returns `true` if the world contains the `name` workload.
695    ///
696    /// ### Borrows
697    ///
698    /// - Scheduler (shared)
699    ///
700    /// ### Panics
701    ///
702    /// - Scheduler borrow failed.
703    ///
704    /// ### Example
705    /// ```
706    /// use shipyard::{Workload, World};
707    ///
708    /// let world = World::new();
709    ///
710    /// Workload::new("foo").add_to_world(&world).unwrap();
711    ///
712    /// assert!(world.contains_workload("foo"));
713    /// assert!(!world.contains_workload("bar"));
714    /// ```
715    #[track_caller]
716    pub fn contains_workload<T>(&self, name: impl AsLabel<T>) -> bool {
717        let label = name.as_label();
718
719        self.scheduler.borrow().unwrap().contains_workload(&*label)
720    }
721    #[allow(clippy::type_complexity)]
722    pub(crate) fn run_batches(
723        &self,
724        systems: &[Box<dyn Fn(&World) -> Result<(), error::Run> + Send + Sync + 'static>],
725        system_names: &[Box<dyn Label>],
726        batches: &Batches,
727        workload_name: &dyn Label,
728    ) -> Result<(), error::RunWorkload> {
729        if let Some(run_if) = &batches.run_if {
730            if !run_if
731                .run(self)
732                .map_err(|err| error::RunWorkload::Run((workload_name.dyn_clone(), err)))?
733            {
734                return Ok(());
735            }
736        }
737
738        #[cfg(feature = "parallel")]
739        {
740            self.run_batches_parallel(systems, system_names, batches, workload_name)
741        }
742
743        #[cfg(not(feature = "parallel"))]
744        {
745            self.run_batches_sequential(systems, system_names, batches, workload_name)
746        }
747    }
748    /// Run the default workload if there is one.
749    ///
750    /// ### Borrows
751    ///
752    /// - Scheduler (shared)
753    /// - Systems' borrow as they are executed
754    ///
755    /// ### Errors
756    ///
757    /// - Scheduler borrow failed.
758    /// - Storage borrow failed.
759    /// - User error returned by system.
760    pub fn run_default_workload(&self) -> Result<(), error::RunWorkload> {
761        let scheduler = self
762            .scheduler
763            .borrow()
764            .map_err(|_| error::RunWorkload::Scheduler)?;
765
766        if !scheduler.is_empty() {
767            self.run_batches(
768                &scheduler.systems,
769                &scheduler.system_names,
770                scheduler.default_workload(),
771                &scheduler.default,
772            )?
773        }
774        Ok(())
775    }
776    /// Returns a `Ref<&AllStorages>`, used to implement custom storages.
777    /// To borrow `AllStorages` you should use `borrow` or `run` with `AllStoragesViewMut`.
778    ///
779    /// ### Errors
780    ///
781    /// - `AllStorages` is already borrowed.
782    pub fn all_storages(&self) -> Result<ARef<'_, &'_ AllStorages>, error::Borrow> {
783        self.all_storages.borrow()
784    }
785    /// Returns a `RefMut<&mut AllStorages>`, used to implement custom storages.
786    /// To borrow `AllStorages` you should use `borrow` or `run` with `AllStoragesViewMut`.
787    ///
788    /// ### Errors
789    ///
790    /// - `AllStorages` is already borrowed.
791    pub fn all_storages_mut(&self) -> Result<ARefMut<'_, &'_ mut AllStorages>, error::Borrow> {
792        self.all_storages.borrow_mut()
793    }
794    /// Inserts a custom storage to the `World`.
795    ///
796    /// ### Errors
797    ///
798    /// - `AllStorages` is already borrowed exclusively.
799    pub fn add_custom_storage<S: 'static + Storage + Send + Sync>(
800        &self,
801        storage_id: StorageId,
802        storage: S,
803    ) -> Result<(), error::Borrow> {
804        let _ = self
805            .all_storages
806            .borrow()?
807            .custom_storage_or_insert_by_id(storage_id, || storage);
808
809        Ok(())
810    }
811
812    /// Increments the current tracking cycle and returns the previous value.
813    #[inline]
814    pub(crate) fn get_current(&self) -> TrackingTimestamp {
815        TrackingTimestamp::new(
816            self.counter
817                .fetch_add(1, core::sync::atomic::Ordering::Acquire),
818        )
819    }
820
821    /// Returns a timestamp used to clear tracking information.
822    pub fn get_tracking_timestamp(&self) -> TrackingTimestamp {
823        TrackingTimestamp::new(self.counter.load(core::sync::atomic::Ordering::Acquire))
824    }
825}
826
827impl World {
828    /// Creates a new entity with the components passed as argument and returns its `EntityId`.
829    /// `component` must always be a tuple, even for a single component.
830    ///
831    /// ### Example
832    ///
833    /// ```
834    /// use shipyard::{Component, World};
835    ///
836    /// #[derive(Component)]
837    /// struct U32(u32);
838    ///
839    /// #[derive(Component)]
840    /// struct USIZE(usize);
841    ///
842    /// let mut world = World::new();
843    ///
844    /// let entity0 = world.add_entity((U32(0),));
845    /// let entity1 = world.add_entity((U32(1), USIZE(11)));
846    /// ```
847    #[inline]
848    pub fn add_entity<C: TupleAddComponent>(&mut self, component: C) -> EntityId {
849        self.all_storages.get_mut().add_entity(component)
850    }
851    /// Creates multiple new entities and returns an iterator yielding the new `EntityId`s.
852    /// `source` must always yield a tuple, even for a single component.
853    ///
854    /// ### Example
855    ///
856    /// ```
857    /// use shipyard::{Component, World};
858    ///
859    /// #[derive(Component)]
860    /// struct U32(u32);
861    ///
862    /// #[derive(Component)]
863    /// struct USIZE(usize);
864    ///
865    /// let mut world = World::new();
866    ///
867    /// let new_entities = world.bulk_add_entity((10..20).map(|i| (U32(i as u32), USIZE(i))));
868    /// ```
869    #[inline]
870    pub fn bulk_add_entity<T: BulkAddEntity>(&mut self, source: T) -> BulkEntityIter<'_> {
871        self.all_storages.get_mut().bulk_add_entity(source)
872    }
873    /// Adds components to an existing entity.
874    /// If the entity already owned a component it will be replaced.
875    /// `component` must always be a tuple, even for a single component.
876    ///
877    /// ### Panics
878    ///
879    /// - `entity` is not alive.
880    ///
881    /// ### Example
882    ///
883    /// ```
884    /// use shipyard::{Component, World};
885    ///
886    /// #[derive(Component)]
887    /// struct U32(u32);
888    ///
889    /// #[derive(Component)]
890    /// struct USIZE(usize);
891    ///
892    /// let mut world = World::new();
893    ///
894    /// // make an empty entity
895    /// let entity = world.add_entity(());
896    ///
897    /// world.add_component(entity, (U32(0),));
898    /// // entity already had a `U32` component so it will be replaced
899    /// world.add_component(entity, (U32(1), USIZE(11)));
900    /// ```
901    #[track_caller]
902    #[inline]
903    pub fn add_component<C: TupleAddComponent>(&mut self, entity: EntityId, component: C) {
904        self.all_storages.get_mut().add_component(entity, component)
905    }
906    /// Deletes components from an entity. As opposed to `remove`, `delete` doesn't return anything.
907    /// `C` must always be a tuple, even for a single component.
908    ///
909    /// ### Example
910    ///
911    /// ```
912    /// use shipyard::{Component, World};
913    ///
914    /// #[derive(Component, Debug, PartialEq, Eq)]
915    /// struct U32(u32);
916    ///
917    /// #[derive(Component)]
918    /// struct USIZE(usize);
919    ///
920    /// let mut world = World::new();
921    ///
922    /// let entity = world.add_entity((U32(0), USIZE(1)));
923    ///
924    /// world.delete_component::<(U32,)>(entity);
925    /// ```
926    #[inline]
927    pub fn delete_component<C: TupleDelete>(&mut self, entity: EntityId) {
928        self.all_storages.get_mut().delete_component::<C>(entity)
929    }
930    /// Removes components from an entity.
931    /// `C` must always be a tuple, even for a single component.
932    ///
933    /// ### Example
934    ///
935    /// ```
936    /// use shipyard::{Component, World};
937    ///
938    /// #[derive(Component, Debug, PartialEq, Eq)]
939    /// struct U32(u32);
940    ///
941    /// #[derive(Component)]
942    /// struct USIZE(usize);
943    ///
944    /// let mut world = World::new();
945    ///
946    /// let entity = world.add_entity((U32(0), USIZE(1)));
947    ///
948    /// let (i,) = world.remove::<(U32,)>(entity);
949    /// assert_eq!(i, Some(U32(0)));
950    /// ```
951    #[inline]
952    pub fn remove<C: TupleRemove>(&mut self, entity: EntityId) -> C::Out {
953        self.all_storages.get_mut().remove::<C>(entity)
954    }
955    /// Deletes an entity with all its components. Returns true if the entity were alive.
956    ///
957    /// ### Example
958    ///
959    /// ```
960    /// use shipyard::{Component, World};
961    ///
962    /// #[derive(Component)]
963    /// struct U32(u32);
964    ///
965    /// #[derive(Component)]
966    /// struct USIZE(usize);
967    ///
968    /// let mut world = World::new();
969    ///
970    /// let entity = world.add_entity((U32(0), USIZE(1)));
971    ///
972    /// assert!(world.delete_entity(entity));
973    /// ```
974    #[inline]
975    pub fn delete_entity(&mut self, entity: EntityId) -> bool {
976        self.all_storages.get_mut().delete_entity(entity)
977    }
978    /// Deletes all components of an entity without deleting the entity.
979    ///
980    /// ### Example
981    ///
982    /// ```
983    /// use shipyard::{Component, World};
984    ///
985    /// #[derive(Component)]
986    /// struct U32(u32);
987    ///
988    /// #[derive(Component)]
989    /// struct USIZE(usize);
990    ///
991    /// let mut world = World::new();
992    ///
993    /// let entity = world.add_entity((U32(0), USIZE(1)));
994    ///
995    /// world.strip(entity);
996    /// ```
997    #[inline]
998    pub fn strip(&mut self, entity: EntityId) {
999        self.all_storages.get_mut().strip(entity);
1000    }
1001    /// Deletes all entities with any of the given components.
1002    /// The storage's type has to be used and not the component.
1003    /// `SparseSet` is the default storage.
1004    ///
1005    /// ### Example
1006    ///
1007    /// ```
1008    /// use shipyard::{Component, SparseSet, World};
1009    ///
1010    /// #[derive(Component)]
1011    /// struct U32(u32);
1012    ///
1013    /// #[derive(Component)]
1014    /// struct USIZE(usize);
1015    ///
1016    /// #[derive(Component)]
1017    /// struct STR(&'static str);
1018    ///
1019    /// let mut world = World::new();
1020    ///
1021    /// let entity0 = world.add_entity((U32(0),));
1022    /// let entity1 = world.add_entity((USIZE(1),));
1023    /// let entity2 = world.add_entity((STR("2"),));
1024    ///
1025    /// // deletes `entity2`
1026    /// world.delete_any::<SparseSet<STR>>();
1027    /// // deletes `entity0` and `entity1`
1028    /// world.delete_any::<(SparseSet<U32>, SparseSet<USIZE>)>();
1029    /// ```
1030    #[inline]
1031    pub fn delete_any<S: TupleDeleteAny>(&mut self) {
1032        self.all_storages.get_mut().delete_any::<S>();
1033    }
1034    /// Deletes all components of an entity except the ones passed in `S`.
1035    /// The storage's type has to be used and not the component.
1036    /// `SparseSet` is the default storage.
1037    ///
1038    /// ### Example
1039    ///
1040    /// ```
1041    /// use shipyard::{Component, SparseSet, World};
1042    ///
1043    /// #[derive(Component)]
1044    /// struct U32(u32);
1045    ///
1046    /// #[derive(Component)]
1047    /// struct USIZE(usize);
1048    ///
1049    /// let mut world = World::new();
1050    ///
1051    /// let entity = world.add_entity((U32(0), USIZE(1)));
1052    ///
1053    /// world.retain_storage::<SparseSet<U32>>(entity);
1054    /// ```
1055    #[inline]
1056    pub fn retain_storage<S: TupleRetainStorage>(&mut self, entity: EntityId) {
1057        self.all_storages.get_mut().retain_storage::<S>(entity);
1058    }
1059    /// Same as `retain_storage` but uses `StorageId` and not generics.
1060    /// You should only use this method if you use a custom storage with a runtime id.
1061    #[inline]
1062    pub fn retain_storage_by_id(&mut self, entity: EntityId, excluded_storage: &[StorageId]) {
1063        self.all_storages
1064            .get_mut()
1065            .retain_storage_by_id(entity, excluded_storage);
1066    }
1067    /// Deletes all entities and components in the `World`.
1068    ///
1069    /// ### Example
1070    ///
1071    /// ```
1072    /// use shipyard::World;
1073    ///
1074    /// let mut world = World::new();
1075    ///
1076    /// world.clear();
1077    /// ```
1078    #[inline]
1079    pub fn clear(&mut self) {
1080        self.all_storages.get_mut().clear();
1081    }
1082    /// Clear all deletion and removal tracking data.
1083    pub fn clear_all_removed_and_deleted(&mut self) {
1084        self.all_storages.get_mut().clear_all_removed_and_deleted()
1085    }
1086    /// Clear all deletion and removal tracking data older than some timestamp.
1087    pub fn clear_all_removed_and_deleted_older_than_timestamp(
1088        &mut self,
1089        timestamp: TrackingTimestamp,
1090    ) {
1091        self.all_storages
1092            .get_mut()
1093            .clear_all_removed_and_deleted_older_than_timestamp(timestamp)
1094    }
1095    /// Make the given entity alive.
1096    /// Does nothing if an entity with a greater generation is already at this index.
1097    /// Returns `true` if the entity is successfully spawned.
1098    #[inline]
1099    pub fn spawn(&mut self, entity: EntityId) -> bool {
1100        self.all_storages.get_mut().spawn(entity)
1101    }
1102
1103    /// Deletes all components for which `f(id, &component)` returns `false`.
1104    ///
1105    /// # Panics
1106    ///
1107    /// - Storage borrow failed.
1108    pub fn retain<T: Component + Send + Sync>(&mut self, f: impl FnMut(EntityId, &T) -> bool) {
1109        self.all_storages.get_mut().retain(f);
1110    }
1111
1112    /// Deletes all components for which `f(id, Mut<component>)` returns `false`.
1113    ///
1114    /// # Panics
1115    ///
1116    /// - Storage borrow failed.
1117    pub fn retain_mut<T: Component + Send + Sync>(
1118        &mut self,
1119        f: impl FnMut(EntityId, Mut<'_, T>) -> bool,
1120    ) {
1121        self.all_storages.get_mut().retain_mut(f);
1122    }
1123
1124    /// Displays storages memory information.
1125    pub fn memory_usage(&self) -> WorldMemoryUsage<'_> {
1126        WorldMemoryUsage(self)
1127    }
1128    /// Returns a list of workloads and all information related to them.
1129    ///
1130    /// ### Borrows
1131    ///
1132    /// - Scheduler (shared)
1133    ///
1134    /// ### Panics
1135    ///
1136    /// - Scheduler borrow failed.
1137    #[track_caller]
1138    pub fn workloads_info(&self) -> WorkloadsInfo {
1139        let scheduler = self.scheduler.borrow().unwrap();
1140
1141        WorkloadsInfo(
1142            scheduler
1143                .workloads_info
1144                .iter()
1145                .map(|(name, workload_info)| (format!("{:?}", name), workload_info.clone()))
1146                .collect(),
1147        )
1148    }
1149
1150    /// Enable insertion tracking for the given components.
1151    pub fn track_insertion<T: TupleTrack>(&mut self) -> &mut World {
1152        self.all_storages.get_mut().track_insertion::<T>();
1153        self
1154    }
1155
1156    /// Enable modification tracking for the given components.
1157    pub fn track_modification<T: TupleTrack>(&mut self) -> &mut World {
1158        self.all_storages.get_mut().track_modification::<T>();
1159        self
1160    }
1161
1162    /// Enable deletion tracking for the given components.
1163    pub fn track_deletion<T: TupleTrack>(&mut self) -> &mut World {
1164        self.all_storages.get_mut().track_deletion::<T>();
1165        self
1166    }
1167
1168    /// Enable removal tracking for the given components.
1169    pub fn track_removal<T: TupleTrack>(&mut self) -> &mut World {
1170        self.all_storages.get_mut().track_removal::<T>();
1171        self
1172    }
1173
1174    /// Enable insertion, deletion and removal tracking for the given components.
1175    pub fn track_all<T: TupleTrack>(&mut self) {
1176        self.all_storages.get_mut().track_all::<T>();
1177    }
1178
1179    #[doc = "Retrieve components of `entity`.
1180
1181Multiple components can be queried at the same time using a tuple.
1182
1183You can use:
1184* `&T` for a shared access to `T` component
1185* `&mut T` for an exclusive access to `T` component"]
1186    #[cfg_attr(
1187        all(feature = "thread_local", docsrs),
1188        doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
1189    )]
1190    #[cfg_attr(
1191        all(feature = "thread_local"),
1192        doc = "* [NonSend]<&T> for a shared access to a `T` component where `T` isn't `Send`
1193* [NonSend]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send`
1194* [NonSync]<&T> for a shared access to a `T` component where `T` isn't `Sync`
1195* [NonSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Sync`
1196* [NonSendSync]<&T> for a shared access to a `T` component where `T` isn't `Send` nor `Sync`
1197* [NonSendSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send` nor `Sync`"
1198    )]
1199    #[cfg_attr(
1200        not(feature = "thread_local"),
1201        doc = "* NonSend: must activate the *thread_local* feature
1202* NonSync: must activate the *thread_local* feature
1203* NonSendSync: must activate the *thread_local* feature"
1204    )]
1205    #[doc = "
1206### Borrows
1207
1208- [AllStorages] (shared) + storage (exclusive or shared)
1209
1210### Errors
1211
1212- [AllStorages] borrow failed.
1213- Storage borrow failed.
1214- Entity does not have the component.
1215
1216### Example
1217```
1218use shipyard::{Component, World};
1219
1220#[derive(Component, Debug, PartialEq, Eq)]
1221struct U32(u32);
1222
1223#[derive(Component, Debug, PartialEq, Eq)]
1224struct USIZE(usize);
1225
1226let mut world = World::new();
1227
1228let entity = world.add_entity((USIZE(0), U32(1)));
1229
1230let (i, j) = world.get::<(&USIZE, &mut U32)>(entity).unwrap();
1231
1232assert!(*i == &USIZE(0));
1233assert!(*j == &U32(1));
1234```"]
1235    #[cfg_attr(
1236        feature = "thread_local",
1237        doc = "[NonSend]: crate::NonSend
1238[NonSync]: crate::NonSync
1239[NonSendSync]: crate::NonSendSync"
1240    )]
1241    #[inline]
1242    pub fn get<T: GetComponent>(
1243        &self,
1244        entity: EntityId,
1245    ) -> Result<T::Out<'_>, error::GetComponent> {
1246        let (all_storages, all_borrow) = unsafe {
1247            ARef::destructure(
1248                self.all_storages
1249                    .borrow()
1250                    .map_err(error::GetStorage::AllStoragesBorrow)?,
1251            )
1252        };
1253
1254        let current = self.get_current();
1255
1256        T::get(all_storages, Some(all_borrow), current, entity)
1257    }
1258
1259    #[doc = "Retrieve a unique component.
1260
1261You can use:
1262* `&T` for a shared access to `T` unique component
1263* `&mut T` for an exclusive access to `T` unique component"]
1264    #[cfg_attr(
1265        all(feature = "thread_local", docsrs),
1266        doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
1267    )]
1268    #[cfg_attr(
1269        all(feature = "thread_local"),
1270        doc = "* [NonSend]<&T> for a shared access to a `T` unique component where `T` isn't `Send`
1271* [NonSend]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Send`
1272* [NonSync]<&T> for a shared access to a `T` unique component where `T` isn't `Sync`
1273* [NonSync]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Sync`
1274* [NonSendSync]<&T> for a shared access to a `T` unique component where `T` isn't `Send` nor `Sync`
1275* [NonSendSync]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Send` nor `Sync`"
1276    )]
1277    #[cfg_attr(
1278        not(feature = "thread_local"),
1279        doc = "* NonSend: must activate the *thread_local* feature
1280* NonSync: must activate the *thread_local* feature
1281* NonSendSync: must activate the *thread_local* feature"
1282    )]
1283    #[doc = "
1284### Borrows
1285
1286- [AllStorages] (shared) + storage (exclusive or shared)
1287
1288### Errors
1289
1290- [AllStorages] borrow failed.
1291- Storage borrow failed.
1292
1293### Example
1294```
1295use shipyard::{Unique, World};
1296
1297#[derive(Unique, Debug, PartialEq, Eq)]
1298struct U32(u32);
1299
1300let mut world = World::new();
1301
1302world.add_unique(U32(0));
1303
1304let i = world.get_unique::<&U32>().unwrap();
1305
1306assert!(*i == U32(0));
1307```"]
1308    #[cfg_attr(
1309        feature = "thread_local",
1310        doc = "[NonSend]: crate::NonSend
1311[NonSync]: crate::NonSync
1312[NonSendSync]: crate::NonSendSync"
1313    )]
1314    #[inline]
1315    pub fn get_unique<T: GetUnique>(&self) -> Result<T::Out<'_>, error::GetStorage> {
1316        let (all_storages, all_borrow) = unsafe {
1317            ARef::destructure(
1318                self.all_storages
1319                    .borrow()
1320                    .map_err(error::GetStorage::AllStoragesBorrow)?,
1321            )
1322        };
1323
1324        T::get_unique(all_storages, Some(all_borrow))
1325    }
1326
1327    #[doc = "Iterate components.
1328
1329Multiple components can be iterated at the same time using a tuple.
1330
1331You can use:
1332* `&T` for a shared access to `T` component
1333* `&mut T` for an exclusive access to `T` component"]
1334    #[cfg_attr(
1335        all(feature = "thread_local", docsrs),
1336        doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
1337    )]
1338    #[cfg_attr(
1339        all(feature = "thread_local"),
1340        doc = "* [NonSend]<&T> for a shared access to a `T` component where `T` isn't `Send`
1341* [NonSend]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send`
1342* [NonSync]<&T> for a shared access to a `T` component where `T` isn't `Sync`
1343* [NonSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Sync`
1344* [NonSendSync]<&T> for a shared access to a `T` component where `T` isn't `Send` nor `Sync`
1345* [NonSendSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send` nor `Sync`"
1346    )]
1347    #[cfg_attr(
1348        not(feature = "thread_local"),
1349        doc = "* NonSend: must activate the *thread_local* feature
1350* NonSync: must activate the *thread_local* feature
1351* NonSendSync: must activate the *thread_local* feature"
1352    )]
1353    #[doc = "
1354### Borrows
1355
1356- [AllStorages] (shared)
1357
1358### Panics
1359
1360- [AllStorages] borrow failed.
1361
1362### Example
1363```
1364use shipyard::{Component, World};
1365
1366#[derive(Component, Debug, PartialEq, Eq)]
1367struct U32(u32);
1368
1369#[derive(Component, Debug, PartialEq, Eq)]
1370struct USIZE(usize);
1371
1372let mut world = World::new();
1373
1374let entity = world.add_entity((USIZE(0), U32(1)));
1375
1376let mut iter = world.iter::<(&USIZE, &mut U32)>();
1377
1378for (i, j) in &mut iter {
1379    // <-- SNIP -->
1380}
1381```"]
1382    #[cfg_attr(
1383        feature = "thread_local",
1384        doc = "[NonSend]: crate::NonSend
1385[NonSync]: crate::NonSync
1386[NonSendSync]: crate::NonSendSync"
1387    )]
1388    #[inline]
1389    #[track_caller]
1390    pub fn iter<T: IterComponent>(&self) -> IntoIterRef<'_, T> {
1391        let (all_storages, all_borrow) = unsafe {
1392            ARef::destructure(
1393                self.all_storages
1394                    .borrow()
1395                    .map_err(error::GetStorage::AllStoragesBorrow)
1396                    .unwrap(),
1397            )
1398        };
1399
1400        let current = self.get_current();
1401
1402        IntoIterRef {
1403            all_storages,
1404            all_borrow: Some(all_borrow),
1405            current,
1406            phantom: core::marker::PhantomData,
1407        }
1408    }
1409
1410    /// Sets the on entity deletion callback.
1411    ///
1412    /// ### Borrows
1413    ///
1414    /// - AllStorages (shared)
1415    /// - Entities (exclusive)
1416    ///
1417    /// ### Panics
1418    ///
1419    /// - AllStorages borrow failed.
1420    /// - Entities borrow failed.
1421    #[track_caller]
1422    pub fn on_deletion(&self, f: impl FnMut(EntityId) + Send + Sync + 'static) {
1423        let mut entities = self.borrow::<EntitiesViewMut<'_>>().unwrap();
1424
1425        entities.on_deletion(f);
1426    }
1427
1428    /// Returns true if entity matches a living entity.
1429    pub fn is_entity_alive(&mut self, entity: EntityId) -> bool {
1430        self.all_storages
1431            .get_mut()
1432            .exclusive_storage_mut::<Entities>()
1433            .unwrap()
1434            .is_alive(entity)
1435    }
1436
1437    /// Moves an entity from a `World` to another.
1438    ///
1439    /// ```
1440    /// use shipyard::{Component, World};
1441    ///
1442    /// #[derive(Component, Debug, PartialEq, Eq)]
1443    /// struct USIZE(usize);
1444    ///
1445    /// let mut world1 = World::new();
1446    /// let mut world2 = World::new();
1447    ///
1448    /// let entity = world1.add_entity(USIZE(1));
1449    ///
1450    /// world1.move_entity(&mut world2, entity);
1451    ///
1452    /// assert!(!world1.is_entity_alive(entity));
1453    /// assert_eq!(world2.get::<&USIZE>(entity).as_deref(), Ok(&&USIZE(1)));
1454    /// ```
1455    #[inline]
1456    #[track_caller]
1457    pub fn move_entity(&mut self, other: &mut World, entity: EntityId) {
1458        let other_all_storages = other.all_storages.get_mut();
1459
1460        self.all_storages
1461            .get_mut()
1462            .move_entity(other_all_storages, entity);
1463    }
1464
1465    /// Moves all components from an entity to another in another `World`.
1466    ///
1467    /// ```
1468    /// use shipyard::{Component, World};
1469    ///
1470    /// #[derive(Component, Debug, PartialEq, Eq)]
1471    /// struct USIZE(usize);
1472    ///
1473    /// let mut world1 = World::new();
1474    /// let mut world2 = World::new();
1475    ///
1476    /// let from = world1.add_entity(USIZE(1));
1477    /// let to = world2.add_entity(());
1478    ///
1479    /// world1.move_components(&mut world2, from, to);
1480    ///
1481    /// assert!(world1.get::<&USIZE>(from).is_err());
1482    /// assert_eq!(world2.get::<&USIZE>(to).as_deref(), Ok(&&USIZE(1)));
1483    /// ```
1484    #[inline]
1485    pub fn move_components(&mut self, other: &mut World, from: EntityId, to: EntityId) {
1486        let other_all_storages = other.all_storages.get_mut();
1487
1488        self.all_storages
1489            .get_mut()
1490            .move_components(other_all_storages, from, to);
1491    }
1492}
1493
1494impl core::fmt::Debug for World {
1495    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1496        let mut debug_struct = f.debug_tuple("World");
1497
1498        if let Ok(all_storages) = self.all_storages.borrow() {
1499            debug_struct.field(&*all_storages);
1500        } else {
1501            debug_struct.field(&"Could not borrow AllStorages");
1502        }
1503
1504        if let Ok(scheduler) = self.scheduler.borrow() {
1505            debug_struct.field(&*scheduler);
1506        } else {
1507            debug_struct.field(&"Could not borrow Scheduler");
1508        }
1509
1510        debug_struct.finish()
1511    }
1512}
1513
1514impl core::fmt::Debug for WorldMemoryUsage<'_> {
1515    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1516        if let Ok(all_storages) = self.0.all_storages.borrow() {
1517            all_storages.memory_usage().fmt(f)
1518        } else {
1519            f.write_str("Could not borrow AllStorages")
1520        }
1521    }
1522}