use std::{
env,
ops::Add,
path::{Path, PathBuf},
};
pub fn get_app_data_dir(app_name: &str, roaming: bool) -> Option<PathBuf> {
let dir_data = DirData {
app_name,
os: env::consts::OS,
roaming,
};
dir_data.get_app_data_dir()
}
struct DirData<'a> {
os: &'a str,
app_name: &'a str,
roaming: bool,
}
impl<'a> DirData<'a> {
fn get_app_data_dir(mut self) -> Option<PathBuf> {
if self.app_name.is_empty() || self.app_name == "." {
return None;
}
if let Some(e) = self.app_name.strip_prefix('.') {
self.app_name = e;
}
match dirs::home_dir() {
Some(dir) => self.retrieve_from_os(&dir),
None => match env::var("HOME") {
Ok(val) => self.retrieve_from_os(Path::new(&val)),
_ => None,
},
}
}
fn retrieve_from_os(&self, home_dir: &Path) -> Option<PathBuf> {
let app_name_upper = self.app_name[..1]
.to_ascii_uppercase()
.add(&self.app_name[1..]);
let app_name_lower = self.app_name[..1]
.to_ascii_lowercase()
.add(&self.app_name[1..]);
match self.os {
"windows" => {
if let Ok(mut app_data) = env::var("LOCALAPPDATA") {
if app_data.is_empty() || self.roaming {
match env::var("APPDATA") {
Ok(val) => {
app_data = val;
}
_ => return None,
}
}
return Some(Path::new(&app_data).join(app_name_upper));
};
}
"macos" => {
if !home_dir.as_os_str().is_empty() {
let joined_paths = Path::new(&home_dir)
.join("Library")
.join("Application Support")
.join(app_name_upper);
return Some(joined_paths);
}
}
"plan9" => {
if !home_dir.as_os_str().is_empty() {
return None;
}
return Some(Path::new(&home_dir).join(app_name_lower));
}
_ => {
if home_dir.as_os_str().is_empty() {
return None;
}
let mut dotted_path = String::from(".");
dotted_path.push_str(app_name_lower.as_str());
return Some(Path::new(&home_dir).join(dotted_path));
}
}
None
}
}