Skip to main content

steeldb/
paths.rs

1//! Location-independent model resolution. An installed `steeldb` binary must find its bundled models
2//! whatever the working directory is — so we search, in priority order: an explicit env override, the
3//! per-user cache (`~/.steeldb/models`, `%LOCALAPPDATA%\steeldb\models`), next-to-the-executable
4//! (`<exe>/models`, and `<exe>/../../models` for the dev `target/<profile>/` layout), then `./models`.
5
6use std::path::PathBuf;
7
8/// Candidate `models/` roots, most-preferred first.
9pub fn model_roots() -> Vec<PathBuf> {
10    let mut roots = Vec::new();
11    if let Ok(r) = std::env::var("STEELDB_MODELS") {
12        roots.push(PathBuf::from(r));
13    }
14    if let Ok(home) = std::env::var("HOME") {
15        roots.push(PathBuf::from(home).join(".steeldb/models"));
16    }
17    if let Ok(la) = std::env::var("LOCALAPPDATA") {
18        roots.push(PathBuf::from(la).join("steeldb").join("models"));
19    }
20    if let Ok(exe) = std::env::current_exe() {
21        if let Some(dir) = exe.parent() {
22            roots.push(dir.join("models")); // installed: models next to the binary
23            roots.push(dir.join("..").join("..").join("models")); // dev: target/<profile>/ → repo/models
24        }
25    }
26    roots.push(PathBuf::from("models")); // CWD fallback (running from repo root)
27    roots
28}
29
30/// Resolve a model sub-directory. An explicit `env_var` wins (if it points at a dir containing
31/// `marker`); otherwise the first `<root>/<name>` that contains `marker`. `marker` is a file that must
32/// exist so we don't return an empty/partial dir.
33pub fn model_dir(name: &str, env_var: &str, marker: &str) -> Option<PathBuf> {
34    if let Ok(p) = std::env::var(env_var) {
35        let p = PathBuf::from(p);
36        if p.join(marker).exists() {
37            return Some(p);
38        }
39    }
40    model_roots().into_iter().map(|r| r.join(name)).find(|d| d.join(marker).exists())
41}