You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/// The trait definition for a function that can be called through the navigation data interface
27
31
traitFunction:DeserializeOwned{
28
32
typeReturnType:Serialize;
@@ -70,13 +74,54 @@ impl Function for DownloadNavigationData {
70
74
unzipped:None,
71
75
})?;
72
76
73
-
// Download the data
74
-
let data = NetworkRequestBuilder::new(&self.url)
75
-
.context("can't create new NetworkRequestBuilder")?
76
-
.get()
77
-
.context(".get() returned None")?
78
-
.wait_for_data()
79
-
.await?;
77
+
// We need to download the data in chunks of DOWNLOAD_CHUNK_SIZE_BYTES to avoid a timeout, so we need to keep track of a "working" accumulation of all responses
78
+
letmut bytes = vec![];
79
+
80
+
letmut current_byte_index = 0;
81
+
loop{
82
+
// Dispatch the request
83
+
let range_end = current_byte_index + DOWNLOAD_CHUNK_SIZE_BYTES - 1;
84
+
let request = NetworkRequestBuilder::new(&self.url)
85
+
.context("can't create new NetworkRequestBuilder")?
// Get the size of actual data. The response will be as long as the requested range is, but content-length contains the amount we actually want to read
94
+
let content_length = request
95
+
.header_section("content-length")
96
+
.context("no content-length header")?
97
+
.trim()
98
+
.parse::<usize>()?;
99
+
100
+
// Check if we somehow have no more data (file size would be a perfect multiple of DOWNLOAD_CHUNK_SIZE_BYTES)
101
+
if content_length == 0{
102
+
break;
103
+
}
104
+
105
+
let data = request.data().ok_or(anyhow!("no data"))?;
106
+
107
+
// Make sure we don't panic if server sent less data than claimed (should never happen, but avoid a panic)
108
+
if data.len() < content_length {
109
+
returnErr(anyhow!(
110
+
"Received less data ({}) than content-length ({})",
111
+
data.len(),
112
+
content_length
113
+
));
114
+
}
115
+
116
+
bytes.write_all(&data[..content_length])?;
117
+
118
+
// Check if we have hit the last chunk
119
+
if content_length < DOWNLOAD_CHUNK_SIZE_BYTES{
120
+
break;
121
+
}
122
+
123
+
current_byte_index += content_length;
124
+
}
80
125
81
126
// Only close connection if DATABASE_STATE has already been initialized - otherwise we end up unnecessarily copying the bundled data and instantly replacing it (due to initialization logic in database state)
82
127
ifLazy::get(&DATABASE_STATE).is_some(){
@@ -103,7 +148,7 @@ impl Function for DownloadNavigationData {
103
148
})?;
104
149
105
150
// Load the zip archive
106
-
letmut zip = ZipArchive::new(Cursor::new(data))?;
151
+
letmut zip = ZipArchive::new(Cursor::new(bytes))?;
107
152
108
153
// Ensure parent folder exists (ignore the result as it will return an error if it already exists)
109
154
let _ = fs::create_dir_all(WORK_NAVIGATION_DATA_FOLDER);
0 commit comments