diff --git a/src/asset.rs b/src/asset.rs new file mode 100644 index 0000000..5d10514 --- /dev/null +++ b/src/asset.rs @@ -0,0 +1,65 @@ +use std::ffi::OsStr; +use std::fs; +use std::fs::DirEntry; +use std::fs::File; +use std::io::BufRead; +use std::io::BufReader; +use std::path::{Path, PathBuf}; + +#[derive(Clone)] +pub struct Asset { + pub extension: Option, + pub hash: String, + pub path_name: String, + pub has_meta: bool, +} + +impl Asset { + pub fn from_path(entry: &DirEntry) -> Option { + let root_file = entry.path(); + if !root_file.is_dir() { + return None; + } + let asset = entry.file_name().into_string().unwrap(); + let mut real_path = String::new(); + let mut extension = None; + let mut has_asset = false; + let mut has_meta = false; + for sub_entry in fs::read_dir(root_file.clone()).unwrap() { + let sub_entry = sub_entry.unwrap(); + let file_name = sub_entry.file_name().into_string().unwrap(); + match file_name.as_str() { + "pathname" => { + let path = sub_entry.path(); + let file = File::open(path).unwrap(); + let buf_reader = BufReader::new(file); + let line = buf_reader.lines().next(); + match line { + Some(Ok(path)) => { + real_path = path; + if let Some(e) = + Path::new(&real_path).extension().and_then(OsStr::to_str) + { + extension = Some(String::from(e)); + } + } + _ => continue, + } + } + "asset" => has_asset = true, + "asset.meta" => has_meta = true, + _ => continue, + } + } + if has_asset { + Some(Asset { + extension, + hash: asset, + path_name: real_path, + has_meta, + }) + } else { + None + } + } +} diff --git a/src/main.rs b/src/main.rs index ebdc15a..785f87e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,9 @@ mod args; +pub mod asset; mod unpacker; use clap::Parser; - - - - - - - fn main() { let args = crate::args::Args::parse(); let unpacker = crate::unpacker::Unpacker { args }; diff --git a/src/unpacker.rs b/src/unpacker.rs index a6659a8..655b7d0 100644 --- a/src/unpacker.rs +++ b/src/unpacker.rs @@ -1,16 +1,16 @@ +use crate::asset::Asset; use flate2::read::GzDecoder; use hashbrown::HashMap; +use rayon::prelude::*; use std::ffi::OsStr; use std::fs::File; use std::io::BufRead; use std::io::BufReader; use std::path::{Path, PathBuf}; use std::process::Command; +use std::sync::mpsc::channel; use std::sync::Arc; use std::{fs, io}; - -use rayon::prelude::*; -use std::sync::mpsc::channel; use tar::Archive; #[derive(Clone)] @@ -52,54 +52,28 @@ impl Unpacker { .par_bridge() .for_each_with(sender, |s, entry| { let entry = entry.unwrap(); - let root_file = entry.path(); - let asset = entry.file_name().into_string().unwrap(); - if !root_file.is_dir() { - return; - } - let mut real_path = String::new(); - let mut extension = None; - let mut has_asset = false; - for sub_entry in fs::read_dir(root_file.clone()).unwrap() { - let sub_entry = sub_entry.unwrap(); - let file_name = sub_entry.file_name().into_string().unwrap(); - if file_name == "pathname" { - let path = sub_entry.path(); - let file = File::open(path).unwrap(); - let buf_reader = BufReader::new(file); - let line = buf_reader.lines().next(); - match line { - Some(Ok(path)) => { - real_path = path; - if let Some(e) = - Path::new(&real_path).extension().and_then(OsStr::to_str) - { - extension = Some(String::from(e)); - } - } - _ => continue, - } - } else if file_name == "asset" { - has_asset = true; + let asset = crate::asset::Asset::from_path(&entry); + if let Some(asset) = asset { + let extension = &asset.extension.clone().unwrap_or_default(); + if !ignored_extensions.contains(extension) { + s.send(asset).unwrap(); } } - if has_asset && !ignored_extensions.contains(&extension.unwrap_or_default()) { - s.send((asset, real_path)).unwrap(); - } }); let tmp_dir = Arc::new(tmp_path); fs::create_dir(output_dir).unwrap(); let output_dir = Arc::new(output_dir); - let mapping: HashMap = receiver.iter().collect(); + let mapping: Vec = receiver.iter().collect(); let mapping_arc = Arc::new(mapping); - mapping_arc.par_iter().for_each(|(asset_hash, asset_path)| { - let path = Path::new(asset_path); + mapping_arc.par_iter().for_each(|(asset)| { + let asset_hash = &asset.hash; + let path = Path::new(&asset.path_name); let source_asset = Path::new(&*tmp_dir).join(asset_hash).join("asset"); let result_path = output_dir.join(path); - process_directory(asset_hash, asset_path, &result_path); + process_directory(asset_hash, &asset.path_name, &result_path); check_source_asset_exists(&source_asset); if self.args.fbx_to_gltf.is_some() {