unity_asset_binary/metadata/
mod.rs1pub mod analyzer;
37pub mod extractor;
38pub mod types;
39
40pub use analyzer::{DependencyAnalyzer, RelationshipAnalyzer};
42pub use extractor::MetadataExtractor;
43pub use types::{
44 AssetMetadata,
46 AssetReference,
47 AssetRelationships,
49 ComponentRelationship,
50 DependencyGraph,
51 DependencyInfo,
53 ExternalReference,
54 ExtractionConfig,
55 ExtractionResult,
56 ExtractionStats,
57 FileInfo,
58 GameObjectHierarchy,
59 InternalReference,
60 MemoryUsage,
61 ObjectStatistics,
62 ObjectSummary,
63 PerformanceMetrics,
65 class_ids,
67};
68
69pub struct MetadataProcessor {
74 extractor: MetadataExtractor,
75 dependency_analyzer: Option<DependencyAnalyzer>,
76 relationship_analyzer: Option<RelationshipAnalyzer>,
77}
78
79impl MetadataProcessor {
80 pub fn new() -> Self {
82 Self {
83 extractor: MetadataExtractor::new(),
84 dependency_analyzer: None,
85 relationship_analyzer: None,
86 }
87 }
88
89 pub fn with_config(config: ExtractionConfig) -> Self {
91 let enable_advanced = config.include_dependencies || config.include_hierarchy;
92
93 Self {
94 extractor: MetadataExtractor::with_config(config),
95 dependency_analyzer: if enable_advanced {
96 Some(DependencyAnalyzer::new())
97 } else {
98 None
99 },
100 relationship_analyzer: if enable_advanced {
101 Some(RelationshipAnalyzer::new())
102 } else {
103 None
104 },
105 }
106 }
107
108 pub fn process_asset(
110 &mut self,
111 asset: &crate::SerializedFile,
112 ) -> crate::error::Result<ExtractionResult> {
113 let mut result = self.extractor.extract_from_asset(asset)?;
114
115 if let Some(ref mut analyzer) = self.dependency_analyzer
117 && self.extractor.config().include_dependencies
118 {
119 let objects: Vec<&crate::asset::ObjectInfo> = asset.objects.iter().collect();
120 match analyzer.analyze_dependencies(&objects) {
121 Ok(deps) => {
122 result.metadata.dependencies = deps;
123 }
124 Err(e) => {
125 result.add_warning(format!("Enhanced dependency analysis failed: {}", e));
126 }
127 }
128 }
129
130 if let Some(ref mut analyzer) = self.relationship_analyzer
132 && self.extractor.config().include_hierarchy
133 {
134 let objects: Vec<&crate::asset::ObjectInfo> = asset.objects.iter().collect();
135 match analyzer.analyze_relationships(&objects) {
136 Ok(rels) => {
137 result.metadata.relationships = rels;
138 }
139 Err(e) => {
140 result.add_warning(format!("Enhanced relationship analysis failed: {}", e));
141 }
142 }
143 }
144
145 Ok(result)
146 }
147
148 pub fn process_bundle(
150 &mut self,
151 bundle: &crate::AssetBundle,
152 ) -> crate::error::Result<Vec<ExtractionResult>> {
153 let mut results = Vec::new();
154
155 for asset in &bundle.assets {
156 let result = self.process_asset(asset)?;
157 results.push(result);
158 }
159
160 Ok(results)
161 }
162
163 pub fn config(&self) -> &ExtractionConfig {
165 self.extractor.config()
166 }
167
168 pub fn set_config(&mut self, config: ExtractionConfig) {
170 let enable_advanced = config.include_dependencies || config.include_hierarchy;
171
172 self.extractor.set_config(config);
173
174 if enable_advanced {
176 if self.dependency_analyzer.is_none() {
177 self.dependency_analyzer = Some(DependencyAnalyzer::new());
178 }
179 if self.relationship_analyzer.is_none() {
180 self.relationship_analyzer = Some(RelationshipAnalyzer::new());
181 }
182 }
183 }
184
185 pub fn clear_caches(&mut self) {
187 if let Some(ref mut analyzer) = self.dependency_analyzer {
188 analyzer.clear_cache();
189 }
190 if let Some(ref mut analyzer) = self.relationship_analyzer {
191 analyzer.clear_cache();
192 }
193 }
194
195 pub fn has_advanced_analysis(&self) -> bool {
197 self.dependency_analyzer.is_some() || self.relationship_analyzer.is_some()
198 }
199}
200
201impl Default for MetadataProcessor {
202 fn default() -> Self {
203 Self::new()
204 }
205}
206
207pub fn create_processor() -> MetadataProcessor {
210 MetadataProcessor::default()
211}
212
213pub fn create_performance_processor() -> MetadataProcessor {
215 let config = ExtractionConfig {
216 include_dependencies: false,
217 include_hierarchy: false,
218 max_objects: Some(1000),
219 include_performance: true,
220 include_object_details: false,
221 };
222 MetadataProcessor::with_config(config)
223}
224
225pub fn create_comprehensive_processor() -> MetadataProcessor {
227 let config = ExtractionConfig {
228 include_dependencies: true,
229 include_hierarchy: true,
230 max_objects: None,
231 include_performance: true,
232 include_object_details: true,
233 };
234 MetadataProcessor::with_config(config)
235}
236
237pub fn extract_basic_metadata(
239 asset: &crate::SerializedFile,
240) -> crate::error::Result<AssetMetadata> {
241 let extractor = MetadataExtractor::new();
242 let result = extractor.extract_from_asset(asset)?;
243 Ok(result.metadata)
244}
245
246pub fn extract_metadata_with_config(
248 asset: &crate::SerializedFile,
249 config: ExtractionConfig,
250) -> crate::error::Result<ExtractionResult> {
251 let extractor = MetadataExtractor::with_config(config);
252 extractor.extract_from_asset(asset)
253}
254
255pub fn get_asset_statistics(asset: &crate::SerializedFile) -> AssetStatistics {
257 AssetStatistics {
258 object_count: asset.objects.len(),
259 type_count: asset.types.len(),
260 external_count: asset.externals.len(),
261 file_size: asset.header.file_size as u64,
262 unity_version: asset.unity_version.clone(),
263 format_version: asset.header.version,
264 }
265}
266
267#[derive(Debug, Clone)]
269pub struct AssetStatistics {
270 pub object_count: usize,
271 pub type_count: usize,
272 pub external_count: usize,
273 pub file_size: u64,
274 pub unity_version: String,
275 pub format_version: u32,
276}
277
278#[derive(Debug, Clone)]
280pub struct ProcessingOptions {
281 pub enable_caching: bool,
282 pub max_cache_size: usize,
283 pub parallel_processing: bool,
284 pub memory_limit_mb: Option<usize>,
285}
286
287impl Default for ProcessingOptions {
288 fn default() -> Self {
289 Self {
290 enable_caching: true,
291 max_cache_size: 1000,
292 parallel_processing: false,
293 memory_limit_mb: None,
294 }
295 }
296}
297
298pub fn is_extraction_supported(asset: &crate::SerializedFile) -> bool {
300 asset.header.version >= 10
302}
303
304pub fn get_recommended_config(asset: &crate::SerializedFile) -> ExtractionConfig {
306 let object_count = asset.objects.len();
307
308 if object_count > 10000 {
309 ExtractionConfig {
311 include_dependencies: false,
312 include_hierarchy: false,
313 max_objects: Some(5000),
314 include_performance: true,
315 include_object_details: false,
316 }
317 } else if object_count > 1000 {
318 ExtractionConfig {
320 include_dependencies: true,
321 include_hierarchy: false,
322 max_objects: Some(2000),
323 include_performance: true,
324 include_object_details: true,
325 }
326 } else {
327 ExtractionConfig::default()
329 }
330}
331
332#[cfg(test)]
333mod tests {
334 use super::*;
335
336 #[test]
337 fn test_processor_creation() {
338 let processor = create_processor();
339 assert!(!processor.has_advanced_analysis());
340 }
341
342 #[test]
343 fn test_comprehensive_processor() {
344 let processor = create_comprehensive_processor();
345 assert!(processor.has_advanced_analysis());
346 assert!(processor.config().include_dependencies);
347 assert!(processor.config().include_hierarchy);
348 }
349
350 #[test]
351 fn test_performance_processor() {
352 let processor = create_performance_processor();
353 assert!(!processor.config().include_dependencies);
354 assert!(!processor.config().include_hierarchy);
355 assert_eq!(processor.config().max_objects, Some(1000));
356 }
357
358 #[test]
359 fn test_extraction_support() {
360 }
363}