specs/storage/
deref_flagged.rs1use std::{
2 marker::PhantomData,
3 ops::{Deref, DerefMut},
4};
5
6use hibitset::BitSetLike;
7
8use crate::{
9 storage::{
10 AccessMut, ComponentEvent, DenseVecStorage, Tracked, TryDefault, UnprotectedStorage,
11 },
12 world::{Component, Index},
13};
14
15use shrev::EventChannel;
16
17pub struct DerefFlaggedStorage<C, T = DenseVecStorage<C>> {
26 channel: EventChannel<ComponentEvent>,
27 storage: T,
28 #[cfg(feature = "storage-event-control")]
29 event_emission: bool,
30 phantom: PhantomData<C>,
31}
32
33impl<C, T> DerefFlaggedStorage<C, T> {
34 #[cfg(feature = "storage-event-control")]
35 fn emit_event(&self) -> bool {
36 self.event_emission
37 }
38
39 #[cfg(not(feature = "storage-event-control"))]
40 fn emit_event(&self) -> bool {
41 true
42 }
43}
44
45impl<C, T> Default for DerefFlaggedStorage<C, T>
46where
47 T: TryDefault,
48{
49 fn default() -> Self {
50 Self {
51 channel: EventChannel::<ComponentEvent>::default(),
52 storage: T::unwrap_default(),
53 #[cfg(feature = "storage-event-control")]
54 event_emission: true,
55 phantom: PhantomData,
56 }
57 }
58}
59
60impl<C: Component, T: UnprotectedStorage<C>> UnprotectedStorage<C> for DerefFlaggedStorage<C, T> {
61 type AccessMut<'a> = FlaggedAccessMut<'a, <T as UnprotectedStorage<C>>::AccessMut<'a>, C>
62 where T: 'a;
63
64 unsafe fn clean<B>(&mut self, has: B)
65 where
66 B: BitSetLike,
67 {
68 unsafe { self.storage.clean(has) };
70 }
71
72 unsafe fn get(&self, id: Index) -> &C {
73 unsafe { self.storage.get(id) }
75 }
76
77 unsafe fn get_mut(&mut self, id: Index) -> Self::AccessMut<'_> {
78 let emit = self.emit_event();
79 FlaggedAccessMut {
80 channel: &mut self.channel,
81 emit,
82 id,
83 access: unsafe { self.storage.get_mut(id) },
85 phantom: PhantomData,
86 }
87 }
88
89 unsafe fn insert(&mut self, id: Index, comp: C) {
90 if self.emit_event() {
91 self.channel.single_write(ComponentEvent::Inserted(id));
92 }
93 unsafe { self.storage.insert(id, comp) };
95 }
96
97 unsafe fn remove(&mut self, id: Index) -> C {
98 if self.emit_event() {
99 self.channel.single_write(ComponentEvent::Removed(id));
100 }
101 unsafe { self.storage.remove(id) }
103 }
104}
105
106impl<C, T> Tracked for DerefFlaggedStorage<C, T> {
107 fn channel(&self) -> &EventChannel<ComponentEvent> {
108 &self.channel
109 }
110
111 fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent> {
112 &mut self.channel
113 }
114
115 #[cfg(feature = "storage-event-control")]
116 fn set_event_emission(&mut self, emit: bool) {
117 self.event_emission = emit;
118 }
119
120 #[cfg(feature = "storage-event-control")]
121 fn event_emission(&self) -> bool {
122 self.event_emission
123 }
124}
125
126pub struct FlaggedAccessMut<'a, A, C> {
129 channel: &'a mut EventChannel<ComponentEvent>,
130 emit: bool,
131 id: Index,
132 access: A,
133 phantom: PhantomData<C>,
134}
135
136impl<'a, A, C> Deref for FlaggedAccessMut<'a, A, C>
137where
138 A: Deref<Target = C>,
139{
140 type Target = C;
141
142 fn deref(&self) -> &Self::Target {
143 self.access.deref()
144 }
145}
146
147impl<'a, A, C> DerefMut for FlaggedAccessMut<'a, A, C>
148where
149 A: AccessMut<Target = C>,
150{
151 fn deref_mut(&mut self) -> &mut Self::Target {
152 if self.emit {
153 self.channel.single_write(ComponentEvent::Modified(self.id));
154 }
155 self.access.access_mut()
156 }
157}