async_ecs/access/write_storage.rs
1use crate::{
2 component::Component,
3 entity::Entities,
4 misc::TryDefault,
5 resource::{RefMut, ResourceId},
6 storage::{MaskedStorage, StorageWrapper},
7 system::SystemData,
8 world::World,
9};
10
11/// A storage with read and write access.
12///
13/// Additionally to what `ReadStorage` can do a storage with mutable access
14/// allows:
15///
16/// ## Aliasing
17///
18/// **It is strictly disallowed to fetch both a `ReadStorage` and a
19/// `WriteStorage` of the same component.**
20/// Because Specs uses interior mutability for its resources, we can't check
21/// this at compile time. If you try to do this, you will get a panic.
22///
23/// It is also disallowed to fetch multiple `WriteStorage`s for the same
24/// component.
25///
26/// ## Retrieve components mutably
27///
28/// This works just like `Storage::get`, but returns a mutable reference:
29///
30/// ```
31/// # use async_ecs::*;
32/// # #[derive(Debug, PartialEq)]
33/// # struct Pos(f32); impl Component for Pos { type Storage = VecStorage<Self>; }
34/// #
35/// # let mut world = World::default(); world.register_component::<Pos>();
36/// let entity = world.create_entity().with(Pos(2.0)).build();
37/// # let mut pos_storage = world.component_mut::<Pos>();
38///
39/// assert_eq!(pos_storage.get_mut(entity), Some(&mut Pos(2.0)));
40/// if let Some(pos) = pos_storage.get_mut(entity) {
41/// *pos = Pos(4.5);
42/// }
43///
44/// assert_eq!(pos_storage.get(entity), Some(&Pos(4.5)));
45/// ```
46///
47/// ## Inserting and removing components
48///
49/// You can insert components using `Storage::insert` and remove them
50/// again with `Storage::remove`.
51///
52/// ```
53/// # use async_ecs::*;
54///
55/// # #[derive(Debug, PartialEq)]
56/// # struct Pos(f32);
57/// # impl Component for Pos { type Storage = VecStorage<Self>; }
58/// #
59/// # let mut world = World::default();
60/// # world.register_component::<Pos>();
61/// #
62/// let entity = world.create_entity().with(Pos(0.1)).build();
63/// # let mut pos_storage = world.component_mut::<Pos>();
64///
65/// if let Ok(Some(p)) = pos_storage.insert(entity, Pos(4.0)) {
66/// println!("Overwrote {:?} with a new position", p);
67/// }
68/// ```
69///
70/// There's also an Entry-API similar to the one provided by
71/// `std::collections::HashMap`.
72pub type WriteStorage<'a, T> = StorageWrapper<'a, T, RefMut<'a, MaskedStorage<T>>>;
73
74impl<'a, T> SystemData<'a> for WriteStorage<'a, T>
75where
76 T: Component,
77{
78 fn setup(world: &mut World) {
79 world.register_component_with_storage::<T, _>(TryDefault::unwrap_default);
80 }
81
82 fn fetch(world: &'a World) -> Self {
83 Self::new(world.borrow_mut(), world.borrow())
84 }
85
86 fn reads() -> Vec<ResourceId> {
87 vec![ResourceId::new::<Entities>()]
88 }
89
90 fn writes() -> Vec<ResourceId> {
91 vec![ResourceId::new::<MaskedStorage<T>>()]
92 }
93}