@@ -55,13 +55,37 @@ impl Chunk {
5555 }
5656}
5757
58+ #[ derive( Clone ) ]
59+ pub struct DownloadConfig {
60+ pub max_chunk_size : u64 ,
61+ }
62+
63+ impl DownloadConfig {
64+ pub fn new ( ) -> Self {
65+ Self {
66+ max_chunk_size : _10MB,
67+ }
68+ }
69+ pub fn set_max_chunk_size ( mut self , size : u64 ) -> Self {
70+ self . max_chunk_size = size;
71+ self
72+ }
73+ }
74+
75+ impl Default for DownloadConfig {
76+ fn default ( ) -> Self {
77+ Self :: new ( )
78+ }
79+ }
80+
5881pub struct Downloader {
5982 url : String ,
6083 headers : HeaderMap ,
6184 file_size : Option < u64 > ,
6285 filename : Option < String > ,
6386 chunks : Arc < Mutex < Vec < Chunk > > > , // this stores downloaded chunk size
6487 reporter : Arc < dyn ProgressReporter + Send + Sync > ,
88+ config : Arc < DownloadConfig > ,
6589}
6690
6791pub trait HeaderUtils {
@@ -141,9 +165,15 @@ impl Downloader {
141165 filename : None ,
142166 chunks : Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
143167 reporter : Arc :: new ( NoopReporter ) ,
168+ config : Arc :: new ( DownloadConfig :: default ( ) ) ,
144169 }
145170 }
146171
172+ pub fn with_config ( mut self , config : DownloadConfig ) -> Self {
173+ self . config = Arc :: new ( config) ;
174+ self
175+ }
176+
147177 pub fn with_reporter < R : ProgressReporter + Send + Sync + ' static > (
148178 mut self ,
149179 reporter : R ,
@@ -265,24 +295,18 @@ impl Downloader {
265295 file. lock ( ) . await . set_len ( file_size) . await ?;
266296
267297 let mut start = 0 ;
268- let thread_size = file_size / threads;
269- let mut byte_size = thread_size;
270-
271- //ignore threads if the file is less than a MB.
272- if file_size < _1MB {
298+ // Determine chunk size: default to per-thread slice, cap at 10 MB for memory,
299+ // or use full file if smaller than 1 MB (no threading benefit).
300+ let chunk_size = if file_size < _1MB {
273301 println ! ( "ℹ️ The file is smaller than 1 MB, so skipping threads." ) ;
274- byte_size = file_size;
275- }
276-
277- // if the byte size is larger than 10 MB, split into 10 MB chunks
278- // so that memory consumption is less.
279- if thread_size > _10MB {
280- byte_size = _10MB
281- }
302+ file_size
303+ } else {
304+ ( file_size / threads) . min ( self . config . max_chunk_size )
305+ } ;
282306
283307 // split chunks to download
284308 while start < file_size {
285- let end = min ( start + byte_size , file_size) ;
309+ let end = min ( start + chunk_size , file_size) ;
286310 self . chunks . lock ( ) . await . push ( Chunk :: new ( start, end) ) ;
287311 start = end + 1 ;
288312 }
@@ -308,6 +332,7 @@ impl Downloader {
308332 let url = self . url . clone ( ) ;
309333 let index_clone = Arc :: clone ( & index) ;
310334 let reporter_clone = Arc :: clone ( & self . reporter ) ;
335+ let config = Arc :: clone ( & self . config ) ;
311336
312337 let task = tokio:: spawn ( async move {
313338 let mut worker_total: u64 = 0 ;
@@ -332,6 +357,7 @@ impl Downloader {
332357 filename : None ,
333358 chunks : Arc :: clone ( & chunks) ,
334359 reporter : Arc :: clone ( & reporter_clone) ,
360+ config : Arc :: clone ( & config) ,
335361 } ;
336362
337363 // Download the chunk and accumulate the bytes downloaded by this worker
@@ -440,4 +466,15 @@ mod tests {
440466 assert_eq ! ( downloader. file_size, Some ( 0 ) ) ;
441467 } ) ;
442468 }
469+ #[ test]
470+ fn test_custom_download_config ( ) {
471+ let config = DownloadConfig :: new ( ) . set_max_chunk_size ( 5 * 1024 * 1024 ) ;
472+ assert_eq ! ( config. max_chunk_size, 5 * 1024 * 1024 ) ;
473+ }
474+
475+ #[ test]
476+ fn test_default_download_config ( ) {
477+ let config = DownloadConfig :: new ( ) ;
478+ assert_eq ! ( config. max_chunk_size, 10 * 1024 * 1024 ) ;
479+ }
443480}
0 commit comments