project_dirs/
dir_utils.rs1use std::path::{Path, PathBuf};
2
3use crate::{FullProjectDirs, ProjectDirs};
4
5pub trait Filter {
7 fn filter_existing_dirs(&self) -> ProjectDirs;
9
10 fn filter_non_dirs(&self) -> ProjectDirs;
13
14 fn filter_absent(&self) -> ProjectDirs;
17
18 fn filter_denied(&self) -> ProjectDirs;
21
22 fn filter_non_valid(&self) -> ProjectDirs;
24}
25
26impl Filter for ProjectDirs {
27 fn filter_existing_dirs(&self) -> ProjectDirs {
28 ProjectDirs::new(
29 self.0
30 .iter()
31 .filter(|(_, p)| p.is_dir())
32 .map(|x| (*x.0, x.1.clone()))
33 .collect(),
34 )
35 }
36
37 fn filter_non_dirs(&self) -> ProjectDirs {
38 ProjectDirs::new(
39 self.0
40 .iter()
41 .filter(|(_, p)| p.exists() && !p.is_dir())
42 .map(|x| (*x.0, x.1.clone()))
43 .collect(),
44 )
45 }
46
47 fn filter_absent(&self) -> ProjectDirs {
48 ProjectDirs::new(
49 self.0
50 .iter()
51 .filter(|(_, p)| p.try_exists().map(|e| !e).unwrap_or(false))
52 .map(|x| (*x.0, x.1.clone()))
53 .collect(),
54 )
55 }
56
57 fn filter_denied(&self) -> ProjectDirs {
58 ProjectDirs::new(
59 self.0
60 .iter()
61 .filter(|(_, p)| p.try_exists().is_err())
62 .map(|x| (*x.0, x.1.clone()))
63 .collect(),
64 )
65 }
66
67 fn filter_non_valid(&self) -> ProjectDirs {
68 ProjectDirs::new(
69 self.0
70 .iter()
71 .filter(|(_, p)| !p.is_dir())
72 .map(|x| (*x.0, x.1.clone()))
73 .collect(),
74 )
75 }
76}
77
78pub trait Mounted {
80 fn mounted(self, mountpoint: &Path) -> Self;
81}
82
83fn strip_root_prefix(p: PathBuf) -> PathBuf {
84 if p.starts_with("/") {
85 p.strip_prefix("/")
86 .expect("Failed to strip / prefix from paths. This is a bug")
87 .to_path_buf()
88 } else {
89 p
90 }
91}
92
93impl Mounted for PathBuf {
94 fn mounted(self, mountpoint: &Path) -> Self {
95 mountpoint.join(strip_root_prefix(self.to_path_buf()))
96 }
97}
98
99impl Mounted for ProjectDirs {
100 fn mounted(self, mountpoint: &Path) -> Self {
101 ProjectDirs::new(
102 self.0
103 .into_iter()
104 .map(|(d, p)| (d, mountpoint.join(strip_root_prefix(p))))
105 .collect(),
106 )
107 }
108}
109
110impl Mounted for FullProjectDirs {
111 fn mounted(self, mountpoint: &Path) -> Self {
112 let pd: ProjectDirs = self.into();
113 pd.mounted(mountpoint).try_into().unwrap()
114 }
115}
116
117pub fn home_dir() -> Option<PathBuf> {
119 #[cfg(feature = "nonstd_home_dir")]
120 return home::home_dir();
121
122 #[cfg(not(feature = "nonstd_home_dir"))]
123 return std::env::home_dir();
124}