1
1
use std:: cell:: RefCell ;
2
- use std:: collections:: HashMap ;
3
2
use std:: fs;
4
3
use std:: io:: Cursor ;
5
4
use std:: path:: { Path , PathBuf } ;
6
5
use std:: rc:: Rc ;
7
6
8
7
use msfs:: { commbus:: * , network:: * } ;
9
8
10
- use crate :: { download:: zip_handler:: ZipFileHandler , util} ;
9
+ use crate :: {
10
+ download:: zip_handler:: { BatchReturn , ZipFileHandler } ,
11
+ util,
12
+ } ;
11
13
12
14
pub struct DownloadOptions {
13
15
batch_size : usize ,
@@ -24,7 +26,6 @@ pub enum DownloadStatus {
24
26
NoDownload ,
25
27
Downloading ,
26
28
Extracting ,
27
- Done ,
28
29
Failed ( String ) ,
29
30
}
30
31
@@ -44,64 +45,100 @@ impl NavdataDownloader {
44
45
}
45
46
46
47
pub fn on_update ( & self ) {
47
- let status = self . update_and_get_status ( ) ;
48
- // If we are extracting, extract the next batch of files
49
- if status == DownloadStatus :: Extracting {
50
- // Send the statistics to the JS side
51
- let statistics: DownloadStatistics = self . get_download_statistics ( ) . unwrap ( ) ;
52
- let mut map = HashMap :: new ( ) ;
53
- map. insert ( "total" , statistics. total_files ) ;
54
- map. insert ( "unzipped" , statistics. files_unzipped ) ;
55
- let data = serde_json:: to_string ( & map) . unwrap ( ) ;
56
- CommBus :: call (
57
- "NAVIGRAPH_UnzippedFilesRemaining" ,
58
- & data,
59
- CommBusBroadcastFlags :: All ,
60
- ) ;
48
+ // Check if we failed and need to send an error message
49
+ // We need to do this in its own variable since we can't borrow_mut and borrow at the same time (self.reset_download() borrows mutably)
50
+ let failed_message = {
51
+ let borrowed_status = self . status . borrow ( ) ;
52
+ if let DownloadStatus :: Failed ( ref message) = * borrowed_status {
53
+ Some ( message. clone ( ) )
54
+ } else {
55
+ None
56
+ }
57
+ } ;
61
58
62
- // Unzip the next batch of files
63
- let has_more_files = self . unzip_batch ( 10 ) ;
64
- if !has_more_files {
65
- println ! ( "[WASM] finished unzip" ) ;
59
+ if let Some ( message) = failed_message {
60
+ // Send the error message to the JS side
61
+ let error_message = serde_json:: json!( {
62
+ "error" : message
63
+ } ) ;
64
+ if let Ok ( data) = serde_json:: to_string ( & error_message) {
65
+ println ! ( "[WASM] Sending error message: {}" , message) ;
66
66
CommBus :: call (
67
- "NAVIGRAPH_NavdataDownloaded " ,
68
- "" ,
67
+ "NAVIGRAPH_DownloadFailed " ,
68
+ & data ,
69
69
CommBusBroadcastFlags :: All ,
70
70
) ;
71
+ }
71
72
72
- self . clear_zip_handler ( ) ;
73
+ self . reset_download ( ) ;
74
+ }
75
+
76
+ // Check if we are extracting
77
+ // We need to do this in its own variable since we can't borrow_mut and borrow at the same time (self.unzip_batch() borrows mutably)
78
+ let extract_next_batch = {
79
+ let borrowed_zip_handler = self . zip_handler . borrow ( ) ;
80
+ if let Some ( zip_handler) = borrowed_zip_handler. as_ref ( ) {
81
+ zip_handler. zip_file_count > zip_handler. current_file_index
82
+ } else {
83
+ // If there is no zip handler, we are not downloading and we don't need to do anything
84
+ return ;
85
+ }
86
+ } ;
87
+
88
+ // Only proceed if there are zip files to process
89
+ if extract_next_batch {
90
+ // Send the statistics to the JS side
91
+ if let Ok ( statistics) = self . get_download_statistics ( ) {
92
+ let data = serde_json:: json!( {
93
+ "total" : statistics. total_files,
94
+ "unzipped" : statistics. files_unzipped,
95
+ } ) ;
96
+ if let Ok ( data) = serde_json:: to_string ( & data) {
97
+ CommBus :: call (
98
+ "NAVIGRAPH_UnzippedFilesRemaining" ,
99
+ & data,
100
+ CommBusBroadcastFlags :: All ,
101
+ ) ;
102
+ }
73
103
}
74
- } else if let DownloadStatus :: Failed ( _) = status {
75
- let error_message = match status {
76
- DownloadStatus :: Failed ( message) => message,
77
- _ => "Unknown error" . to_owned ( ) ,
78
- } ;
79
- // Send the error message to the JS side
80
- let mut map = HashMap :: new ( ) ;
81
- map. insert ( "error" , & error_message) ;
82
- let data = serde_json:: to_string ( & map) . unwrap ( ) ;
83
- CommBus :: call (
84
- "NAVIGRAPH_DownloadFailed" ,
85
- & data,
86
- CommBusBroadcastFlags :: All ,
87
- ) ;
88
104
89
- self . clear_zip_handler ( ) ;
105
+ // Unzip the next batch of files
106
+ let unzip_status = self . unzip_batch ( self . options . borrow ( ) . batch_size ) ;
107
+ match unzip_status {
108
+ Ok ( BatchReturn :: Finished ) => {
109
+ println ! ( "[WASM] Finished extracting" ) ;
110
+ CommBus :: call (
111
+ "NAVIGRAPH_NavdataDownloaded" ,
112
+ "" ,
113
+ CommBusBroadcastFlags :: All ,
114
+ ) ;
115
+
116
+ self . reset_download ( ) ;
117
+ }
118
+ Err ( e) => {
119
+ println ! ( "[WASM] Failed to unzip: {}" , e) ;
120
+ let mut status = self . status . borrow_mut ( ) ;
121
+ * status = DownloadStatus :: Failed ( format ! ( "Failed to unzip: {}" , e) ) ;
122
+ }
123
+ _ => ( ) ,
124
+ }
90
125
}
91
126
}
92
127
93
128
pub fn set_download_options ( self : & Rc < Self > , args : & str ) {
94
129
// Parse the JSON
95
130
let json_result: Result < serde_json:: Value , serde_json:: Error > = serde_json:: from_str ( args) ;
96
- if json_result. is_err ( ) {
97
- println ! (
98
- "[WASM] Failed to parse JSON: {}" ,
99
- json_result. err( ) . unwrap( )
100
- ) ;
131
+ if let Err ( err) = json_result {
132
+ println ! ( "[WASM] Failed to parse JSON: {}" , err) ;
101
133
return ;
102
134
}
135
+ // Safe to unwrap since we already checked if it was an error
103
136
let json = json_result. unwrap ( ) ;
104
- let batch_size = json[ "batchSize" ] . as_u64 ( ) . unwrap_or_default ( ) as usize ;
137
+ // Get batch size, if it fails to parse then just return
138
+ let batch_size = match json[ "batchSize" ] . as_u64 ( ) {
139
+ Some ( batch_size) => batch_size as usize ,
140
+ None => return ,
141
+ } ;
105
142
106
143
// Set the options (only batch size for now)
107
144
let mut options = self . options . borrow_mut ( ) ;
@@ -110,7 +147,7 @@ impl NavdataDownloader {
110
147
111
148
pub fn download ( self : & Rc < Self > , args : & str ) {
112
149
// Silently fail if we are already downloading (maybe we should send an error message?)
113
- if self . update_and_get_status ( ) != DownloadStatus :: NoDownload {
150
+ if * self . status . borrow ( ) == DownloadStatus :: Downloading {
114
151
println ! ( "[WASM] Already downloading" ) ;
115
152
return ;
116
153
}
@@ -125,6 +162,7 @@ impl NavdataDownloader {
125
162
} else {
126
163
// If we failed to parse the JSON, set our status to failed (read above for why this is in its own scope)
127
164
let mut status = self . status . borrow_mut ( ) ;
165
+ // Safe to unwrap since we already checked if it was an error
128
166
let error = json_result. err ( ) . unwrap ( ) ;
129
167
* status = DownloadStatus :: Failed ( format ! ( "JSON Parsing error from JS: {}" , error) ) ;
130
168
println ! ( "[WASM] Failed: {}" , error) ;
@@ -137,14 +175,23 @@ impl NavdataDownloader {
137
175
// Check if json has "folder"
138
176
let folder = json[ "folder" ] . as_str ( ) . unwrap_or_default ( ) . to_owned ( ) ;
139
177
178
+ // Create the request
140
179
let captured_self = self . clone ( ) ;
141
- NetworkRequestBuilder :: new ( url)
180
+ println ! ( "[WASM] Creating request" ) ;
181
+ match NetworkRequestBuilder :: new ( url)
142
182
. unwrap ( )
143
183
. with_callback ( move |request, status_code| {
144
184
captured_self. request_finished_callback ( request, status_code, folder)
145
185
} )
146
186
. get ( )
147
- . unwrap ( ) ;
187
+ {
188
+ Some ( _) => ( ) ,
189
+ None => {
190
+ let mut status = self . status . borrow_mut ( ) ;
191
+ * status = DownloadStatus :: Failed ( "Failed to create request" . to_string ( ) ) ;
192
+ return ;
193
+ }
194
+ }
148
195
}
149
196
150
197
fn request_finished_callback ( & self , request : NetworkRequest , status_code : i32 , folder : String ) {
@@ -165,6 +212,7 @@ impl NavdataDownloader {
165
212
match util:: delete_folder_recursively ( & path) {
166
213
Ok ( _) => ( ) ,
167
214
Err ( e) => {
215
+ println ! ( "[WASM] Failed to delete directory: {}" , e) ;
168
216
let mut status = self . status . borrow_mut ( ) ;
169
217
* status = DownloadStatus :: Failed ( format ! ( "Failed to delete directory: {}" , e) ) ;
170
218
return ;
@@ -185,7 +233,7 @@ impl NavdataDownloader {
185
233
* status = DownloadStatus :: Failed ( "No data received" . to_string ( ) ) ;
186
234
return ;
187
235
}
188
- // Extract the data from the request
236
+ // Extract the data from the request (safe to unwrap since we already checked if data was none)
189
237
let data = data. unwrap ( ) ;
190
238
let cursor = Cursor :: new ( data) ;
191
239
let zip = zip:: ZipArchive :: new ( cursor) ;
@@ -229,48 +277,25 @@ impl NavdataDownloader {
229
277
} )
230
278
}
231
279
232
- pub fn update_and_get_status ( & self ) -> DownloadStatus {
233
- // This basically either sets the status to no download, extracting, or done
234
-
235
- let mut status = self . status . borrow_mut ( ) ;
236
- let zip_handler_option = self . zip_handler . borrow ( ) ;
237
-
238
- // If there is no zip handler, we are not downloading
239
- * status = match zip_handler_option. as_ref ( ) {
240
- None => DownloadStatus :: NoDownload ,
241
- Some ( zip_handler) => {
242
- // Downloaded all files
243
- match zip_handler
244
- . zip_file_count
245
- . cmp ( & zip_handler. current_file_index )
246
- {
247
- std:: cmp:: Ordering :: Equal => DownloadStatus :: Done ,
248
- std:: cmp:: Ordering :: Greater => DownloadStatus :: Extracting ,
249
- _ => return status. clone ( ) ,
250
- }
251
- }
252
- } ;
280
+ pub fn unzip_batch (
281
+ & self ,
282
+ batch_size : usize ,
283
+ ) -> Result < BatchReturn , Box < dyn std:: error:: Error > > {
284
+ let mut zip_handler = self . zip_handler . borrow_mut ( ) ;
253
285
254
- // Clone here to return the updated status
255
- status. clone ( )
256
- }
286
+ let handler = zip_handler
287
+ . as_mut ( )
288
+ . ok_or_else ( || "Zip handler not found" . to_string ( ) ) ?;
289
+ let res = handler. unzip_batch ( batch_size) ?;
257
290
258
- pub fn unzip_batch ( & self , batch_size : usize ) -> bool {
259
- let mut zip_handler = self . zip_handler . borrow_mut ( ) ;
260
- match zip_handler. as_mut ( ) {
261
- Some ( handler) => handler. unzip_batch ( batch_size) ,
262
- None => false ,
263
- }
291
+ Ok ( res)
264
292
}
265
293
266
- pub fn clear_zip_handler ( & self ) {
267
- // Borrow mutably and set the zip handler to None. We need to do this in its own scope so that the borrow_mut is dropped
268
- // I really don't like this since update_and_get_status also borrows mutably but I don't know how else to do it/what the best way is
269
- {
270
- let mut zip_handler = self . zip_handler . borrow_mut ( ) ;
271
- * zip_handler = None ;
272
- }
273
- self . update_and_get_status ( ) ;
294
+ pub fn reset_download ( & self ) {
295
+ // Use the take method to replace the current value with None and drop the old value.
296
+ self . zip_handler . borrow_mut ( ) . take ( ) ;
297
+
298
+ * self . status . borrow_mut ( ) = DownloadStatus :: NoDownload ;
274
299
}
275
300
276
301
pub fn delete_all_navdata ( & self ) {
0 commit comments