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
use std::fmt;
use std::path::PathBuf;
use std::sync::Arc;
use reqwest::header::HeaderMap;
use reqwest::Method;
use crate::direction::Direction;
use crate::http_breakpoint::{BreakpointDownload, BreakpointDownloadHttpConfig, BreakpointUpload};
/// User-facing task input built by upload/download builders.
///
/// This type only carries request parameters. Internal runtime state is created
/// later when the task is enqueued.
#[derive(Clone)]
pub struct PounceTask {
/// Transfer direction.
pub(crate) direction: Direction,
/// Display file name.
pub(crate) file_name: String,
/// Local source/target path.
pub(crate) file_path: PathBuf,
/// Total file size in bytes (upload only at build time).
pub(crate) total_size: u64,
/// Chunk size in bytes.
pub(crate) chunk_size: u64,
/// Request URL.
pub(crate) url: String,
/// Request HTTP method.
pub(crate) method: Method,
/// Base request headers.
pub(crate) headers: HeaderMap,
/// Download-only signature shown in callbacks.
///
/// Upload tasks ignore this value and use internal signature generation.
pub(crate) client_file_sign: Option<String>,
/// Optional custom upload breakpoint protocol.
pub(crate) breakpoint_upload: Option<Arc<dyn BreakpointUpload + Send + Sync>>,
/// Optional custom download breakpoint protocol.
pub(crate) breakpoint_download: Option<Arc<dyn BreakpointDownload + Send + Sync>>,
/// Optional HTTP configuration for breakpoint download.
pub(crate) breakpoint_download_http: Option<BreakpointDownloadHttpConfig>,
/// Maximum retry count per chunk transfer.
///
/// Applies only to chunk transfer stage, not prepare stage.
pub(crate) max_chunk_retries: u32,
}
impl fmt::Debug for PounceTask {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PounceTask")
.field("direction", &self.direction)
.field("file_name", &self.file_name)
.field("file_path", &self.file_path)
.field("total_size", &self.total_size)
.field("chunk_size", &self.chunk_size)
.field("url", &self.url)
.field("method", &self.method)
.field("headers", &self.headers)
.field("client_file_sign", &self.client_file_sign)
.field(
"breakpoint_upload",
&self
.breakpoint_upload
.as_ref()
.map(|_| "Arc<dyn BreakpointUpload + Send + Sync>"),
)
.field(
"breakpoint_download",
&self
.breakpoint_download
.as_ref()
.map(|_| "Arc<dyn BreakpointDownload + Send + Sync>"),
)
.field("breakpoint_download_http", &self.breakpoint_download_http)
.field("max_chunk_retries", &self.max_chunk_retries)
.finish()
}
}
impl PounceTask {
/// Default maximum retry count per chunk transfer.
pub const DEFAULT_MAX_CHUNK_RETRIES: u32 = 3;
/// Normalizes chunk size input.
///
/// `0` is converted to `1 MiB`; other values are kept unchanged.
pub(crate) fn normalized_chunk_size(chunk_size: u64) -> u64 {
if chunk_size == 0 {
1024 * 1024
} else {
chunk_size
}
}
/// Normalizes retry count input.
///
/// - `0` means "disable retry".
/// - Other values are used as-is.
pub(crate) fn normalized_max_chunk_retries(max_chunk_retries: u32) -> u32 {
max_chunk_retries
}
/// Checks whether required task fields are missing/invalid.
///
/// For upload, `total_size` must be greater than `0`.
pub(crate) fn is_empty(&self) -> bool {
self.file_path.as_os_str().is_empty()
|| self.file_name.is_empty()
|| self.url.is_empty()
|| match self.direction {
Direction::Upload => self.total_size == 0,
Direction::Download => false,
}
}
}