1use crate::{
24 core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
25 manager::ResourceManager,
26 ResourceData, ResourceLoadError,
27};
28use std::{
29 ops::{Deref, DerefMut},
30 sync::Arc,
31 task::Waker,
32};
33
34#[doc(hidden)]
35#[derive(Reflect, Debug, Default)]
36#[reflect(hide_all)]
37pub struct WakersList(Vec<Waker>);
38
39impl Deref for WakersList {
40 type Target = Vec<Waker>;
41
42 fn deref(&self) -> &Self::Target {
43 &self.0
44 }
45}
46
47impl DerefMut for WakersList {
48 fn deref_mut(&mut self) -> &mut Self::Target {
49 &mut self.0
50 }
51}
52
53#[derive(Reflect, Debug, Clone, Default)]
55#[reflect(hide_all)]
56pub struct LoadError(pub Option<Arc<dyn ResourceLoadError>>);
57
58impl LoadError {
59 pub fn new<T: ResourceLoadError>(value: T) -> Self {
61 Self(Some(Arc::new(value)))
62 }
63}
64
65#[derive(Debug, Reflect)]
77pub enum ResourceState {
78 Pending {
80 wakers: WakersList,
82 },
83 LoadError {
85 error: LoadError,
87 },
88 Ok(Box<dyn ResourceData>),
90}
91
92impl Default for ResourceState {
93 fn default() -> Self {
94 Self::LoadError {
95 error: Default::default(),
96 }
97 }
98}
99
100impl Drop for ResourceState {
101 fn drop(&mut self) {
102 if let ResourceState::Pending { wakers, .. } = self {
103 assert_eq!(wakers.len(), 0);
104 }
105 }
106}
107
108impl Visit for ResourceState {
109 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
110 if visitor.is_reading() {
111 let mut type_uuid = Uuid::default();
112 type_uuid.visit("TypeUuid", visitor)?;
113
114 let resource_manager = visitor.blackboard.get::<ResourceManager>().expect(
115 "Resource data constructor container must be \
116 provided when serializing resources!",
117 );
118 let resource_manager_state = resource_manager.state();
119
120 if let Some(mut instance) = resource_manager_state
121 .constructors_container
122 .try_create(&type_uuid)
123 {
124 drop(resource_manager_state);
125 instance.visit(name, visitor)?;
126 *self = Self::Ok(instance);
127 Ok(())
128 } else {
129 Err(VisitError::User(format!(
130 "There's no constructor registered for type {type_uuid}!"
131 )))
132 }
133 } else if let Self::Ok(instance) = self {
134 instance.visit(name, visitor)?;
135 Ok(())
136 } else {
137 Ok(())
139 }
140 }
141}
142
143impl ResourceState {
144 #[inline]
146 pub fn new_pending() -> Self {
147 Self::Pending {
148 wakers: Default::default(),
149 }
150 }
151
152 #[inline]
154 pub fn new_load_error(error: LoadError) -> Self {
155 Self::LoadError { error }
156 }
157
158 #[inline]
160 pub fn new_ok<T: ResourceData>(data: T) -> Self {
161 Self::Ok(Box::new(data))
162 }
163
164 pub fn is_loading(&self) -> bool {
166 matches!(self, ResourceState::Pending { .. })
167 }
168
169 pub fn switch_to_pending_state(&mut self) {
171 *self = ResourceState::Pending {
172 wakers: Default::default(),
173 };
174 }
175
176 #[inline]
179 pub fn commit(&mut self, state: ResourceState) {
180 assert!(!matches!(state, ResourceState::Pending { .. }));
181
182 let wakers = if let ResourceState::Pending { ref mut wakers } = self {
183 std::mem::take(wakers)
184 } else {
185 unreachable!()
186 };
187
188 *self = state;
189
190 for waker in wakers.0 {
191 waker.wake();
192 }
193 }
194
195 pub fn commit_ok<T: ResourceData>(&mut self, data: T) {
197 self.commit(ResourceState::Ok(Box::new(data)))
198 }
199
200 pub fn commit_error<E: ResourceLoadError>(&mut self, error: E) {
202 self.commit(ResourceState::LoadError {
203 error: LoadError::new(error),
204 })
205 }
206}
207
208#[cfg(test)]
209mod test {
210 use fyrox_core::{
211 reflect::{FieldInfo, Reflect},
212 TypeUuidProvider,
213 };
214 use std::error::Error;
215 use std::path::Path;
216
217 use super::*;
218
219 #[derive(Debug, Default, Reflect, Visit)]
220 struct Stub {}
221
222 impl ResourceData for Stub {
223 fn type_uuid(&self) -> Uuid {
224 Uuid::default()
225 }
226
227 fn save(&mut self, _path: &Path) -> Result<(), Box<dyn Error>> {
228 Err("Saving is not supported!".to_string().into())
229 }
230
231 fn can_be_saved(&self) -> bool {
232 false
233 }
234 }
235
236 impl TypeUuidProvider for Stub {
237 fn type_uuid() -> Uuid {
238 Uuid::default()
239 }
240 }
241
242 #[test]
243 fn resource_state_new_pending() {
244 let state = ResourceState::new_pending();
245
246 assert!(matches!(state, ResourceState::Pending { wakers: _ }));
247 assert!(state.is_loading());
248 }
249
250 #[test]
251 fn resource_state_new_load_error() {
252 let state = ResourceState::new_load_error(Default::default());
253
254 assert!(matches!(state, ResourceState::LoadError { error: _ }));
255 assert!(!state.is_loading());
256 }
257
258 #[test]
259 fn resource_state_new_ok() {
260 let state = ResourceState::new_ok(Stub {});
261 assert!(matches!(state, ResourceState::Ok(_)));
262 assert!(!state.is_loading());
263 }
264
265 #[test]
266 fn resource_state_switch_to_pending_state() {
267 let mut state = ResourceState::new_ok(Stub {});
269 state.switch_to_pending_state();
270
271 assert!(matches!(state, ResourceState::Pending { wakers: _ }));
272
273 let mut state = ResourceState::new_load_error(Default::default());
275 state.switch_to_pending_state();
276
277 assert!(matches!(state, ResourceState::Pending { wakers: _ }));
278
279 let mut state = ResourceState::new_pending();
281 state.switch_to_pending_state();
282
283 assert!(matches!(state, ResourceState::Pending { wakers: _ }));
284 }
285
286 #[test]
287 fn visit_for_resource_state() {
288 let mut state = ResourceState::new_pending();
290 let mut visitor = Visitor::default();
291
292 assert!(state.visit("name", &mut visitor).is_ok());
293
294 let mut state = ResourceState::new_load_error(Default::default());
296 let mut visitor = Visitor::default();
297
298 assert!(state.visit("name", &mut visitor).is_ok());
299
300 let mut state = ResourceState::new_ok(Stub {});
302 let mut visitor = Visitor::default();
303
304 assert!(state.visit("name", &mut visitor).is_ok());
305 }
306}