1mod dir_comparer;
2mod file_comparer;
3mod file_hash_cache;
4mod file_hasher;
5mod file_iterator;
6mod progress_reporter;
7
8pub use dir_comparer::{DirectoryComparer, FileComparisonMethod};
9pub use file_comparer::{Classification, FileComparer, FileComparisonResult};
10pub(crate) use file_hash_cache::FileHashCache;
11pub use file_hasher::{DuplicatedFiles, FileHasher};
12pub(crate) use file_iterator::FileIterator;
13pub(crate) use progress_reporter::ProgressReporter;
14
15use std::path::{Path, StripPrefixError};
16
17pub(crate) fn human_readable_size(size: u64) -> String {
18 const MB: u64 = 1024 * 1024;
19 const GB: u64 = 1024 * 1024 * 1024;
20 if size >= GB {
21 format!("{:.1}GB", size as f64 / GB as f64)
22 } else if size >= MB {
23 format!("{:.1}MB", size as f64 / MB as f64)
24 } else {
25 format!("{} bytes", size)
26 }
27}
28
29pub(crate) fn strip_prefix<'a>(path: &'a Path, base: &Path) -> Result<&'a Path, StripPrefixError> {
31 let result = path.strip_prefix(base);
32 #[cfg(windows)]
33 if let Ok(result_path) = result {
34 let result_os_str = result_path.as_os_str();
35 let result_bytes = result_os_str.as_encoded_bytes();
36 if !result_bytes.is_empty() && result_bytes[0] as char == std::path::MAIN_SEPARATOR {
37 return Ok(Path::new(unsafe {
40 use std::ffi::OsStr;
41 OsStr::from_encoded_bytes_unchecked(&result_bytes[1..])
42 }));
43 }
44 }
45 result
46}
47
48#[cfg(test)]
49mod tests {
50 #[cfg(windows)]
51 use super::*;
52
53 #[cfg(windows)]
54 #[test]
55 fn test_strip_prefix_share_root() -> anyhow::Result<()> {
56 let path = Path::new(r"\\server\share\dir1\dir2");
57 let base = Path::new(r"\\server\share");
58 assert_eq!(strip_prefix(path, base)?.to_str().unwrap(), r"dir1\dir2");
59 assert_eq!(path.strip_prefix(base)?.to_str().unwrap(), r"dir1\dir2");
60 Ok(())
61 }
62
63 #[cfg(windows)]
64 #[test]
65 fn test_strip_prefix_unc_root() -> anyhow::Result<()> {
66 let path = Path::new(r"\\?\UNC\server\share\dir1\dir2");
67 let base = Path::new(r"\\?\UNC\server\share");
68 assert_eq!(strip_prefix(path, base)?.to_str().unwrap(), r"dir1\dir2");
69 Ok(())
71 }
72}