fyrox_resource/
constructor.rs1use crate::{
26 core::{parking_lot::Mutex, uuid::Uuid, SafeLock, TypeUuidProvider},
27 ResourceData,
28};
29use fxhash::FxHashMap;
30
31pub struct ResourceDataConstructor {
33 pub type_name: String,
35 pub callback: Box<dyn FnMut() -> Box<dyn ResourceData> + Send>,
37}
38
39impl ResourceDataConstructor {
40 pub fn create_instance(&mut self) -> Box<dyn ResourceData> {
42 (self.callback)()
43 }
44}
45
46#[derive(Default)]
48pub struct ResourceConstructorContainer {
49 pub map: Mutex<FxHashMap<Uuid, ResourceDataConstructor>>,
51}
52
53impl ResourceConstructorContainer {
54 pub fn new() -> Self {
56 ResourceConstructorContainer::default()
57 }
58
59 pub fn add<T>(&self)
62 where
63 T: ResourceData + Default + TypeUuidProvider,
64 {
65 let previous = self.map.safe_lock().insert(
66 <T as TypeUuidProvider>::type_uuid(),
67 ResourceDataConstructor {
68 callback: Box::new(|| Box::<T>::default()),
69 type_name: std::any::type_name::<T>().to_owned(),
70 },
71 );
72
73 assert!(previous.is_none());
74 }
75
76 pub fn add_custom(&self, type_uuid: Uuid, constructor: ResourceDataConstructor) {
78 self.map.safe_lock().insert(type_uuid, constructor);
79 }
80
81 pub fn remove(&self, type_uuid: Uuid) {
83 self.map.safe_lock().remove(&type_uuid);
84 }
85
86 pub fn try_create(&self, type_uuid: &Uuid) -> Option<Box<dyn ResourceData>> {
89 self.map
90 .safe_lock()
91 .get_mut(type_uuid)
92 .map(|c| c.create_instance())
93 }
94
95 pub fn len(&self) -> usize {
97 self.map.safe_lock().len()
98 }
99
100 pub fn is_empty(&self) -> bool {
102 self.len() == 0
103 }
104}
105
106#[cfg(test)]
107mod test {
108 use fyrox_core::reflect::prelude::*;
109 use fyrox_core::visitor::{Visit, VisitResult, Visitor};
110 use std::error::Error;
111 use std::path::Path;
112
113 use super::*;
114
115 #[derive(Debug, Default, Clone, Reflect, Visit)]
116 struct Stub {}
117
118 impl ResourceData for Stub {
119 fn type_uuid(&self) -> Uuid {
120 Uuid::default()
121 }
122
123 fn save(&mut self, _path: &Path) -> Result<(), Box<dyn Error>> {
124 Err("Saving is not supported!".to_string().into())
125 }
126
127 fn can_be_saved(&self) -> bool {
128 false
129 }
130
131 fn try_clone_box(&self) -> Option<Box<dyn ResourceData>> {
132 Some(Box::new(self.clone()))
133 }
134 }
135
136 impl TypeUuidProvider for Stub {
137 fn type_uuid() -> Uuid {
138 Uuid::default()
139 }
140 }
141
142 #[test]
143 fn resource_constructor_container_new() {
144 let c = ResourceConstructorContainer::new();
145
146 assert_eq!(c.len(), 0);
147
148 c.add::<Stub>();
149 assert_eq!(c.len(), 1);
150 }
151
152 #[test]
153 fn resource_constructor_container_add_custom() {
154 let c = ResourceConstructorContainer::new();
155
156 assert!(c.is_empty());
157
158 c.add_custom(
159 Uuid::default(),
160 ResourceDataConstructor {
161 callback: Box::new(|| Box::<Stub>::default()),
162 type_name: std::any::type_name::<Stub>().to_owned(),
163 },
164 );
165 assert_eq!(c.len(), 1);
166
167 c.remove(Uuid::default());
168 assert!(c.is_empty());
169 }
170
171 #[test]
172 fn resource_constructor_container_try_create() {
173 let c = ResourceConstructorContainer::new();
174 c.add::<Stub>();
175
176 let res = c.try_create(&Uuid::default());
177 assert!(res.is_some());
178 }
179}