1use crate::{core::reflect::prelude::*, ResourceData, ResourceLoadError, TypedResourceData};
24use fyrox_core::reflect::ReflectHandle;
25use std::any::{Any, TypeId};
26use std::fmt::{Debug, Display};
27use std::path::PathBuf;
28use std::{
29 ops::{Deref, DerefMut},
30 sync::Arc,
31 task::Waker,
32};
33
34#[doc(hidden)]
35#[derive(Reflect, Debug, Default, Clone)]
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 WakersList {
48 pub fn add_waker(&mut self, cx_waker: &Waker) {
49 if let Some(pos) = self.iter().position(|waker| waker.will_wake(cx_waker)) {
50 self[pos].clone_from(cx_waker);
51 } else {
52 self.push(cx_waker.clone())
53 }
54 }
55}
56
57impl DerefMut for WakersList {
58 fn deref_mut(&mut self) -> &mut Self::Target {
59 &mut self.0
60 }
61}
62
63#[derive(Reflect, Debug, Clone, Default)]
65#[reflect(hide_all)]
66pub struct LoadError(pub Option<Arc<dyn ResourceLoadError>>);
67
68impl std::error::Error for LoadError {}
69
70impl LoadError {
71 pub fn new<T: ResourceLoadError>(value: T) -> Self {
73 Self(Some(Arc::new(value)))
74 }
75}
76
77impl Display for LoadError {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 match &self.0 {
80 None => f.write_str("None"),
81 Some(x) => Display::fmt(x, f),
82 }
83 }
84}
85
86#[doc(hidden)]
87#[derive(Debug)]
88pub struct ResourceDataWrapper(pub Box<dyn ResourceData>);
89
90impl Reflect for ResourceDataWrapper {
91 fn source_path() -> &'static str
92 where
93 Self: Sized,
94 {
95 file!()
96 }
97
98 fn derived_types() -> &'static [TypeId]
99 where
100 Self: Sized,
101 {
102 &[]
103 }
104
105 fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
106 Reflect::try_clone_box(&*self.0)
107 }
108
109 fn query_derived_types(&self) -> &'static [TypeId] {
110 self.deref().query_derived_types()
111 }
112
113 fn type_name(&self) -> &'static str {
114 self.deref().type_name()
115 }
116
117 fn doc(&self) -> &'static str {
118 self.deref().doc()
119 }
120
121 fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) {
122 self.deref().fields_ref(func)
123 }
124
125 fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [FieldMut])) {
126 self.deref_mut().fields_mut(func)
127 }
128
129 fn into_any(self: Box<Self>) -> Box<dyn Any> {
130 self
131 }
132
133 fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
134 self.deref().as_any(func)
135 }
136
137 fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
138 self.deref_mut().as_any_mut(func)
139 }
140
141 fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
142 self.deref().as_reflect(func)
143 }
144
145 fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
146 self.deref_mut().as_reflect_mut(func)
147 }
148
149 fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
150 self.deref_mut().set(value)
151 }
152
153 fn assembly_name(&self) -> &'static str {
154 env!("CARGO_PKG_NAME")
155 }
156
157 fn type_assembly_name() -> &'static str
158 where
159 Self: Sized,
160 {
161 env!("CARGO_PKG_NAME")
162 }
163
164 fn set_field(
165 &mut self,
166 field: &str,
167 value: Box<dyn Reflect>,
168 func: &mut dyn FnMut(Result<Box<dyn Reflect>, SetFieldError>),
169 ) {
170 self.deref_mut().set_field(field, value, func)
171 }
172
173 fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
174 self.deref().field(name, func)
175 }
176
177 fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
178 self.deref_mut().field_mut(name, func)
179 }
180
181 fn as_array(&self, func: &mut dyn FnMut(Option<&dyn ReflectArray>)) {
182 self.deref().as_array(func)
183 }
184
185 fn as_array_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectArray>)) {
186 self.deref_mut().as_array_mut(func)
187 }
188
189 fn as_list(&self, func: &mut dyn FnMut(Option<&dyn ReflectList>)) {
190 self.deref().as_list(func)
191 }
192
193 fn as_list_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectList>)) {
194 self.deref_mut().as_list_mut(func)
195 }
196
197 fn as_inheritable_variable(
198 &self,
199 func: &mut dyn FnMut(Option<&dyn ReflectInheritableVariable>),
200 ) {
201 self.deref().as_inheritable_variable(func)
202 }
203
204 fn as_inheritable_variable_mut(
205 &mut self,
206 func: &mut dyn FnMut(Option<&mut dyn ReflectInheritableVariable>),
207 ) {
208 self.deref_mut().as_inheritable_variable_mut(func)
209 }
210
211 fn as_hash_map(&self, func: &mut dyn FnMut(Option<&dyn ReflectHashMap>)) {
212 self.deref().as_hash_map(func)
213 }
214
215 fn as_hash_map_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectHashMap>)) {
216 self.deref_mut().as_hash_map_mut(func)
217 }
218
219 fn as_handle(&self, func: &mut dyn FnMut(Option<&dyn ReflectHandle>)) {
220 self.deref().as_handle(func)
221 }
222
223 fn as_handle_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectHandle>)) {
224 self.deref_mut().as_handle_mut(func)
225 }
226}
227
228impl Deref for ResourceDataWrapper {
229 type Target = dyn ResourceData;
230
231 fn deref(&self) -> &Self::Target {
232 &*self.0
233 }
234}
235
236impl DerefMut for ResourceDataWrapper {
237 fn deref_mut(&mut self) -> &mut Self::Target {
238 &mut *self.0
239 }
240}
241
242impl Clone for ResourceDataWrapper {
243 fn clone(&self) -> Self {
244 Self(ResourceData::try_clone_box(&*self.0).unwrap())
245 }
246}
247
248#[derive(Clone, Reflect)]
275pub enum ResourceState {
276 Unloaded,
279 Pending {
281 wakers: WakersList,
283 },
284 LoadError {
286 path: PathBuf,
289 error: LoadError,
291 },
292 Ok {
294 data: ResourceDataWrapper,
296 },
297}
298
299impl Debug for ResourceState {
300 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301 match self {
302 Self::Unloaded => write!(f, "Unloaded"),
303 Self::Pending { .. } => write!(f, "Pending"),
304 Self::LoadError { path, error } => write!(f, "LoadError {:?}: {:?}", error, path),
305 Self::Ok { .. } => write!(f, "Ok"),
306 }
307 }
308}
309
310impl Display for ResourceState {
311 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
312 match self {
313 Self::Unloaded => write!(f, "Unloaded"),
314 Self::Pending { .. } => write!(f, "Pending"),
315 Self::LoadError { path, error } => {
316 if path.as_os_str().is_empty() {
317 write!(f, "{} (for unknown path)", error)
318 } else {
319 write!(f, "{} (for {:?})", error, path)
320 }
321 }
322 Self::Ok { .. } => write!(f, "Ok"),
323 }
324 }
325}
326
327impl Default for ResourceState {
328 fn default() -> Self {
329 ResourceState::new_load_error(
330 Default::default(),
331 LoadError::new("Default resource state of unknown type."),
332 )
333 }
334}
335
336impl Drop for ResourceState {
337 fn drop(&mut self) {
338 if let ResourceState::Pending { wakers, .. } = self {
339 assert_eq!(wakers.len(), 0);
340 }
341 }
342}
343
344impl ResourceState {
345 #[inline]
347 pub fn new_pending() -> Self {
348 Self::Pending {
349 wakers: Default::default(),
350 }
351 }
352
353 #[inline]
355 pub fn new_load_error(path: PathBuf, error: LoadError) -> Self {
356 Self::LoadError { path, error }
357 }
358
359 #[inline]
361 pub fn new_ok<T: ResourceData>(data: T) -> Self {
362 Self::Ok {
363 data: ResourceDataWrapper(Box::new(data)),
364 }
365 }
366
367 #[inline]
369 pub fn new_ok_untyped(data: Box<dyn ResourceData>) -> Self {
370 Self::Ok {
371 data: ResourceDataWrapper(data),
372 }
373 }
374
375 pub fn is_loading(&self) -> bool {
377 matches!(self, ResourceState::Pending { .. })
378 }
379
380 pub fn is_ok(&self) -> bool {
382 matches!(self, ResourceState::Ok { .. })
383 }
384
385 pub fn switch_to_pending_state(&mut self) {
387 *self = ResourceState::Pending {
388 wakers: Default::default(),
389 };
390 }
391
392 #[inline]
395 pub fn commit(&mut self, state: ResourceState) {
396 assert!(!matches!(state, ResourceState::Pending { .. }));
397
398 let wakers = if let ResourceState::Pending { ref mut wakers, .. } = self {
399 std::mem::take(wakers)
400 } else {
401 WakersList::default()
402 };
403
404 *self = state;
405
406 for waker in wakers.0 {
407 waker.wake();
408 }
409 }
410
411 pub fn commit_ok<T: ResourceData>(&mut self, data: T) {
413 self.commit(ResourceState::Ok {
414 data: ResourceDataWrapper(Box::new(data)),
415 })
416 }
417
418 pub fn commit_error<E: ResourceLoadError>(&mut self, path: PathBuf, error: E) {
420 self.commit(ResourceState::LoadError {
421 path,
422 error: LoadError::new(error),
423 })
424 }
425
426 pub fn data_ref(&self) -> Option<&ResourceDataWrapper> {
428 match self {
429 ResourceState::Pending { .. }
430 | ResourceState::LoadError { .. }
431 | ResourceState::Unloaded => None,
432 ResourceState::Ok { data, .. } => Some(data),
433 }
434 }
435
436 pub fn data_mut(&mut self) -> Option<&mut ResourceDataWrapper> {
438 match self {
439 ResourceState::Pending { .. }
440 | ResourceState::LoadError { .. }
441 | ResourceState::Unloaded => None,
442 ResourceState::Ok { data, .. } => Some(data),
443 }
444 }
445
446 pub fn data_ref_of_type<T: TypedResourceData>(&self) -> Option<&T> {
449 match self {
450 ResourceState::Pending { .. }
451 | ResourceState::LoadError { .. }
452 | ResourceState::Unloaded => None,
453 ResourceState::Ok { data, .. } => (&**data as &dyn Any).downcast_ref::<T>(),
454 }
455 }
456
457 pub fn data_mut_of_type<T: TypedResourceData>(&mut self) -> Option<&mut T> {
460 match self {
461 ResourceState::Pending { .. }
462 | ResourceState::LoadError { .. }
463 | ResourceState::Unloaded => None,
464 ResourceState::Ok { data, .. } => (&mut **data as &mut dyn Any).downcast_mut::<T>(),
465 }
466 }
467}
468
469#[cfg(test)]
470mod test {
471 use fyrox_core::{
472 reflect::{FieldRef, Reflect},
473 uuid::Uuid,
474 visitor::prelude::*,
475 TypeUuidProvider,
476 };
477 use std::error::Error;
478 use std::path::Path;
479
480 use super::*;
481
482 #[derive(Debug, Default, Clone, Reflect, Visit)]
483 struct Stub {}
484
485 impl ResourceData for Stub {
486 fn type_uuid(&self) -> Uuid {
487 Uuid::default()
488 }
489
490 fn save(&mut self, _path: &Path) -> Result<(), Box<dyn Error>> {
491 Err("Saving is not supported!".to_string().into())
492 }
493
494 fn can_be_saved(&self) -> bool {
495 false
496 }
497
498 fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
499 Some(Box::new(self.clone()))
500 }
501 }
502
503 impl TypeUuidProvider for Stub {
504 fn type_uuid() -> Uuid {
505 Uuid::default()
506 }
507 }
508
509 #[test]
510 fn resource_state_new_pending() {
511 let state = ResourceState::new_pending();
512
513 assert!(matches!(state, ResourceState::Pending { .. }));
514 assert!(state.is_loading());
515 }
516
517 #[test]
518 fn resource_state_new_load_error() {
519 let state = ResourceState::new_load_error(Default::default(), Default::default());
520
521 assert!(matches!(state, ResourceState::LoadError { .. }));
522 assert!(!state.is_loading());
523 }
524
525 #[test]
526 fn resource_state_new_ok() {
527 let state = ResourceState::new_ok(Stub {});
528 assert!(matches!(state, ResourceState::Ok { .. }));
529 assert!(!state.is_loading());
530 }
531
532 #[test]
533 fn resource_state_switch_to_pending_state() {
534 let mut state = ResourceState::new_ok(Stub {});
536 state.switch_to_pending_state();
537
538 assert!(matches!(state, ResourceState::Pending { .. }));
539
540 let mut state = ResourceState::new_load_error(Default::default(), Default::default());
542 state.switch_to_pending_state();
543
544 assert!(matches!(state, ResourceState::Pending { .. }));
545
546 let mut state = ResourceState::new_pending();
548 state.switch_to_pending_state();
549
550 assert!(matches!(state, ResourceState::Pending { .. }));
551 }
552}