@@ -18,7 +18,7 @@ use reqwest::{Client, ClientBuilder, Proxy, header};
1818use rustls:: crypto:: aws_lc_rs;
1919#[ cfg( feature = "reqwest-rustls-tls" ) ]
2020use rustls_platform_verifier:: Verifier ;
21- use sha2:: { Digest , Sha256 } ;
21+ use sha2:: Sha256 ;
2222use thiserror:: Error ;
2323use tokio_stream:: StreamExt ;
2424use tracing:: { debug, warn} ;
@@ -163,35 +163,9 @@ impl<'a> Download<'a> {
163163 async fn download_file_ ( & self ) -> anyhow:: Result < ( ) > {
164164 debug ! ( url = %self . url, "downloading file" ) ;
165165
166- // This callback will write the download to disk and optionally
167- // hash the contents, then forward the notification up the stack
168- let callback: & dyn Fn ( Event < ' _ > ) -> anyhow:: Result < ( ) > = & |msg| {
169- if let Event :: DownloadDataReceived ( data) = msg
170- && let Some ( h) = self . hasher . as_ref ( )
171- {
172- h. borrow_mut ( ) . update ( data) ;
173- }
174-
175- match msg {
176- Event :: DownloadContentLengthReceived ( len) => {
177- if let Some ( status) = self . status {
178- status. received_length ( len)
179- }
180- }
181- Event :: DownloadDataReceived ( data) => {
182- if let Some ( status) = self . status {
183- status. received_data ( data. len ( ) )
184- }
185- }
186- Event :: ResumingPartialDownload => debug ! ( "resuming partial download" ) ,
187- }
188-
189- Ok ( ( ) )
190- } ;
191-
192166 // Download the file
193167
194- let res = self . download_to_path ( Some ( callback ) ) . await ;
168+ let res = self . download_to_path ( ) . await ;
195169
196170 // The notification should only be sent if the download was successful (i.e. didn't timeout)
197171 if let Some ( status) = self . status {
@@ -204,8 +178,8 @@ impl<'a> Download<'a> {
204178 res
205179 }
206180
207- async fn download_to_path ( & self , callback : Option < DownloadCallback < ' _ > > ) -> anyhow:: Result < ( ) > {
208- let Err ( err) = self . download_impl ( callback ) . await else {
181+ async fn download_to_path ( & self ) -> anyhow:: Result < ( ) > {
182+ let Err ( err) = self . download_impl ( ) . await else {
209183 return Ok ( ( ) ) ;
210184 } ;
211185
@@ -224,15 +198,14 @@ impl<'a> Download<'a> {
224198 )
225199 }
226200
227- async fn download_impl ( & self , callback : Option < DownloadCallback < ' _ > > ) -> anyhow:: Result < ( ) > {
228- let ( file, resume_from) = if self . resume {
201+ async fn download_impl ( & self ) -> anyhow:: Result < ( ) > {
202+ let ( mut file, resume_from) = if self . resume {
229203 // TODO: blocking call
230204 let possible_partial = OpenOptions :: new ( ) . read ( true ) . open ( self . path ) ;
231205
232206 let downloaded_so_far = if let Ok ( mut partial) = possible_partial {
233- if let Some ( cb) = callback {
234- cb ( Event :: ResumingPartialDownload ) ?;
235-
207+ debug ! ( "resuming partial download" ) ;
208+ if let Some ( status) = self . status {
236209 let mut buf = vec ! [ 0 ; 32768 ] ;
237210 let mut downloaded_so_far = 0 ;
238211 loop {
@@ -241,7 +214,7 @@ impl<'a> Download<'a> {
241214 if n == 0 {
242215 break ;
243216 }
244- cb ( Event :: DownloadDataReceived ( & buf [ ..n ] ) ) ? ;
217+ status . received_data ( n ) ;
245218 }
246219
247220 downloaded_so_far
@@ -276,7 +249,6 @@ impl<'a> Download<'a> {
276249 )
277250 } ;
278251
279- let file = RefCell :: new ( file) ;
280252 let client = match self . options . tls {
281253 #[ cfg( feature = "reqwest-rustls-tls" ) ]
282254 Tls :: Rustls => rustls_client ( self . options . timeout ) ?,
@@ -285,25 +257,9 @@ impl<'a> Download<'a> {
285257 } ;
286258
287259 // TODO: the sync callback will stall the async runtime if IO calls block, which is OS dependent. Rearrange.
288- self . execute (
289- resume_from,
290- & |event| {
291- if let Event :: DownloadDataReceived ( data) = event {
292- file. borrow_mut ( )
293- . write_all ( data)
294- . context ( "unable to write download to disk" ) ?;
295- }
296- match callback {
297- Some ( cb) => cb ( event) ,
298- None => Ok ( ( ) ) ,
299- }
300- } ,
301- client,
302- )
303- . await ?;
260+ self . execute ( resume_from, & mut file, client) . await ?;
304261
305- file. borrow_mut ( )
306- . sync_data ( )
262+ file. sync_data ( )
307263 . context ( "unable to sync download to disk" ) ?;
308264
309265 Ok :: < ( ) , anyhow:: Error > ( ( ) )
@@ -312,7 +268,7 @@ impl<'a> Download<'a> {
312268 async fn execute (
313269 & self ,
314270 resume_from : u64 ,
315- callback : & dyn Fn ( Event < ' _ > ) -> anyhow :: Result < ( ) > ,
271+ file : & mut fs :: File ,
316272 client : & Client ,
317273 ) -> anyhow:: Result < ( ) > {
318274 // Short-circuit reqwest for the "file:" URL scheme
@@ -339,7 +295,13 @@ impl<'a> Download<'a> {
339295 if bytes_read == 0 {
340296 break ;
341297 }
342- callback ( Event :: DownloadDataReceived ( & buffer[ 0 ..bytes_read] ) ) ?;
298+
299+ file. write_all ( & buffer[ ..bytes_read] )
300+ . context ( "unable to write download to disk" ) ?;
301+
302+ if let Some ( status) = self . status {
303+ status. received_data ( bytes_read) ;
304+ }
343305 }
344306
345307 return Ok ( ( ) ) ;
@@ -362,13 +324,19 @@ impl<'a> Download<'a> {
362324
363325 if let Some ( len) = res. content_length ( ) {
364326 let len = len + resume_from;
365- callback ( Event :: DownloadContentLengthReceived ( len) ) ?;
327+ if let Some ( status) = self . status {
328+ status. received_length ( len) ;
329+ }
366330 }
367331
368332 let mut stream = res. bytes_stream ( ) ;
369333 while let Some ( item) = stream. next ( ) . await {
370334 let bytes = item. map_err ( DownloadError :: Reqwest ) ?;
371- callback ( Event :: DownloadDataReceived ( & bytes) ) ?;
335+ file. write_all ( & bytes)
336+ . context ( "unable to write download to disk" ) ?;
337+ if let Some ( status) = self . status {
338+ status. received_data ( bytes. len ( ) ) ;
339+ }
372340 }
373341 Ok ( ( ) )
374342 }
@@ -403,17 +371,6 @@ enum Tls {
403371 NativeTls ,
404372}
405373
406- #[ derive( Debug , Copy , Clone ) ]
407- enum Event < ' a > {
408- ResumingPartialDownload ,
409- /// Received the Content-Length of the to-be downloaded data.
410- DownloadContentLengthReceived ( u64 ) ,
411- /// Received some data.
412- DownloadDataReceived ( & ' a [ u8 ] ) ,
413- }
414-
415- type DownloadCallback < ' a > = & ' a dyn Fn ( Event < ' _ > ) -> anyhow:: Result < ( ) > ;
416-
417374fn client_generic ( ) -> ClientBuilder {
418375 Client :: builder ( )
419376 // HACK: set `pool_max_idle_per_host` to `0` to avoid an issue in the underlying
0 commit comments