Skip to content

Commit af6d929

Browse files
committed
refactor: more cleanup, also add options to downloader
1 parent 90417ad commit af6d929

File tree

7 files changed

+111
-100
lines changed

7 files changed

+111
-100
lines changed

Sources/Code/WASM/navdata_updater/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ msfs = { git = "https://github.com/pepperoni505/msfs-rs.git", branch = "main" }
1818
serde = "1.0.190"
1919
serde_json = "1.0.108"
2020
rusqlite = { git = "https://github.com/navigraph/rusqlite", rev = "366c520", features = ["bundled", "wasm32-wasi-vfs"] }
21-
zip = { version = "0.6.4", default-features = false, features = ["deflate"] }
21+
zip = { version = "0.6.4", default-features = false, features = ["deflate"] }
Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use std::collections::HashMap;
21
use std::rc::Rc;
32

4-
use crate::download::downloader::{DownloadStatus, NavdataDownloader};
3+
use crate::download::downloader::NavdataDownloader;
54
use msfs::{commbus::*, MSFSEvent};
65

76
pub struct Dispatcher<'a> {
@@ -12,7 +11,7 @@ pub struct Dispatcher<'a> {
1211
impl<'a> Dispatcher<'a> {
1312
pub fn new() -> Self {
1413
Dispatcher {
15-
commbus: CommBus::new(),
14+
commbus: CommBus::default(),
1615
downloader: Rc::new(NavdataDownloader::new()),
1716
}
1817
}
@@ -26,8 +25,7 @@ impl<'a> Dispatcher<'a> {
2625
self.handle_update();
2726
}
2827
MSFSEvent::PreKill => {
29-
// TODO: replace this!
30-
CommBus::unregister_all();
28+
self.commbus.unregister_all();
3129
}
3230

3331
_ => {}
@@ -40,62 +38,26 @@ impl<'a> Dispatcher<'a> {
4038
let captured_downloader = self.downloader.clone();
4139
self.commbus
4240
.register("NAVIGRAPH_DownloadNavdata", move |args| {
43-
captured_downloader.download(args)
41+
captured_downloader.download(Dispatcher::trim_null_terminator(args))
4442
})
4543
.expect("Failed to register NAVIGRAPH_DownloadNavdata");
4644
}
47-
// Left out for now as the sim doesn't seem to like deleting files (?)
48-
// {
49-
// let captured_downloader = self.downloader.clone();
50-
// self.commbus
51-
// .register("NAVIGRAPH_DeleteAllFiles", move |_| {
52-
// captured_downloader.delete_all_files()
53-
// })
54-
// .expect("Failed to register NAVIGRAPH_DeleteAllFiles");
55-
// }
45+
{
46+
let captured_downloader = self.downloader.clone();
47+
self.commbus
48+
.register("NAVIGRAPH_SetDownloadOptions", move |args| {
49+
captured_downloader.set_download_options(Dispatcher::trim_null_terminator(args))
50+
})
51+
.expect("Failed to register NAVIGRAPH_SetDownloadOptions");
52+
}
5653
}
5754

5855
fn handle_update(&mut self) {
5956
// update unzip
60-
// todo: maybe another way to check instead of cloning? i mean we drop the value anyway but not sure on performance
61-
let captured_downloader = self.downloader.clone();
62-
let status = captured_downloader.update_and_get_status();
63-
if captured_downloader.update_and_get_status() == DownloadStatus::Extracting {
64-
let statistics = captured_downloader.get_download_statistics().unwrap(); // will always be Some because we are extracting
65-
let mut map = HashMap::new();
66-
map.insert("total", statistics.total_files);
67-
map.insert("unzipped", statistics.files_unzipped);
68-
let data = serde_json::to_string(&map).unwrap();
69-
CommBus::call(
70-
"NAVIGRAPH_UnzippedFilesRemaining",
71-
&data,
72-
CommBusBroadcastFlags::All,
73-
);
74-
let has_more_files = captured_downloader.unzip_batch(10);
75-
if !has_more_files {
76-
println!("[WASM] finished unzip");
77-
CommBus::call(
78-
"NAVIGRAPH_NavdataDownloaded",
79-
"",
80-
CommBusBroadcastFlags::All,
81-
);
82-
captured_downloader.clear_zip_handler();
83-
}
84-
} else if let DownloadStatus::Failed(_) = status {
85-
let error_message = match status {
86-
DownloadStatus::Failed(message) => message,
87-
_ => "Unknown error".to_owned(),
88-
};
89-
let mut map = HashMap::new();
90-
map.insert("error", &error_message);
91-
let data = serde_json::to_string(&map).unwrap();
92-
CommBus::call(
93-
"NAVIGRAPH_DownloadFailed",
94-
&data,
95-
CommBusBroadcastFlags::All,
96-
);
97-
// clear the zip handler
98-
captured_downloader.clear_zip_handler();
99-
}
57+
self.downloader.on_update();
58+
}
59+
60+
fn trim_null_terminator(s: &str) -> &str {
61+
s.trim_end_matches(char::from(0))
10062
}
10163
}

