1use std::ffi::OsString;
2use std::fs;
3
4#[derive(Debug, Clone)]
5pub struct FileEntry {
6 name: OsString,
7 name_str: String,
8 lowercase_name: String,
9 display_name: String,
10 is_dir: bool,
11 is_hidden: bool,
12 is_system: bool,
13}
14
15impl FileEntry {
16 pub fn name(&self) -> &OsString {
18 &self.name
19 }
20
21 pub fn name_str(&self) -> &str {
22 &self.name_str
23 }
24
25 pub fn lowercase_name(&self) -> &str {
26 &self.lowercase_name
27 }
28
29 pub fn display_name(&self) -> &str {
30 &self.display_name
31 }
32
33 pub fn is_dir(&self) -> bool {
34 self.is_dir
35 }
36
37 pub fn is_hidden(&self) -> bool {
38 self.is_hidden
39 }
40
41 pub fn is_system(&self) -> bool {
42 self.is_system
43 }
44
45 pub fn set_display_name(&mut self, new_name: String) {
47 self.display_name = new_name;
48 }
49}
50
51pub fn browse_dir(path: &std::path::Path) -> std::io::Result<Vec<FileEntry>> {
52 let mut entries = Vec::with_capacity(256);
53 for entry in fs::read_dir(path)? {
54 let entry = match entry {
55 Ok(e) => e,
56 Err(_) => continue,
57 };
58
59 let name = entry.file_name();
60 let name_lossy = name.to_string_lossy();
61 let name_str = name_lossy.to_string();
62 let lowercase_name = name_lossy.to_lowercase();
63
64 let is_dir = entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false);
65
66 let display_name = if is_dir {
67 format!("{}/", name_lossy)
68 } else {
69 name_lossy.into_owned()
70 };
71
72 #[cfg(unix)]
73 let (is_hidden, is_system) = {
74 use std::os::unix::ffi::OsStrExt;
75 let is_hidden = name.as_bytes().first() == Some(&b'.');
77 (is_hidden, false)
78 };
79
80 #[cfg(windows)]
81 let (is_dir, is_hidden, is_system) = {
82 use std::os::windows::fs::MetadataExt;
83 let starts_with_dot = lowercase_name.starts_with('.');
84
85 if let Ok(md) = entry.metadata() {
86 let attrs = md.file_attributes();
87 (
88 md.is_dir(),
89 (attrs & 0x2 != 0) || starts_with_dot,
90 (attrs & 0x4 != 0),
91 )
92 } else {
93 (is_dir, starts_with_dot, false)
94 }
95 };
96
97 entries.push(FileEntry {
98 name,
99 name_str,
100 lowercase_name,
101 display_name,
102 is_dir,
103 is_hidden,
104 is_system,
105 });
106 }
107 Ok(entries)
108}