wordchipper_disk_cache/
path_resolver.rs1use std::{
6 env,
7 path::{Path, PathBuf},
8};
9
10use directories_next::ProjectDirs;
11
12pub struct PathResolver {
14 pub qualifier: &'static str,
16
17 pub organization: &'static str,
19
20 pub application: &'static str,
22
23 pub cache_env_vars: &'static [&'static str],
25
26 pub data_env_vars: &'static [&'static str],
28}
29
30impl PathResolver {
31 pub fn project_dirs(&self) -> Option<ProjectDirs> {
33 ProjectDirs::from(self.organization, self.application, self.qualifier)
34 }
35
36 pub fn resolve_cache_dir<P: AsRef<Path>>(
52 &self,
53 path: Option<P>,
54 ) -> Option<PathBuf> {
55 if let Some(path) = path.as_ref() {
56 return Some(path.as_ref().to_path_buf());
57 }
58
59 for env_var in self.cache_env_vars {
60 if let Ok(path) = env::var(env_var) {
61 return Some(PathBuf::from(path));
62 }
63 }
64
65 if let Some(pds) = self.project_dirs() {
66 return Some(pds.cache_dir().to_path_buf());
67 }
68
69 None
70 }
71
72 pub fn resolve_data_dir<P: AsRef<Path>>(
88 &self,
89 path: Option<P>,
90 ) -> Option<PathBuf> {
91 if let Some(path) = path.as_ref() {
92 return Some(path.as_ref().to_path_buf());
93 }
94
95 for env_var in self.data_env_vars {
96 if let Ok(path) = env::var(env_var) {
97 return Some(PathBuf::from(path));
98 }
99 }
100
101 if let Some(pds) = self.project_dirs() {
102 return Some(pds.data_dir().to_path_buf());
103 }
104
105 None
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use serial_test::serial;
112
113 use super::*;
114
115 const CACHE_ENV1: &str = "_APP_PATH_CACHE_ENV1";
116 const CACHE_ENV2: &str = "_APP_PATH_CACHE_ENV2";
117 const DATA_ENV1: &str = "_APP_PATH_DATA_ENV1";
118 const DATA_ENV2: &str = "_APP_PATH_DATA_ENV2";
119
120 const TEST_CONFIG: PathResolver = PathResolver {
121 qualifier: "io",
122 organization: "crates",
123 application: "example",
124 cache_env_vars: &[CACHE_ENV1, CACHE_ENV2],
125 data_env_vars: &[DATA_ENV1, DATA_ENV2],
126 };
127
128 #[test]
129 #[serial]
130 fn test_resolve_dirs() {
131 let pds = TEST_CONFIG
132 .project_dirs()
133 .expect("failed to get project dirs");
134
135 let no_path: Option<PathBuf> = None;
136
137 let user_cache_dir = PathBuf::from("/tmp/app_cache/cache");
138 let user_data_dir = PathBuf::from("/tmp/app_cache/data");
139
140 let env_cache_dir1 = PathBuf::from("/tmp/app_cache/env_cache.1");
141 let env_cache_dir2 = PathBuf::from("/tmp/app_cache/env_cache.2");
142 let env_data_dir1 = PathBuf::from("/tmp/app_cache/env_data.1");
143 let env_data_dir2 = PathBuf::from("/tmp/app_cache/env_data.2");
144
145 unsafe {
147 for v in TEST_CONFIG.cache_env_vars {
148 env::remove_var(v);
149 }
150 for v in TEST_CONFIG.data_env_vars {
151 env::remove_var(v);
152 }
153 }
154
155 assert_eq!(
157 TEST_CONFIG.resolve_cache_dir(Some(user_cache_dir.clone())),
158 Some(user_cache_dir.clone()),
159 );
160 assert_eq!(
161 TEST_CONFIG.resolve_data_dir(Some(user_data_dir.clone())),
162 Some(user_data_dir.clone()),
163 );
164
165 assert_eq!(
167 TEST_CONFIG.resolve_cache_dir(no_path.clone()),
168 Some(pds.cache_dir().to_path_buf())
169 );
170 assert_eq!(
171 TEST_CONFIG.resolve_data_dir(no_path.clone()),
172 Some(pds.data_dir().to_path_buf())
173 );
174
175 unsafe {
177 env::set_var(CACHE_ENV2, env_cache_dir2.to_str().unwrap());
178 env::set_var(DATA_ENV2, env_data_dir2.to_str().unwrap());
179 }
180
181 assert_eq!(
183 TEST_CONFIG.resolve_cache_dir(Some(user_cache_dir.clone())),
184 Some(user_cache_dir.clone()),
185 );
186 assert_eq!(
187 TEST_CONFIG.resolve_data_dir(Some(user_data_dir.clone())),
188 Some(user_data_dir.clone()),
189 );
190
191 assert_eq!(
193 TEST_CONFIG.resolve_cache_dir(no_path.clone()),
194 Some(env_cache_dir2.clone())
195 );
196 assert_eq!(
197 TEST_CONFIG.resolve_data_dir(no_path.clone()),
198 Some(env_data_dir2.clone())
199 );
200
201 unsafe {
203 env::set_var(CACHE_ENV1, env_cache_dir1.to_str().unwrap());
204 env::set_var(DATA_ENV1, env_data_dir1.to_str().unwrap());
205 }
206
207 assert_eq!(
209 TEST_CONFIG.resolve_cache_dir(Some(user_cache_dir.clone())),
210 Some(user_cache_dir.clone()),
211 );
212 assert_eq!(
213 TEST_CONFIG.resolve_data_dir(Some(user_data_dir.clone())),
214 Some(user_data_dir.clone()),
215 );
216
217 assert_eq!(
219 TEST_CONFIG.resolve_cache_dir(no_path.clone()),
220 Some(env_cache_dir1.clone())
221 );
222 assert_eq!(
223 TEST_CONFIG.resolve_data_dir(no_path.clone()),
224 Some(env_data_dir1.clone())
225 );
226 }
227}