1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use fast_down::{ProgressEntry, Proxy};
use parking_lot::Mutex;
use std::{collections::HashMap, net::IpAddr, sync::Arc, time::Duration};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum WriteMethod {
#[default]
Mmap,
Std,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct Config {
/// Number of threads. Recommended: `32` / `16` / `8`. More threads does not always mean faster.
pub threads: usize,
/// Proxy setting. Supports https, http, and socks5 proxies.
pub proxy: Proxy<String>,
/// Custom request headers.
pub headers: HashMap<String, String>,
/// Minimum chunk size in bytes. Recommended: `8 * 1024 * 1024`
///
/// - Chunks that are too small may cause heavy contention.
/// - When chunking is no longer possible, speculative mode is used.
pub min_chunk_size: u64,
/// Whether to ensure data is fully flushed to disk. Recommended: `false`
///
/// Set to `true` only if you need to power off immediately after download.
pub sync_all: bool,
/// Write buffer size in bytes. Recommended: `16 * 1024 * 1024`
///
/// - Only effective for [`WriteMethod::Std`]. Helps convert random writes into sequential writes.
/// - Not used for [`WriteMethod::Mmap`], as the buffer is managed by the OS.
pub write_buffer_size: usize,
/// Cache high watermark in bytes. Recommended: `16 * 1024 * 1024`
///
/// When the byte merge buffer reaches this size, a merge flush is triggered
/// to reduce the buffer to `cache_low_watermark` or below.
///
/// - Only effective for [`WriteMethod::Std`].
/// - Not used for [`WriteMethod::Mmap`].
pub cache_high_watermark: usize,
/// Cache low watermark in bytes. Recommended: `8 * 1024 * 1024`
///
/// After a merge flush, the byte merge buffer size is reduced to this level or below.
///
/// - Only effective for [`WriteMethod::Std`].
/// - Not used for [`WriteMethod::Mmap`].
pub cache_low_watermark: usize,
/// Write queue capacity. Recommended: `10240`
///
/// If download threads fill the write queue, backpressure is applied to
/// slow down downloads and prevent excessive memory usage.
pub write_queue_cap: usize,
/// Default retry interval after a request failure. Recommended: `500ms`
///
/// If the server returns a `Retry-After` header, that value takes precedence.
pub retry_gap: Duration,
/// Pull timeout. Recommended: `5000ms`
///
/// If no bytes are received within `pull_timeout` after sending the request,
/// the connection is dropped and re-established. This helps TCP detect
/// congestion and can improve download speed.
pub pull_timeout: Duration,
/// Whether to accept invalid certificates (dangerous). Recommended: `false`
pub accept_invalid_certs: bool,
/// Whether to accept invalid hostnames (dangerous). Recommended: `false`
pub accept_invalid_hostnames: bool,
/// Write method. Recommended: [`WriteMethod::Mmap`]
///
/// - [`WriteMethod::Mmap`] is fastest — it delegates writes to the OS, but:
/// 1. On 32-bit systems, the maximum file size is 4 GB, so it automatically
/// falls back to [`WriteMethod::Std`].
/// 2. The file size must be known, otherwise it falls back to [`WriteMethod::Std`].
/// 3. In rare cases, the OS may cache all data in memory and flush it all
/// at once after the download completes, causing a long post-download delay.
/// - [`WriteMethod::Std`] has the best compatibility. It sorts chunks within
/// `write_buffer_size` to approximate sequential writes.
#[cfg(feature = "file")]
pub write_method: WriteMethod,
/// Number of retries for fetching metadata. Recommended: `10`. Note: this is not
/// the retry count during download.
pub retry_times: usize,
/// Local IP addresses to bind for outgoing requests. Recommended: `Vec::new()`
///
/// If you have multiple network interfaces, you can provide their IP addresses;
/// requests will be rotated among them. This may not always improve speed.
pub local_address: Vec<IpAddr>,
/// Maximum number of speculative workers. Recommended: `3`
///
/// When the remaining chunk is smaller than `min_chunk_size` and cannot be split,
/// speculative mode is used. Up to `max_speculative` workers compete on the same
/// chunk to prevent the download from stalling near 99%.
pub max_speculative: usize,
/// Already downloaded chunks. Pass `Vec::new()` to download the entire file.
pub downloaded_chunk: Arc<Mutex<Vec<ProgressEntry>>>,
/// Smoothing window for downloaded chunks in bytes. Recommended: `8 * 1024`
///
/// Filters out small gaps in `downloaded_chunk` that are smaller than
/// `chunk_window` to reduce the number of HTTP requests.
pub chunk_window: u64,
}
impl Default for Config {
fn default() -> Self {
Self {
retry_times: 10,
threads: 32,
proxy: Proxy::System,
headers: HashMap::new(),
sync_all: false,
min_chunk_size: 8 * 1024 * 1024,
write_buffer_size: 16 * 1024 * 1024,
cache_high_watermark: 16 * 1024 * 1024,
cache_low_watermark: 8 * 1024 * 1024,
write_queue_cap: 10240,
retry_gap: Duration::from_millis(500),
pull_timeout: Duration::from_secs(5),
accept_invalid_certs: false,
accept_invalid_hostnames: false,
local_address: Vec::new(),
max_speculative: 3,
#[cfg(feature = "file")]
write_method: WriteMethod::Mmap,
downloaded_chunk: Arc::default(),
chunk_window: 8 * 1024,
}
}
}