Sources/Code/WASM/navdata_updater/src/download/downloader.rs

Lines changed: 91 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
use std::cell::RefCell;
2+
use std::collections::HashMap;
23
use std::fs;
34
use std::io::Cursor;
45
use std::path::PathBuf;
56
use std::rc::Rc;
67

7-
use msfs::network::*;
8+
use msfs::{commbus::*, network::*};
89

910
use crate::download::zip_handler::ZipFileHandler;
10-
use crate::util::JsonParser;
11+
12+
pub struct DownloadOptions {
13+
batch_size: usize,
14+
}
1115

1216
pub struct DownloadStatistics {
1317
pub total_files: usize,
@@ -27,42 +31,110 @@ pub enum DownloadStatus {
2731
pub struct NavdataDownloader {
2832
zip_handler: RefCell<Option<ZipFileHandler<Cursor<Vec<u8>>>>>,
2933
status: RefCell<DownloadStatus>,
34+
options: RefCell<DownloadOptions>,
3035
}
3136

3237
impl NavdataDownloader {
3338
pub fn new() -> Self {
3439
NavdataDownloader {
3540
zip_handler: RefCell::new(None),
3641
status: RefCell::new(DownloadStatus::NoDownload),
42+
options: RefCell::new(DownloadOptions { batch_size: 10 }), // default batch size
43+
}
44+
}
45+
46+
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+
);
61+
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");
66+
CommBus::call(
67+
"NAVIGRAPH_NavdataDownloaded",
68+
"",
69+
CommBusBroadcastFlags::All,
70+
);
71+
72+
self.clear_zip_handler();
73+
}
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+
89+
self.clear_zip_handler();
3790
}
3891
}
3992

