Skip to main content

fast_down_ffi/
config.rs

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