unity_asset/environment/imp/
object_query.rs1use super::*;
2
3impl Environment {
4 pub fn binary_object_infos(&self) -> impl Iterator<Item = BinaryObjectRef<'_>> {
6 let typetree_options = self.options.typetree;
7 let standalone_reporter = self.reporter.clone();
8 let bundled_reporter = self.reporter.clone();
9
10 let standalone = self.binary_assets.iter().flat_map(move |(source, file)| {
11 let reporter = standalone_reporter.clone();
12 file.object_handles().map(move |object| BinaryObjectRef {
13 source,
14 source_kind: BinarySourceKind::SerializedFile,
15 asset_index: None,
16 object,
17 typetree_options,
18 reporter: reporter.clone(),
19 })
20 });
21
22 let bundled = self
23 .bundles
24 .iter()
25 .flat_map(move |(bundle_source, bundle)| {
26 let reporter = bundled_reporter.clone();
27 bundle
28 .assets
29 .iter()
30 .enumerate()
31 .flat_map(move |(asset_index, file)| {
32 let reporter = reporter.clone();
33 file.object_handles().map(move |object| BinaryObjectRef {
34 source: bundle_source,
35 source_kind: BinarySourceKind::AssetBundle,
36 asset_index: Some(asset_index),
37 object,
38 typetree_options,
39 reporter: reporter.clone(),
40 })
41 })
42 });
43
44 standalone.chain(bundled)
45 }
46
47 pub fn binary_sources(&self) -> Vec<(BinarySourceKind, BinarySource)> {
49 let mut out: Vec<(BinarySourceKind, BinarySource)> = Vec::new();
50
51 let mut asset_sources: Vec<BinarySource> = self.binary_assets.keys().cloned().collect();
52 asset_sources.sort();
53 out.extend(
54 asset_sources
55 .into_iter()
56 .map(|s| (BinarySourceKind::SerializedFile, s)),
57 );
58
59 let mut bundle_sources: Vec<BinarySource> = self.bundles.keys().cloned().collect();
60 bundle_sources.sort();
61 out.extend(
62 bundle_sources
63 .into_iter()
64 .map(|s| (BinarySourceKind::AssetBundle, s)),
65 );
66
67 out
68 }
69
70 pub fn find_binary_objects(&self, path_id: i64) -> Vec<BinaryObjectRef<'_>> {
74 let mut out = Vec::new();
75 let typetree_options = self.options.typetree;
76 let reporter = self.reporter.clone();
77
78 let mut asset_sources: Vec<&BinarySource> = self.binary_assets.keys().collect();
79 asset_sources.sort();
80 for source in asset_sources {
81 let file = &self.binary_assets[source];
82 if let Some(object) = file.find_object_handle(path_id) {
83 out.push(BinaryObjectRef {
84 source,
85 source_kind: BinarySourceKind::SerializedFile,
86 asset_index: None,
87 object,
88 typetree_options,
89 reporter: reporter.clone(),
90 });
91 }
92 }
93
94 let mut bundle_sources: Vec<&BinarySource> = self.bundles.keys().collect();
95 bundle_sources.sort();
96 for bundle_source in bundle_sources {
97 let bundle = &self.bundles[bundle_source];
98 for (asset_index, asset) in bundle.assets.iter().enumerate() {
99 if let Some(object) = asset.find_object_handle(path_id) {
100 out.push(BinaryObjectRef {
101 source: bundle_source,
102 source_kind: BinarySourceKind::AssetBundle,
103 asset_index: Some(asset_index),
104 object,
105 typetree_options,
106 reporter: reporter.clone(),
107 });
108 }
109 }
110 }
111
112 out
113 }
114
115 pub fn find_binary_object(&self, path_id: i64) -> Option<BinaryObjectRef<'_>> {
117 self.find_binary_objects(path_id).into_iter().next()
118 }
119
120 pub fn find_binary_objects_in_source<P: AsRef<Path>>(
122 &self,
123 source: P,
124 path_id: i64,
125 ) -> Vec<BinaryObjectRef<'_>> {
126 let source = BinarySource::path(source.as_ref());
127 self.find_binary_objects_in_source_id(&source, path_id)
128 }
129
130 pub fn find_binary_objects_in_source_id(
132 &self,
133 source: &BinarySource,
134 path_id: i64,
135 ) -> Vec<BinaryObjectRef<'_>> {
136 let typetree_options = self.options.typetree;
137 let reporter = self.reporter.clone();
138
139 if let Some((key, file)) = self.binary_assets.get_key_value(source) {
140 if let Some(object) = file.find_object_handle(path_id) {
141 return vec![BinaryObjectRef {
142 source: key,
143 source_kind: BinarySourceKind::SerializedFile,
144 asset_index: None,
145 object,
146 typetree_options,
147 reporter,
148 }];
149 }
150 return Vec::new();
151 }
152
153 if let Some((key, bundle)) = self.bundles.get_key_value(source) {
154 let mut out = Vec::new();
155 for (asset_index, asset) in bundle.assets.iter().enumerate() {
156 if let Some(object) = asset.find_object_handle(path_id) {
157 out.push(BinaryObjectRef {
158 source: key,
159 source_kind: BinarySourceKind::AssetBundle,
160 asset_index: Some(asset_index),
161 object,
162 typetree_options,
163 reporter: reporter.clone(),
164 });
165 }
166 }
167 return out;
168 }
169
170 Vec::new()
171 }
172
173 pub fn find_binary_object_in_source<P: AsRef<Path>>(
175 &self,
176 source: P,
177 path_id: i64,
178 ) -> Option<BinaryObjectRef<'_>> {
179 self.find_binary_objects_in_source(source, path_id)
180 .into_iter()
181 .next()
182 }
183
184 pub fn find_binary_object_in_source_id(
185 &self,
186 source: &BinarySource,
187 path_id: i64,
188 ) -> Option<BinaryObjectRef<'_>> {
189 self.find_binary_objects_in_source_id(source, path_id)
190 .into_iter()
191 .next()
192 }
193
194 pub fn find_binary_object_in_bundle_asset<P: AsRef<Path>>(
196 &self,
197 bundle_path: P,
198 asset_index: usize,
199 path_id: i64,
200 ) -> Option<BinaryObjectRef<'_>> {
201 let bundle_source = BinarySource::path(bundle_path.as_ref());
202 self.find_binary_object_in_bundle_asset_source(&bundle_source, asset_index, path_id)
203 }
204
205 pub fn find_binary_object_in_bundle_asset_source(
206 &self,
207 bundle_source: &BinarySource,
208 asset_index: usize,
209 path_id: i64,
210 ) -> Option<BinaryObjectRef<'_>> {
211 let typetree_options = self.options.typetree;
212 let reporter = self.reporter.clone();
213
214 let (key, bundle) = self.bundles.get_key_value(bundle_source)?;
215 let asset = bundle.assets.get(asset_index)?;
216 let object = asset.find_object_handle(path_id)?;
217 Some(BinaryObjectRef {
218 source: key,
219 source_kind: BinarySourceKind::AssetBundle,
220 asset_index: Some(asset_index),
221 object,
222 typetree_options,
223 reporter,
224 })
225 }
226
227 pub fn find_binary_object_keys(&self, path_id: i64) -> Vec<BinaryObjectKey> {
229 self.find_binary_objects(path_id)
230 .into_iter()
231 .map(|r| r.key())
232 .collect()
233 }
234
235 pub fn find_binary_object_keys_in_source<P: AsRef<Path>>(
237 &self,
238 source: P,
239 path_id: i64,
240 ) -> Vec<BinaryObjectKey> {
241 self.find_binary_objects_in_source(source, path_id)
242 .into_iter()
243 .map(|r| r.key())
244 .collect()
245 }
246
247 pub fn read_binary_object_key(&self, key: &BinaryObjectKey) -> Result<UnityObject> {
249 let typetree_options = self.options.typetree;
250 match key.source_kind {
251 BinarySourceKind::SerializedFile => {
252 let file = self.binary_assets.get(&key.source).ok_or_else(|| {
253 UnityAssetError::format(format!(
254 "SerializedFile source not loaded: {}",
255 key.source.describe()
256 ))
257 })?;
258 let object = file.find_object_handle(key.path_id).ok_or_else(|| {
259 UnityAssetError::format(format!(
260 "Object not found in SerializedFile {}: path_id={}",
261 key.source.describe(),
262 key.path_id
263 ))
264 })?;
265 let obj = object.read_with_options(typetree_options).map_err(|e| {
266 UnityAssetError::with_source("Failed to parse binary object", e)
267 })?;
268 if let Some(reporter) = &self.reporter {
269 for w in obj.typetree_warnings() {
270 reporter.typetree_warning(key, w);
271 }
272 }
273 Ok(obj)
274 }
275 BinarySourceKind::AssetBundle => {
276 let bundle = self.bundles.get(&key.source).ok_or_else(|| {
277 UnityAssetError::format(format!(
278 "AssetBundle source not loaded: {}",
279 key.source.describe()
280 ))
281 })?;
282 let asset_index = key.asset_index.ok_or_else(|| {
283 UnityAssetError::format(
284 "AssetBundle key requires an asset_index (which asset in the bundle?)"
285 .to_string(),
286 )
287 })?;
288 let file = bundle.assets.get(asset_index).ok_or_else(|| {
289 UnityAssetError::format(format!(
290 "AssetBundle asset index out of range: {} asset_index={}",
291 key.source.describe(),
292 asset_index
293 ))
294 })?;
295 let object = file.find_object_handle(key.path_id).ok_or_else(|| {
296 UnityAssetError::format(format!(
297 "Object not found in AssetBundle {} asset_index={}: path_id={}",
298 key.source.describe(),
299 asset_index,
300 key.path_id
301 ))
302 })?;
303 let obj = object.read_with_options(typetree_options).map_err(|e| {
304 UnityAssetError::with_source("Failed to parse binary object", e)
305 })?;
306 if let Some(reporter) = &self.reporter {
307 for w in obj.typetree_warnings() {
308 reporter.typetree_warning(key, w);
309 }
310 }
311 Ok(obj)
312 }
313 }
314 }
315
316 pub fn peek_binary_object_name(&self, key: &BinaryObjectKey) -> Result<Option<String>> {
321 let typetree_options = self.options.typetree;
322 match key.source_kind {
323 BinarySourceKind::SerializedFile => {
324 let file = self.binary_assets.get(&key.source).ok_or_else(|| {
325 UnityAssetError::format(format!(
326 "SerializedFile source not loaded: {}",
327 key.source.describe()
328 ))
329 })?;
330 let object = file.find_object_handle(key.path_id).ok_or_else(|| {
331 UnityAssetError::format(format!(
332 "Object not found in SerializedFile {}: path_id={}",
333 key.source.describe(),
334 key.path_id
335 ))
336 })?;
337 object
338 .peek_name_with_options(typetree_options)
339 .map_err(|e| {
340 UnityAssetError::with_source("Failed to peek binary object name", e)
341 })
342 }
343 BinarySourceKind::AssetBundle => {
344 let bundle = self.bundles.get(&key.source).ok_or_else(|| {
345 UnityAssetError::format(format!(
346 "AssetBundle source not loaded: {}",
347 key.source.describe()
348 ))
349 })?;
350 let asset_index = key.asset_index.ok_or_else(|| {
351 UnityAssetError::format(
352 "AssetBundle key requires an asset_index (which asset in the bundle?)"
353 .to_string(),
354 )
355 })?;
356 let file = bundle.assets.get(asset_index).ok_or_else(|| {
357 UnityAssetError::format(format!(
358 "AssetBundle asset index out of range: {} asset_index={}",
359 key.source.describe(),
360 asset_index
361 ))
362 })?;
363 let object = file.find_object_handle(key.path_id).ok_or_else(|| {
364 UnityAssetError::format(format!(
365 "Object not found in AssetBundle {} asset_index={}: path_id={}",
366 key.source.describe(),
367 asset_index,
368 key.path_id
369 ))
370 })?;
371 object
372 .peek_name_with_options(typetree_options)
373 .map_err(|e| {
374 UnityAssetError::with_source("Failed to peek binary object name", e)
375 })
376 }
377 }
378 }
379}