unity_asset/environment/imp/
loader.rs1use super::*;
2
3impl Environment {
4 pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
6 let path = path.as_ref();
7
8 if path.is_file() {
9 self.load_file(path)?;
10 } else if path.is_dir() {
11 self.load_directory(path)?;
12 }
13
14 Ok(())
15 }
16
17 pub fn load_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
19 let path = path.as_ref();
20
21 if let Some(ext) = path.extension() {
23 match ext.to_str() {
24 Some("asset") | Some("prefab") | Some("unity") | Some("meta") => {
25 match YamlDocument::load_yaml_with_warnings(path, false) {
26 Ok((doc, warnings)) => {
27 for w in warnings {
28 self.push_warning(EnvironmentWarning::YamlDocumentSkipped {
29 path: path.to_path_buf(),
30 doc_index: w.doc_index,
31 error: w.error,
32 });
33 }
34 self.yaml_documents.insert(path.to_path_buf(), doc);
35 }
36 Err(_) => {
37 self.try_load_binary(path)?;
40 }
41 }
42 }
43 _ => {
44 self.try_load_binary(path)?;
46 }
47 }
48 } else {
49 self.try_load_binary(path)?;
52 }
53
54 Ok(())
55 }
56
57 fn try_load_binary(&mut self, path: &Path) -> Result<()> {
58 match load_unity_file(path) {
59 Ok(UnityFile::AssetBundle(bundle)) => {
60 let mut bundle = bundle;
61 if let Some(registry) = self.type_tree_registry.clone() {
62 for file in bundle.assets.iter_mut() {
63 file.set_type_tree_registry(Some(registry.clone()));
64 }
65 }
66 let source = BinarySource::path(path);
67 self.bundles.insert(source.clone(), bundle);
68 match self.bundle_container_cache.write() {
69 Ok(mut cache) => {
70 cache.remove(&source);
71 }
72 Err(e) => {
73 let mut cache = e.into_inner();
74 cache.remove(&source);
75 }
76 }
77 }
78 Ok(UnityFile::SerializedFile(asset)) => {
79 let mut asset = asset;
80 if let Some(registry) = self.type_tree_registry.clone() {
81 asset.set_type_tree_registry(Some(registry));
82 }
83 let source = BinarySource::path(path);
84 self.binary_assets.insert(source, asset);
85 match self.bundle_container_cache.write() {
86 Ok(mut cache) => cache.clear(),
87 Err(e) => e.into_inner().clear(),
88 }
89 }
90 Ok(UnityFile::WebFile(web)) => {
91 let web_path = path.to_path_buf();
92 self.webfiles.insert(web_path.clone(), web);
93 self.load_webfile_entries(&web_path)?;
94 }
95 Err(_) => {}
96 }
97
98 Ok(())
99 }
100
101 fn load_webfile_entries(&mut self, web_path: &PathBuf) -> Result<()> {
102 let web = self.webfiles.get(web_path).ok_or_else(|| {
103 UnityAssetError::format(format!("WebFile not loaded: {:?}", web_path))
104 })?;
105
106 let mut entry_names: Vec<String> = web.files.iter().map(|f| f.name.clone()).collect();
107 entry_names.sort();
108 entry_names.dedup();
109
110 for entry_name in entry_names {
111 let view = match web.extract_file_view(&entry_name) {
112 Ok(v) => v,
113 Err(_) => continue,
114 };
115
116 let Ok(parsed) =
117 load_unity_file_from_shared_range(view.backing_shared(), view.absolute_range())
118 else {
119 continue;
120 };
121
122 match parsed {
123 UnityFile::AssetBundle(bundle) => {
124 let mut bundle = bundle;
125 if let Some(registry) = self.type_tree_registry.clone() {
126 for file in bundle.assets.iter_mut() {
127 file.set_type_tree_registry(Some(registry.clone()));
128 }
129 }
130 let source = BinarySource::WebEntry {
131 web_path: web_path.clone(),
132 entry_name: entry_name.clone(),
133 };
134 self.bundles.insert(source.clone(), bundle);
135 match self.bundle_container_cache.write() {
136 Ok(mut cache) => {
137 cache.remove(&source);
138 }
139 Err(e) => {
140 let mut cache = e.into_inner();
141 cache.remove(&source);
142 }
143 }
144 }
145 UnityFile::SerializedFile(asset) => {
146 let mut asset = asset;
147 if let Some(registry) = self.type_tree_registry.clone() {
148 asset.set_type_tree_registry(Some(registry));
149 }
150 let source = BinarySource::WebEntry {
151 web_path: web_path.clone(),
152 entry_name,
153 };
154 self.binary_assets.insert(source, asset);
155 match self.bundle_container_cache.write() {
156 Ok(mut cache) => cache.clear(),
157 Err(e) => e.into_inner().clear(),
158 }
159 }
160 UnityFile::WebFile(_) => {
161 }
163 }
164 }
165
166 Ok(())
167 }
168
169 pub fn load_directory<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
171 let path = path.as_ref();
172
173 if !path.exists() {
174 return Err(UnityAssetError::format(format!(
175 "Directory does not exist: {:?}",
176 path
177 )));
178 }
179
180 if !path.is_dir() {
181 return Err(UnityAssetError::format(format!(
182 "Path is not a directory: {:?}",
183 path
184 )));
185 }
186
187 self.traverse_directory(path)?;
189
190 Ok(())
191 }
192
193 fn traverse_directory(&mut self, dir: &Path) -> Result<()> {
195 let entries = std::fs::read_dir(dir).map_err(|e| {
196 UnityAssetError::with_source(format!("Failed to read directory {:?}", dir), e)
197 })?;
198
199 for entry in entries {
200 let entry = entry
201 .map_err(|e| UnityAssetError::with_source("Failed to read directory entry", e))?;
202 let path = entry.path();
203
204 if path.is_dir() {
205 if let Some(dir_name) = path.file_name().and_then(|n| n.to_str()) {
207 match dir_name {
208 "Library" | "Temp" | "Logs" | ".git" | ".vs" | "obj" | "bin" => {
209 continue; }
211 _ => {
212 self.traverse_directory(&path)?;
214 }
215 }
216 }
217 } else if path.is_file() {
218 if let Err(e) = self.load_file(&path) {
220 self.push_warning(EnvironmentWarning::LoadFailed {
222 path,
223 error: e.to_string(),
224 });
225 }
226 }
227 }
228
229 Ok(())
230 }
231}