40-
pub fn download(self: &Rc<Self>, args: &[u8]) {
41-
// Silently fail if we are already downloading
93+
pub fn set_download_options(self: &Rc<Self>, args: &str) {
94+
// Parse the JSON
95+
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+
);
101+
return;
102+
}
103+
let json = json_result.unwrap();
104+
let batch_size = json["batchSize"].as_u64().unwrap_or_default() as usize;
105+
106+
// Set the options (only batch size for now)
107+
let mut options = self.options.borrow_mut();
108+
options.batch_size = batch_size;
109+
}
110+
111+
pub fn download(self: &Rc<Self>, args: &str) {
112+
// Silently fail if we are already downloading (maybe we should send an error message?)
42113
if self.update_and_get_status() != DownloadStatus::NoDownload {
43114
println!("[WASM] Already downloading");
44115
return;
45116
}
46117

47-
// Set our status to downloading (needs to be done in its own scope so that the borrow_mut is dropped)
48-
{
118+
// Parse the JSON
119+
let json_result: Result<serde_json::Value, serde_json::Error> = serde_json::from_str(args);
120+
if json_result.is_ok() {
121+
// Set our status to downloading (needs to be done in its own scope so that the borrow_mut is dropped)
49122
let mut status = self.status.borrow_mut();
50123
*status = DownloadStatus::Downloading;
51124
println!("[WASM] Downloading");
52-
}
53-
54-
let json_result = JsonParser::parse(args);
55-
if json_result.is_err() {
125+
} else {
126+
// If we failed to parse the JSON, set our status to failed (read above for why this is in its own scope)
56127
let mut status = self.status.borrow_mut();
57128
let error = json_result.err().unwrap();
58129
*status = DownloadStatus::Failed(format!("JSON Parsing error from JS: {}", error));
59130
println!("[WASM] Failed: {}", error);
60131
return;
61132
}
133+
// Safe to unwrap since we already checked if it was an error
62134
let json = json_result.unwrap();
63135
let url = json["url"].as_str().unwrap_or_default();
64136

65-
// check if json has "folder"
137+
// Check if json has "folder"
66138
let folder = json["folder"].as_str().unwrap_or_default().to_owned();
67139

68140
let captured_self = self.clone();
@@ -76,6 +148,7 @@ impl NavdataDownloader {
76148
}
77149

78150
fn request_finished_callback(&self, request: NetworkRequest, status_code: i32, folder: String) {
151+
// Fail if the status code is not 200
79152
if status_code != 200 {
80153
let mut status = self.status.borrow_mut();
81154
*status = DownloadStatus::Failed(format!(
@@ -85,13 +158,15 @@ impl NavdataDownloader {
85158
));
86159
return;
87160
}
161+
// Create the directory if it doesn't exist
88162
let path = PathBuf::from(format!("\\work/navdata/{}", folder));
89163
if let Err(e) = fs::create_dir_all(&path) {
90164
let mut status = self.status.borrow_mut();
91165
*status = DownloadStatus::Failed(format!("Failed to create directory: {}", e));
92166
return;
93167
}
94168

169+
// Check the data from the request
95170
let data = request.data();
96171
if data.is_none() {
97172
let mut status = self.status.borrow_mut();
@@ -109,10 +184,11 @@ impl NavdataDownloader {
109184
);
110185
return;
111186
}
187+
// Unwrap is safe since we already checked if it was an error
112188
let zip = zip.unwrap();
113189

190+
// Create the zip handler
114191
let handler = ZipFileHandler::new(zip, path);
115-
116192
let mut zip_handler = self.zip_handler.borrow_mut();
117193
*zip_handler = Some(handler);
118194

@@ -127,7 +203,7 @@ impl NavdataDownloader {
127203
pub fn get_download_statistics(
128204
&self,
129205
) -> Result<DownloadStatistics, Box<dyn std::error::Error>> {
130-
let zip_handler_ref = self.zip_handler.borrow(); // Borrow and hold onto the reference
206+
let zip_handler_ref = self.zip_handler.borrow();
131207
let zip_handler = zip_handler_ref.as_ref().ok_or("No zip handler")?;
132208

133209
let total_files = zip_handler.zip_file_count;
@@ -141,8 +217,9 @@ impl NavdataDownloader {
141217
})
142218
}
143219

144-
/// This basically either sets the status to no download, extracting, or done
145220
pub fn update_and_get_status(&self) -> DownloadStatus {
221+
// This basically either sets the status to no download, extracting, or done
222+
146223
let mut status = self.status.borrow_mut();
147224
let zip_handler_option = self.zip_handler.borrow();
148225

@@ -166,9 +243,6 @@ impl NavdataDownloader {
166243
status.clone()
167244
}
168245

169-
/// Unzips a batch of files
170-
///
171-
/// Returns true if there are more files to unzip (false if we are done)
172246
pub fn unzip_batch(&self, batch_size: usize) -> bool {
173247
let mut zip_handler = self.zip_handler.borrow_mut();
174248
match zip_handler.as_mut() {
@@ -186,18 +260,4 @@ impl NavdataDownloader {
186260
}
187261
self.update_and_get_status();
188262
}
189-
190-
pub fn delete_all_files(&self) {
191-
// if we are downloading, quietly fail
192-
if self.update_and_get_status() != DownloadStatus::NoDownload {
193-
println!("[WASM] Cannot delete files while downloading");
194-
return;
195-
}
196-
let path = PathBuf::from("\\work/navdata");
197-
// iterate through all files in the directory and delete them
198-
match fs::remove_dir_all(&path) {
199-
Ok(_) => (),
200-
Err(e) => println!("[WASM] Failed to delete all files: {}", e),
201-
}
202-
}
203263
}

Sources/Code/WASM/navdata_updater/src/download/zip_handler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ impl<R: io::Read + io::Seek> ZipFileHandler<R> {
2828
let unwrapped_zip_archive = self.zip_archive.as_mut().unwrap();
2929
for _ in 0..batch_size {
3030
if self.current_file_index >= self.zip_file_count {
31-
// lets clear our zip
31+
// Done extracting, drop the zip archive
3232
self.zip_archive = None;
33-
return false; // no more files to unzip
33+
return false;
3434
}
3535

3636
let mut file = match unwrapped_zip_archive.by_index(self.current_file_index) {

Sources/Code/WASM/navdata_updater/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
mod dispatcher;
22
mod download;
3-
mod util;
43

54
#[msfs::gauge(name=navdata_updater)]
65
async fn navdata_updater(mut gauge: msfs::Gauge) -> Result<(), Box<dyn std::error::Error>> {

Sources/Code/WASM/navdata_updater/src/util.rs

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)