fyrox_resource/
constructor.rs1use crate::{
26 core::{parking_lot::Mutex, uuid::Uuid, 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.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.lock().insert(type_uuid, constructor);
79 }
80
81 pub fn remove(&self, type_uuid: Uuid) {
83 self.map.lock().remove(&type_uuid);
84 }
85
86 pub fn try_create(&self, type_uuid: &Uuid) -> Option<Box<dyn ResourceData>> {
89 self.map
90 .lock()
91 .get_mut(type_uuid)
92 .map(|c| c.create_instance())
93 }
94
95 pub fn len(&self) -> usize {
97 self.map.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, 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
132 impl TypeUuidProvider for Stub {
133 fn type_uuid() -> Uuid {
134 Uuid::default()
135 }
136 }
137
138 #[test]
139 fn resource_constructor_container_new() {
140 let c = ResourceConstructorContainer::new();
141
142 assert_eq!(c.len(), 0);
143
144 c.add::<Stub>();
145 assert_eq!(c.len(), 1);
146 }
147
148 #[test]
149 fn resource_constructor_container_add_custom() {
150 let c = ResourceConstructorContainer::new();
151
152 assert!(c.is_empty());
153
154 c.add_custom(
155 Uuid::default(),
156 ResourceDataConstructor {
157 callback: Box::new(|| Box::<Stub>::default()),
158 type_name: std::any::type_name::<Stub>().to_owned(),
159 },
160 );
161 assert_eq!(c.len(), 1);
162
163 c.remove(Uuid::default());
164 assert!(c.is_empty());
165 }
166
167 #[test]
168 fn resource_constructor_container_try_create() {
169 let c = ResourceConstructorContainer::new();
170 c.add::<Stub>();
171
172 let res = c.try_create(&Uuid::default());
173 assert!(res.is_some());
174 }
175}