lunar-lib 0.11.0

Common utilities for lunar applications
Documentation
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(())
}

/// Returns the applications config directory based on the initialized `fs_name`
///
/// For example, on unix, if you initialized using `app_name`, this would return `$XDG_CONFIG_HOME/app_name/`
#[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())
    }
}

/// Returns the applications config directory based on the initialized `fs_name()`
///
/// For example, on unix, if you initialized using `app_name`, this would return `$XDG_CONFIG_HOME/app_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())
}