1use crate::utils::parse_header_hashmap;
2use fast_down_ffi::{WriteMethod, fast_down::utils::Proxy};
3use itertools::Itertools;
4use serde::{Deserialize, Serialize};
5use std::{collections::HashMap, net::IpAddr, path::PathBuf, time::Duration};
6
7#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
8pub struct DownloadConfig {
9 pub save_dir: PathBuf,
10 pub threads: usize,
11 pub proxy: Proxy<String>,
12 pub headers: HashMap<String, String>,
13 pub min_chunk_size: u64,
14 pub write_buffer_size: usize,
15 pub write_queue_cap: usize,
16 pub retry_gap: Duration,
17 pub pull_timeout: Duration,
18 pub accept_invalid_certs: bool,
19 pub accept_invalid_hostnames: bool,
20 pub local_address: Vec<IpAddr>,
21 pub max_speculative: usize,
22 pub write_method: WriteMethod,
23 pub retry_times: usize,
24 pub chunk_window: u64,
25}
26
27impl Default for DownloadConfig {
28 fn default() -> Self {
29 Self {
30 save_dir: dirs::download_dir().unwrap_or_default(),
31 threads: 32,
32 proxy: Proxy::System,
33 headers: HashMap::new(),
34 min_chunk_size: 500 * 1024,
35 write_buffer_size: 16 * 1024 * 1024,
36 write_queue_cap: 10240,
37 retry_gap: Duration::from_millis(500),
38 pull_timeout: Duration::from_secs(5),
39 accept_invalid_certs: false,
40 accept_invalid_hostnames: false,
41 local_address: Vec::new(),
42 max_speculative: 3,
43 write_method: WriteMethod::Mmap,
44 retry_times: 3,
45 chunk_window: 8 * 1024,
46 }
47 }
48}
49
50impl DownloadConfig {
51 pub fn to_ui_download_config(&self) -> crate::ui::DownloadConfig {
52 crate::ui::DownloadConfig {
53 accept_invalid_certs: self.accept_invalid_certs,
54 accept_invalid_hostnames: self.accept_invalid_hostnames,
55 headers: self
56 .headers
57 .iter()
58 .map(|(k, v)| format!("{k}: {v}"))
59 .join("\n")
60 .into(),
61 ips: self
62 .local_address
63 .iter()
64 .map(|addr| addr.to_string())
65 .join("\n")
66 .into(),
67 max_speculative: self.max_speculative as i32,
68 min_chunk_size: self.min_chunk_size as i32,
69 proxy: match self.proxy.as_deref() {
70 Proxy::No => "null",
71 Proxy::System => "",
72 Proxy::Custom(proxy) => proxy,
73 }
74 .into(),
75 pull_timeout_ms: self.pull_timeout.as_millis() as i32,
76 retry_gap_ms: self.retry_gap.as_millis() as i32,
77 save_dir: self.save_dir.to_string_lossy().as_ref().into(),
78 threads: self.threads as i32,
79 write_buffer_size: self.write_buffer_size as i32,
80 write_method: match self.write_method {
81 WriteMethod::Mmap => 0,
82 WriteMethod::Std => 1,
83 },
84 write_queue_cap: self.write_queue_cap as i32,
85 retry_times: self.retry_times as i32,
86 chunk_window: self.chunk_window as i32,
87 }
88 }
89}
90
91impl From<&crate::ui::DownloadConfig> for DownloadConfig {
92 fn from(value: &crate::ui::DownloadConfig) -> Self {
93 Self {
94 save_dir: value.save_dir.as_str().into(),
95 threads: value.threads as usize,
96 proxy: match value.proxy.as_str() {
97 "" => Proxy::System,
98 "null" => Proxy::No,
99 proxy => Proxy::Custom(proxy.to_string()),
100 },
101 headers: parse_header_hashmap(&value.headers),
102 min_chunk_size: value.min_chunk_size as u64,
103 write_buffer_size: value.write_buffer_size as usize,
104 write_queue_cap: value.write_queue_cap as usize,
105 retry_gap: Duration::from_millis(value.retry_gap_ms as u64),
106 pull_timeout: Duration::from_millis(value.pull_timeout_ms as u64),
107 accept_invalid_certs: value.accept_invalid_certs,
108 accept_invalid_hostnames: value.accept_invalid_hostnames,
109 local_address: value
110 .ips
111 .as_str()
112 .lines()
113 .filter_map(|line| line.trim().parse().ok())
114 .collect(),
115 max_speculative: value.max_speculative as usize,
116 write_method: match value.write_method {
117 1 => WriteMethod::Std,
118 _ => WriteMethod::Mmap,
119 },
120 retry_times: value.retry_times as usize,
121 chunk_window: value.chunk_window as u64,
122 }
123 }
124}
125
126#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
127pub struct GeneralConfig {
128 pub max_concurrency: usize,
129 pub auto_start: bool,
130}
131
132impl Default for GeneralConfig {
133 fn default() -> Self {
134 Self {
135 max_concurrency: 2,
136 auto_start: false,
137 }
138 }
139}
140
141impl From<&crate::ui::GeneralConfig> for GeneralConfig {
142 fn from(value: &crate::ui::GeneralConfig) -> Self {
143 Self {
144 max_concurrency: value.max_concurrency as usize,
145 auto_start: value.auto_start,
146 }
147 }
148}
149
150impl GeneralConfig {
151 pub fn to_ui_general_config(&self) -> crate::ui::GeneralConfig {
152 crate::ui::GeneralConfig {
153 max_concurrency: self.max_concurrency as i32,
154 auto_start: self.auto_start,
155 }
156 }
157}