Skip to main content

soar_dl/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// Download progress events
4#[derive(Debug, Clone, Copy)]
5pub enum Progress {
6    Starting { total: u64 },
7    Resuming { current: u64, total: u64 },
8    Chunk { current: u64, total: u64 },
9    Complete { total: u64 },
10    Error,
11    Aborted,
12    Recovered,
13}
14
15/// How to handle existing files
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum OverwriteMode {
18    Skip,
19    Force,
20    Prompt,
21}
22
23/// Resume information stored in xattrs
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ResumeInfo {
26    pub downloaded: u64,
27    pub total: u64,
28    pub etag: Option<String>,
29    pub last_modified: Option<String>,
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    fn test_progress_starting() {
38        let progress = Progress::Starting {
39            total: 1024,
40        };
41        match progress {
42            Progress::Starting {
43                total,
44            } => assert_eq!(total, 1024),
45            _ => panic!("Expected Progress::Starting"),
46        }
47    }
48
49    #[test]
50    fn test_progress_chunk() {
51        let progress = Progress::Chunk {
52            current: 512,
53            total: 1024,
54        };
55        match progress {
56            Progress::Chunk {
57                current,
58                total,
59            } => {
60                assert_eq!(current, 512);
61                assert_eq!(total, 1024);
62            }
63            _ => panic!("Expected Progress::Chunk"),
64        }
65    }
66
67    #[test]
68    fn test_progress_complete() {
69        let progress = Progress::Complete {
70            total: 1024,
71        };
72        match progress {
73            Progress::Complete {
74                total,
75            } => assert_eq!(total, 1024),
76            _ => panic!("Expected Progress::Complete"),
77        }
78    }
79
80    #[test]
81    fn test_progress_clone() {
82        let p1 = Progress::Starting {
83            total: 100,
84        };
85        let p2 = p1;
86        match (p1, p2) {
87            (
88                Progress::Starting {
89                    total: t1,
90                },
91                Progress::Starting {
92                    total: t2,
93                },
94            ) => {
95                assert_eq!(t1, t2);
96            }
97            _ => panic!("Clone failed"),
98        }
99    }
100
101    #[test]
102    fn test_overwrite_mode_equality() {
103        assert_eq!(OverwriteMode::Skip, OverwriteMode::Skip);
104        assert_eq!(OverwriteMode::Force, OverwriteMode::Force);
105        assert_eq!(OverwriteMode::Prompt, OverwriteMode::Prompt);
106
107        assert_ne!(OverwriteMode::Skip, OverwriteMode::Force);
108        assert_ne!(OverwriteMode::Force, OverwriteMode::Prompt);
109        assert_ne!(OverwriteMode::Skip, OverwriteMode::Prompt);
110    }
111
112    #[test]
113    fn test_overwrite_mode_clone() {
114        let mode1 = OverwriteMode::Force;
115        let mode2 = mode1;
116        assert_eq!(mode1, mode2);
117    }
118
119    #[test]
120    fn test_resume_info_with_etag() {
121        let info = ResumeInfo {
122            downloaded: 512,
123            total: 1024,
124            etag: Some("\"abc123\"".to_string()),
125            last_modified: None,
126        };
127
128        assert_eq!(info.downloaded, 512);
129        assert_eq!(info.total, 1024);
130        assert_eq!(info.etag, Some("\"abc123\"".to_string()));
131        assert_eq!(info.last_modified, None);
132    }
133
134    #[test]
135    fn test_resume_info_with_last_modified() {
136        let info = ResumeInfo {
137            downloaded: 256,
138            total: 1024,
139            etag: None,
140            last_modified: Some("Wed, 21 Oct 2015 07:28:00 GMT".to_string()),
141        };
142
143        assert_eq!(info.downloaded, 256);
144        assert_eq!(
145            info.last_modified,
146            Some("Wed, 21 Oct 2015 07:28:00 GMT".to_string())
147        );
148    }
149
150    #[test]
151    fn test_resume_info_serialize_deserialize() {
152        let info = ResumeInfo {
153            downloaded: 1024,
154            total: 2048,
155            etag: Some("etag-value".to_string()),
156            last_modified: Some("date".to_string()),
157        };
158
159        let json = serde_json::to_string(&info).unwrap();
160        let deserialized: ResumeInfo = serde_json::from_str(&json).unwrap();
161
162        assert_eq!(deserialized.downloaded, info.downloaded);
163        assert_eq!(deserialized.total, info.total);
164        assert_eq!(deserialized.etag, info.etag);
165        assert_eq!(deserialized.last_modified, info.last_modified);
166    }
167
168    #[test]
169    fn test_resume_info_clone() {
170        let info1 = ResumeInfo {
171            downloaded: 100,
172            total: 200,
173            etag: Some("tag".to_string()),
174            last_modified: None,
175        };
176
177        let info2 = info1.clone();
178        assert_eq!(info1.downloaded, info2.downloaded);
179        assert_eq!(info1.total, info2.total);
180        assert_eq!(info1.etag, info2.etag);
181    }
182}