alopex_chirps_file_transfer/
options.rs1use serde::{Deserialize, Serialize};
2use std::time::Duration;
3
4pub const DEFAULT_CHUNK_SIZE: usize = 1024 * 1024;
6pub const MIN_CHUNK_SIZE: usize = 64 * 1024;
8pub const MAX_CHUNK_SIZE: usize = 16 * 1024 * 1024;
10const DEFAULT_CONCURRENCY: usize = 4;
11const DEFAULT_CLOCK_SKEW_TOLERANCE_SECS: u64 = 2;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
14pub enum CompressionAlgorithm {
16 #[default]
18 None,
19 Zstd,
21 ZstdLevel(i32),
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
26pub enum HashAlgorithm {
28 #[default]
30 Sha256,
31 Blake3,
33 XxHash64,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
38pub enum TransferMode {
40 #[default]
42 Copy,
43 Move,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
48pub enum SyncDirection {
50 Push,
52 Pull,
54 Bidirectional,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
59pub enum ConflictResolution {
61 #[default]
63 NewerWins,
64 SourceWins,
66 TargetWins,
68 Manual,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
73pub enum SortBy {
75 #[default]
77 Name,
78 Size,
80 ModifiedTime,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct RetryPolicy {
87 pub max_retries: u8,
88 pub initial_delay: Duration,
89 pub max_delay: Duration,
90 pub backoff_multiplier: f64,
91 pub jitter: bool,
92}
93
94impl Default for RetryPolicy {
95 fn default() -> Self {
96 RetryPolicy {
97 max_retries: 3,
98 initial_delay: Duration::from_millis(100),
99 max_delay: Duration::from_secs(10),
100 backoff_multiplier: 2.0,
101 jitter: true,
102 }
103 }
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct TransferOptions {
109 pub chunk_size: usize,
110 pub concurrency: usize,
111 pub compression: CompressionAlgorithm,
112 pub bandwidth_limit: Option<u64>,
113 pub retry_policy: RetryPolicy,
114 pub verify_on_complete: bool,
115 pub hash_algorithm: HashAlgorithm,
116 pub resumable: bool,
117 pub overwrite: bool,
118 pub mode: TransferMode,
119 pub preserve_metadata: bool,
120}
121
122impl Default for TransferOptions {
123 fn default() -> Self {
124 TransferOptions {
125 chunk_size: DEFAULT_CHUNK_SIZE,
126 concurrency: DEFAULT_CONCURRENCY,
127 compression: CompressionAlgorithm::None,
128 bandwidth_limit: None,
129 retry_policy: RetryPolicy::default(),
130 verify_on_complete: true,
131 hash_algorithm: HashAlgorithm::Sha256,
132 resumable: true,
133 overwrite: false,
134 mode: TransferMode::Copy,
135 preserve_metadata: true,
136 }
137 }
138}
139
140impl TransferOptions {
141 pub fn with_chunk_size(mut self, chunk_size: usize) -> Self {
146 self.chunk_size = chunk_size;
147 self
148 }
149
150 pub fn with_concurrency(mut self, concurrency: usize) -> Self {
155 self.concurrency = concurrency;
156 self
157 }
158
159 pub fn with_compression(mut self, compression: CompressionAlgorithm) -> Self {
164 self.compression = compression;
165 self
166 }
167
168 pub fn with_bandwidth_limit(mut self, bandwidth_limit: Option<u64>) -> Self {
173 self.bandwidth_limit = bandwidth_limit;
174 self
175 }
176
177 pub fn with_retry_policy(mut self, retry_policy: RetryPolicy) -> Self {
182 self.retry_policy = retry_policy;
183 self
184 }
185
186 pub fn with_verify_on_complete(mut self, verify_on_complete: bool) -> Self {
191 self.verify_on_complete = verify_on_complete;
192 self
193 }
194
195 pub fn with_hash_algorithm(mut self, hash_algorithm: HashAlgorithm) -> Self {
200 self.hash_algorithm = hash_algorithm;
201 self
202 }
203
204 pub fn with_resumable(mut self, resumable: bool) -> Self {
209 self.resumable = resumable;
210 self
211 }
212
213 pub fn with_overwrite(mut self, overwrite: bool) -> Self {
218 self.overwrite = overwrite;
219 self
220 }
221
222 pub fn with_mode(mut self, mode: TransferMode) -> Self {
227 self.mode = mode;
228 self
229 }
230
231 pub fn with_preserve_metadata(mut self, preserve_metadata: bool) -> Self {
236 self.preserve_metadata = preserve_metadata;
237 self
238 }
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct SyncOptions {
244 pub transfer: TransferOptions,
245 pub direction: SyncDirection,
246 pub conflict_resolution: ConflictResolution,
247 pub follow_symlinks: bool,
248 pub clock_skew_tolerance: Duration,
249}
250
251impl Default for SyncOptions {
252 fn default() -> Self {
253 SyncOptions {
254 transfer: TransferOptions::default(),
255 direction: SyncDirection::Push,
256 conflict_resolution: ConflictResolution::NewerWins,
257 follow_symlinks: false,
258 clock_skew_tolerance: Duration::from_secs(DEFAULT_CLOCK_SKEW_TOLERANCE_SECS),
259 }
260 }
261}
262
263impl SyncOptions {
264 pub fn with_transfer(mut self, transfer: TransferOptions) -> Self {
269 self.transfer = transfer;
270 self
271 }
272
273 pub fn with_direction(mut self, direction: SyncDirection) -> Self {
278 self.direction = direction;
279 self
280 }
281
282 pub fn with_conflict_resolution(mut self, conflict_resolution: ConflictResolution) -> Self {
287 self.conflict_resolution = conflict_resolution;
288 self
289 }
290
291 pub fn with_follow_symlinks(mut self, follow_symlinks: bool) -> Self {
296 self.follow_symlinks = follow_symlinks;
297 self
298 }
299
300 pub fn with_clock_skew_tolerance(mut self, clock_skew_tolerance: Duration) -> Self {
305 self.clock_skew_tolerance = clock_skew_tolerance;
306 self
307 }
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize, Default)]
311pub struct RemoveOptions {
313 pub recursive: bool,
314 pub ignore_not_found: bool,
315}
316
317impl RemoveOptions {
318 pub fn with_recursive(mut self, recursive: bool) -> Self {
323 self.recursive = recursive;
324 self
325 }
326
327 pub fn with_ignore_not_found(mut self, ignore_not_found: bool) -> Self {
332 self.ignore_not_found = ignore_not_found;
333 self
334 }
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct ListOptions {
340 pub recursive: bool,
341 pub include_hidden: bool,
342 pub files_only: bool,
343 pub directories_only: bool,
344 pub pattern: Option<String>,
345 pub limit: usize,
346 pub sort_by: SortBy,
347}
348
349impl Default for ListOptions {
350 fn default() -> Self {
351 ListOptions {
352 recursive: false,
353 include_hidden: false,
354 files_only: false,
355 directories_only: false,
356 pattern: None,
357 limit: 0,
358 sort_by: SortBy::Name,
359 }
360 }
361}
362
363impl ListOptions {
364 pub fn with_recursive(mut self, recursive: bool) -> Self {
369 self.recursive = recursive;
370 self
371 }
372
373 pub fn with_include_hidden(mut self, include_hidden: bool) -> Self {
378 self.include_hidden = include_hidden;
379 self
380 }
381
382 pub fn with_files_only(mut self, files_only: bool) -> Self {
387 self.files_only = files_only;
388 self
389 }
390
391 pub fn with_directories_only(mut self, directories_only: bool) -> Self {
396 self.directories_only = directories_only;
397 self
398 }
399
400 pub fn with_pattern(mut self, pattern: Option<String>) -> Self {
405 self.pattern = pattern;
406 self
407 }
408
409 pub fn with_limit(mut self, limit: usize) -> Self {
414 self.limit = limit;
415 self
416 }
417
418 pub fn with_sort_by(mut self, sort_by: SortBy) -> Self {
423 self.sort_by = sort_by;
424 self
425 }
426}