use std::{
path::PathBuf,
sync::{Mutex, OnceLock},
};
use directories::{BaseDirs, UserDirs};
static DIRS: OnceLock<(&'static str, BaseDirs, UserDirs)> = OnceLock::new();
static DIRS_LOCK: Mutex<()> = Mutex::new(());
fn fs_name() -> &'static str {
DIRS.get().unwrap().0
}
pub fn base_dirs() -> &'static BaseDirs {
&DIRS.get().unwrap().1
}
pub fn user_dirs() -> &'static UserDirs {
&DIRS.get().unwrap().2
}
pub fn init_directories(fs_name: &'static str) -> Result<(), &'static str> {
DIRS.get().map_or(Ok(()), |(fs_name, ..)| Err(*fs_name))?;
let _lock = DIRS_LOCK.lock().unwrap();
DIRS.get().map_or(Ok(()), |(fs_name, ..)| Err(*fs_name))?;
let base_dirs = BaseDirs::new()
.expect("Users system is configured incorrectly. A home folder can not be identified");
let user_dirs = UserDirs::new().unwrap();
DIRS.set((fs_name, base_dirs, user_dirs)).unwrap();
Ok(())
}
#[must_use]
pub fn config_dir() -> PathBuf {
let base_dirs = base_dirs();
let config_dir = base_dirs.config_dir();
if config_dir == base_dirs.data_dir() {
data_dir().join("config")
} else {
config_dir.join(fs_name())
}
}
#[must_use]
pub fn data_dir() -> PathBuf {
let base_dirs = base_dirs();
base_dirs.data_dir().join(fs_name())
}
#[must_use]
pub fn state_dir() -> PathBuf {
let base_dirs = base_dirs();
base_dirs
.state_dir()
.map_or(data_dir().join("state"), |p| p.join(fs_name()))
}
#[must_use]
pub fn cache_dir() -> PathBuf {
let base_dirs = base_dirs();
base_dirs.cache_dir().join(fs_name())
}
#[must_use]
pub fn runtime_dir() -> PathBuf {
let base_dirs = base_dirs();
base_dirs
.runtime_dir()
.unwrap_or_else(|| base_dirs.cache_dir())
.join(fs_name())
}