Skip to main content

yui_core/util/
data_dir.rs

1//! Runtime resolution of the user-data directory for yui.
2//!
3//! Lookup order:
4//!   1. `$YUI_DATA_DIR` if set.
5//!   2. Platform user-data dir via the `directories` crate
6//!      (e.g. `~/Library/Application Support/yui/` on macOS).
7//!
8//! Subdirectories under the data dir partition the data by kind, e.g.
9//! `<data_dir>/links/3_1.json`, `<data_dir>/braid/3_1.json`. The set of
10//! kinds is open — callers pass the subdirectory name they want.
11
12use std::path::PathBuf;
13
14use directories::ProjectDirs;
15
16pub const ENV_VAR: &str = "YUI_DATA_DIR";
17
18pub fn resolve_data_dir() -> Result<PathBuf, String> {
19    if let Some(dir) = std::env::var_os(ENV_VAR) {
20        return Ok(PathBuf::from(dir));
21    }
22    let proj = ProjectDirs::from("", "", "yui")
23        .ok_or_else(|| "no platform user-data directory available".to_string())?;
24    Ok(proj.data_dir().to_path_buf())
25}
26
27pub fn load_json(kind: &str, name: &str) -> Result<String, Box<dyn std::error::Error>> {
28    let dir = resolve_data_dir()?;
29    let path = dir.join(kind).join(format!("{name}.json"));
30    if !path.exists() {
31        return Err(format!(
32            "no `{kind}/{name}.json` under {}. \
33             Set ${ENV_VAR}, or run a script under `scripts/` to populate it.",
34            dir.display()
35        ).into());
36    }
37    Ok(std::fs::read_to_string(&path)?)
38}