1- use std:: collections:: HashMap ;
1+ use std:: collections:: { HashMap , HashSet } ;
22use std:: ffi:: OsString ;
33use std:: io:: Read ;
44use std:: path:: { Path , PathBuf } ;
@@ -19,7 +19,7 @@ struct Config {
1919}
2020
2121type AssetMap = HashMap < PathBuf , Vec < u8 > > ;
22- type FolderMap = HashMap < OsString , bool > ;
22+ type FolderSet = HashSet < OsString > ;
2323type ExtractTask = Vec < JoinHandle < Result < ( ) , io:: Error > > > ;
2424
2525fn parse_arguments ( ) -> Config {
@@ -64,11 +64,11 @@ fn read_asset_to_memory<R: Read>(
6464 mut entry : tar:: Entry < ' _ , R > ,
6565 path : PathBuf ,
6666) -> Result < ( ) , io:: Error > {
67- debug ! ( "reading asset to memory « {:?}» " , path) ;
67+ debug ! ( "reading asset to memory {:?}" , path) ;
6868 let mut asset_data = Vec :: new ( ) ;
6969 entry. read_to_end ( & mut asset_data) ?;
7070 trace ! (
71- "saving « {:?}» with {} bytes to memory" ,
71+ "saving {:?} with {} bytes to memory" ,
7272 path,
7373 asset_data. len( ) ,
7474 ) ;
@@ -77,22 +77,22 @@ fn read_asset_to_memory<R: Read>(
7777}
7878
7979fn check_for_folders < R : Read > (
80- folders : & mut FolderMap ,
80+ folders : & mut FolderSet ,
8181 mut entry : tar:: Entry < ' _ , R > ,
8282 path : PathBuf ,
8383) -> Result < ( ) , io:: Error > {
84- debug ! ( "reading asset to memory « {:?}» " , path) ;
84+ debug ! ( "reading asset to memory {:?}" , path) ;
8585 let mut metadata = String :: new ( ) ;
8686 entry. read_to_string ( & mut metadata) ?;
8787 if metadata. contains ( "folderAsset: yes\n " ) {
88- folders. insert ( path. into_os_string ( ) , true ) ;
88+ folders. insert ( path. into_os_string ( ) ) ;
8989 }
9090 Ok ( ( ) )
9191}
9292
9393fn read_destination_path_and_write < R : Read > (
9494 assets : & mut AssetMap ,
95- folders : & FolderMap ,
95+ folders : & FolderSet ,
9696 tasks : & mut ExtractTask ,
9797 mut entry : tar:: Entry < ' _ , R > ,
9898 path : PathBuf ,
@@ -104,44 +104,49 @@ fn read_destination_path_and_write<R: Read>(
104104 if let Some ( asset_data) = assets. remove ( & asset_path) {
105105 tasks. push ( tokio:: spawn ( write_asset_to_pathname (
106106 asset_data,
107- path. clone ( ) ,
107+ path. to_string_lossy ( ) . to_string ( ) ,
108108 path_name,
109109 ) ) ) ;
110110 } else {
111111 let path_string = path. into_os_string ( ) ;
112- if folders. contains_key ( & path_string) {
113- warn ! ( "no asset data found for «{}» " , path_name. escape_default( ) ) ;
112+ if folders. contains ( & path_string) {
113+ warn ! ( "no asset data found for {} " , path_name. escape_default( ) ) ;
114114 }
115115 }
116116 Ok ( ( ) )
117117}
118118
119119async fn write_asset_to_pathname (
120120 asset_data : Vec < u8 > ,
121- entry_hash : PathBuf ,
121+ entry_hash : String ,
122122 path_name : String ,
123123) -> Result < ( ) , io:: Error > {
124124 let target_path = sanitize_path:: sanitize_path ( & path_name) ?;
125+ let asset_hash: & str ;
126+
127+ match entry_hash. find ( '/' ) {
128+ Some ( idx) => {
129+ ( asset_hash, _) = entry_hash. split_at ( idx) ;
130+ }
131+ None => {
132+ asset_hash = & entry_hash;
133+ }
134+ }
125135
126136 if path_name != target_path {
127- debug ! (
128- "sanitizing path «{}» => «{}»" ,
129- path_name. escape_default( ) ,
130- target_path. escape_default( ) ,
131- ) ;
137+ debug ! ( "sanitizing path {:?} => {:?}" , path_name, target_path, ) ;
132138 }
133139
134140 if let Some ( parent) = Path :: new ( & target_path) . parent ( ) {
135141 fs:: create_dir_all ( parent) . await ?;
136142 }
137143
138- info ! ( "extracting: «{:?}» to «{}» " , entry_hash , target_path) ;
144+ info ! ( "extracting {} to {:?} " , asset_hash , target_path) ;
139145 let file = fs:: File :: create ( & target_path) . await ?;
140146 let mut file_writer = io:: BufWriter :: new ( file) ;
141147 file_writer. write_all ( & asset_data) . await ?;
142148 file_writer. flush ( ) . await ?;
143-
144- trace ! ( "done extracting «{:?}»" , entry_hash) ;
149+ trace ! ( "{} is written to disk" , asset_hash) ;
145150 Ok ( ( ) )
146151}
147152
@@ -150,7 +155,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
150155 let config = parse_arguments ( ) ;
151156 SimpleLogger :: new ( ) . with_level ( config. log_level ) . init ( ) ?;
152157 debug ! ( "opening unitypackage file at {}" , & config. input_path) ;
153-
154158 let file = std:: fs:: File :: open ( & config. input_path ) ;
155159
156160 if let Err ( err) = file {
@@ -161,7 +165,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
161165 let decoder = GzDecoder :: new ( file?) ;
162166 let mut archive = tar:: Archive :: new ( decoder) ;
163167 let mut assets: AssetMap = HashMap :: new ( ) ;
164- let mut folders: FolderMap = HashMap :: new ( ) ;
168+ let mut folders: FolderSet = HashSet :: new ( ) ;
165169 let mut tasks: ExtractTask = Vec :: new ( ) ;
166170
167171 debug ! ( "iterating archive's entries" ) ;
@@ -188,8 +192,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
188192 check_for_folders ( & mut folders, entry, path) ?;
189193 } else if path. ends_with ( "pathname" ) {
190194 read_destination_path_and_write ( & mut assets, & folders, & mut tasks, entry, path) ?;
195+ } else if path. ends_with ( "/" ) {
196+ trace ! ( "skipping folder {}" , path. display( ) ) ;
191197 } else {
192- trace ! ( "skipping entry with name «{:?}» " , path)
198+ trace ! ( "skipping entry with name {} " , path. display ( ) )
193199 }
194200 }
195201
0 commit comments