1use std::ffi::OsStr;
2use std::path::Path;
3
4use crate::walk::DirEntry;
5
6#[cfg(unix)]
12pub fn is_hidden(dent: &DirEntry) -> bool {
13 use std::os::unix::ffi::OsStrExt;
14
15 if let Some(name) = file_name(dent.path()) {
16 name.as_bytes().get(0) == Some(&b'.')
17 } else {
18 false
19 }
20}
21
22#[cfg(windows)]
29pub fn is_hidden(dent: &DirEntry) -> bool {
30 use std::os::windows::fs::MetadataExt;
31 use winapi_util::file;
32
33 if let Ok(md) = dent.metadata() {
37 if file::is_hidden(md.file_attributes() as u64) {
38 return true;
39 }
40 }
41 if let Some(name) = file_name(dent.path()) {
42 name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
43 } else {
44 false
45 }
46}
47
48#[cfg(not(any(unix, windows)))]
52pub fn is_hidden(dent: &DirEntry) -> bool {
53 if let Some(name) = file_name(dent.path()) {
54 name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
55 } else {
56 false
57 }
58}
59
60#[cfg(unix)]
64pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
65 prefix: &'a P,
66 path: &'a Path,
67) -> Option<&'a Path> {
68 use std::os::unix::ffi::OsStrExt;
69
70 let prefix = prefix.as_ref().as_os_str().as_bytes();
71 let path = path.as_os_str().as_bytes();
72 if prefix.len() > path.len() || prefix != &path[0..prefix.len()] {
73 None
74 } else {
75 Some(&Path::new(OsStr::from_bytes(&path[prefix.len()..])))
76 }
77}
78
79#[cfg(not(unix))]
83pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
84 prefix: &'a P,
85 path: &'a Path,
86) -> Option<&'a Path> {
87 path.strip_prefix(prefix).ok()
88}
89
90#[cfg(unix)]
93pub fn is_file_name<P: AsRef<Path>>(path: P) -> bool {
94 use memchr::memchr;
95 use std::os::unix::ffi::OsStrExt;
96
97 let path = path.as_ref().as_os_str().as_bytes();
98 memchr(b'/', path).is_none()
99}
100
101#[cfg(not(unix))]
104pub fn is_file_name<P: AsRef<Path>>(path: P) -> bool {
105 path.as_ref().parent().map(|p| p.as_os_str().is_empty()).unwrap_or(false)
106}
107
108#[cfg(unix)]
113pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
114 path: &'a P,
115) -> Option<&'a OsStr> {
116 use memchr::memrchr;
117 use std::os::unix::ffi::OsStrExt;
118
119 let path = path.as_ref().as_os_str().as_bytes();
120 if path.is_empty() {
121 return None;
122 } else if path.len() == 1 && path[0] == b'.' {
123 return None;
124 } else if path.last() == Some(&b'.') {
125 return None;
126 } else if path.len() >= 2 && &path[path.len() - 2..] == &b".."[..] {
127 return None;
128 }
129 let last_slash = memrchr(b'/', path).map(|i| i + 1).unwrap_or(0);
130 Some(OsStr::from_bytes(&path[last_slash..]))
131}
132
133#[cfg(not(unix))]
138pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
139 path: &'a P,
140) -> Option<&'a OsStr> {
141 path.as_ref().file_name()
142}