assembly_pack/common/
fs.rs1use std::{
3 fs::{DirEntry, Metadata},
4 io,
5 path::Path,
6};
7
8pub struct FileInfo<'a> {
10 _path: &'a str,
11 _name: String,
12 _real: &'a Path,
13 _entry: DirEntry,
14}
15
16impl<'a> FileInfo<'a> {
17 pub fn name(&self) -> &str {
19 self._name.as_ref()
20 }
21
22 pub fn path(&self) -> String {
24 win_join(self._path, &self._name)
25 }
26
27 pub fn real(&self) -> &Path {
29 self._real
30 }
31
32 pub fn metadata(&self) -> io::Result<Metadata> {
34 self._entry.metadata()
35 }
36}
37
38fn win_join(base: &str, name: &str) -> String {
40 if base.is_empty() {
41 name.to_string()
42 } else if base.ends_with('\\') {
43 format!("{}{}", base, name)
44 } else {
45 format!("{}\\{}", base, name)
46 }
47}
48
49pub trait FsVisitor {
51 fn visit_file(&mut self, info: FileInfo);
53
54 #[allow(unused_variables)]
56 fn failed_read_dir(&mut self, real: &Path, e: io::Error) {
57 #[cfg(feature = "log")]
58 log::error!("Failed to read_dir {}: {}", real.display(), e);
59 }
60
61 #[allow(unused_variables)]
63 fn failed_next_dir_entry(&mut self, real: &Path, e: io::Error) {
64 #[cfg(feature = "log")]
65 log::error!("Failed next dir entry {}: {}", real.display(), e);
66 }
67}
68
69pub fn scan_dir<V: FsVisitor>(visitor: &mut V, path: String, real: &Path, recurse: bool) {
77 let rd = match std::fs::read_dir(real) {
78 Ok(rd) => rd,
79 Err(e) => {
80 visitor.failed_read_dir(real, e);
81 return;
82 }
83 };
84
85 for e in rd {
87 match e {
88 Ok(_entry) => {
89 let new_real_path = _entry.path();
90 let name = new_real_path
91 .file_name()
92 .expect("file_name on dir entry path")
93 .to_string_lossy()
94 .into_owned();
95 match _entry.file_type() {
96 Ok(t) => {
97 if t.is_file() {
98 visitor.visit_file(FileInfo {
99 _path: &path,
100 _name: name,
101 _real: &new_real_path,
102 _entry,
103 });
104 } else if t.is_dir() && recurse {
105 let new_path = win_join(&path, &name);
106 scan_dir(visitor, new_path, &new_real_path, recurse);
107 }
108 }
109 Err(e) => visitor.failed_next_dir_entry(&new_real_path, e),
110 }
111 }
112 Err(e) => {
113 visitor.failed_next_dir_entry(real, e);
114 return;
115 }
116 };
117 }
118}