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