1#[derive(Debug, Clone, Default)]
5pub struct FileTransferOptions {
6 hold_timestamp: bool,
8 sync_mode: bool,
10 compress: bool,
13 mode_sync: bool,
15 debug_dir: bool,
17}
18
19impl FileTransferOptions {
20 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn hold_timestamp(mut self, enable: bool) -> Self {
27 self.hold_timestamp = enable;
28 self
29 }
30
31 pub fn sync_mode(mut self, enable: bool) -> Self {
33 self.sync_mode = enable;
34 self
35 }
36
37 pub fn compress(mut self, enable: bool) -> Self {
39 self.compress = enable;
40 self
41 }
42
43 pub fn mode_sync(mut self, enable: bool) -> Self {
45 self.mode_sync = enable;
46 self
47 }
48
49 pub fn debug_dir(mut self, enable: bool) -> Self {
51 self.debug_dir = enable;
52 self
53 }
54
55 pub(crate) fn to_flags(&self) -> String {
57 let mut flags = Vec::new();
58
59 if self.hold_timestamp {
60 flags.push("-a");
61 }
62 if self.sync_mode {
63 flags.push("-sync");
64 }
65 if self.compress {
66 flags.push("-z");
67 }
68 if self.mode_sync {
69 flags.push("-m");
70 }
71 if self.debug_dir {
72 flags.push("-b");
73 }
74
75 flags.join(" ")
76 }
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81pub enum FileTransferDirection {
82 Send,
84 Recv,
86}
87
88pub(crate) fn validate_path(path: &str) -> bool {
90 !path.is_empty() && !path.contains('\0')
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_file_options_flags() {
99 let opts = FileTransferOptions::new()
100 .hold_timestamp(true)
101 .compress(true);
102 assert_eq!(opts.to_flags(), "-a -z");
103
104 let opts = FileTransferOptions::new().sync_mode(true).mode_sync(true);
105 assert_eq!(opts.to_flags(), "-sync -m");
106 }
107
108 #[test]
109 fn test_validate_path() {
110 assert!(validate_path("/data/local/tmp/test.txt"));
111 assert!(validate_path("test.txt"));
112 assert!(!validate_path(""));
113 assert!(!validate_path("test\0file"));
114 }
115}