async_ecs/access/
read_storage.rs

1use crate::{
2    component::Component,
3    entity::Entities,
4    misc::TryDefault,
5    resource::{Ref, ResourceId},
6    storage::{MaskedStorage, StorageWrapper},
7    system::SystemData,
8    world::World,
9};
10
11/// A storage with read access.
12///
13/// This is just a type alias for a fetched component storage.
14///
15/// The main functionality it provides is listed in the following,
16/// however make sure to also check out the documentation for the
17/// respective methods on `Storage`.
18///
19/// ## Aliasing
20///
21/// **It is strictly disallowed to get both a `ReadStorage` and a `WriteStorage`
22/// of the same component.**
23/// Because Specs uses interior mutability for its resources, we can't check
24/// this at compile time. If you try to do this, you will get a panic.
25///
26/// It is explicitly allowed to get multiple `ReadStorage`s for the same
27/// component.
28///
29/// ## Joining storages
30///
31/// `&ReadStorage` implements `Join`, which allows to do
32/// something like this:
33///
34/// ```
35/// use async_ecs::*;
36///
37/// struct Pos;
38///
39/// impl Component for Pos {
40///     type Storage = VecStorage<Self>;
41/// }
42///
43/// struct Vel;
44///
45/// impl Component for Vel {
46///     type Storage = VecStorage<Self>;
47/// }
48///
49/// let mut world = World::default();
50/// world.register_component::<Pos>();
51/// world.register_component::<Vel>();
52///
53/// let pos_storage = world.component::<Pos>();
54/// let vel_storage = world.component::<Vel>();
55///
56/// for (pos, vel) in (&pos_storage, &vel_storage).join() {}
57/// ```
58///
59/// This joins the position and the velocity storage, which means it only
60/// iterates over the components of entities that have both a position
61/// **and** a velocity.
62///
63/// ## Retrieving single components
64///
65/// If you have an entity (for example because you stored it before
66/// or because you're joining over `Entities`), you can get a single
67/// component by calling `Storage::get`:
68///
69/// ```
70/// # use async_ecs::*;
71/// #
72/// # #[derive(Debug, PartialEq)]
73/// # struct Pos;
74/// # impl Component for Pos { type Storage = VecStorage<Self>; }
75/// #
76/// # #[derive(Debug, PartialEq)]
77/// # struct Vel;
78/// # impl Component for Vel { type Storage = VecStorage<Self>; }
79/// #
80/// # let mut world = World::default();
81/// # world.register_component::<Pos>();
82/// # world.register_component::<Vel>();
83/// #
84/// let entity1 = world.create_entity().with(Pos).build();
85/// let entity2 = world.create_entity().with(Vel).build();
86///
87/// # let pos_storage = world.component::<Pos>();
88/// # let vel_storage = world.component::<Vel>();
89/// assert_eq!(pos_storage.get(entity1), Some(&Pos));
90/// assert_eq!(pos_storage.get(entity2), None);
91///
92/// assert_eq!(vel_storage.get(entity1), None);
93/// assert_eq!(vel_storage.get(entity2), Some(&Vel));
94/// ```
95///
96/// ## Usage as `SystemData`
97///
98/// `ReadStorage` implements `SystemData` which allows you to
99/// get it inside a system by simply adding it to the tuple:
100///
101/// ```
102/// # use async_ecs::*;
103/// #[derive(Debug)]
104/// struct Pos {
105///     x: f32,
106///     y: f32,
107/// }
108///
109/// impl Component for Pos {
110///     type Storage = VecStorage<Self>;
111/// }
112///
113/// struct Sys;
114///
115/// impl<'a> System<'a> for Sys {
116///     type SystemData = (Entities<'a>, ReadStorage<'a, Pos>);
117///
118///     fn run(&mut self, (ent, pos): Self::SystemData) {
119///         for (ent, pos) in (&*ent, &pos).join() {
120///             println!("Entitiy with id {} has a position of {:?}", ent.id(), pos);
121///         }
122///     }
123/// }
124/// ```
125///
126/// These operations can't mutate anything; if you want to do
127/// insertions or modify components, you need to use `WriteStorage`.
128/// Note that you can also use `LazyUpdate` , which does insertions on
129/// `World::maintain`. This allows more concurrency and is designed
130/// to be used for entity initialization.
131pub type ReadStorage<'a, T> = StorageWrapper<'a, T, Ref<'a, MaskedStorage<T>>>;
132
133impl<'a, T> SystemData<'a> for ReadStorage<'a, T>
134where
135    T: Component,
136{
137    fn setup(world: &mut World) {
138        world.register_component_with_storage::<T, _>(TryDefault::unwrap_default);
139    }
140
141    fn fetch(world: &'a World) -> Self {
142        Self::new(world.borrow(), world.borrow())
143    }
144
145    fn reads() -> Vec<ResourceId> {
146        vec![
147            ResourceId::new::<Entities>(),
148            ResourceId::new::<MaskedStorage<T>>(),
149        ]
150    }
151
152    fn writes() -> Vec<ResourceId> {
153        vec![]
154    }
155}