use std::path::PathBuf;
use anyhow::{bail, Context, Result};
pub const DEFAULT_LOCAL_ID: &str = "default";
pub fn of(local_id: &str) -> Result<PathBuf> {
if local_id.is_empty() || local_id == "." || local_id == ".." || local_id.contains(['/', '\\'])
{
bail!("a device's local id is one path component, not {local_id:?}");
}
Ok(dirs::data_local_dir()
.context(
"this platform has no per-user data directory: set DEVICE_DIR, or name the \
device directory explicitly",
)?
.join("semio")
.join("arora")
.join("devices")
.join(local_id))
}
pub(crate) fn override_from_env() -> Option<PathBuf> {
env_nonempty("DEVICE_DIR").map(PathBuf::from)
}
pub(crate) fn local_id_from_env() -> String {
env_nonempty("DEVICE_LOCAL_ID").unwrap_or_else(|| DEFAULT_LOCAL_ID.to_string())
}
fn env_nonempty(key: &str) -> Option<String> {
std::env::var(key)
.ok()
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_local_id_names_one_directory_under_devices() {
let dir = of("bench-2").unwrap();
assert!(
dir.ends_with("semio/arora/devices/bench-2"),
"{}",
dir.display()
);
}
#[test]
fn a_local_id_is_one_path_component() {
for bad in ["", ".", "..", "a/b", "a\\b"] {
assert!(of(bad).is_err(), "{bad:?} is refused");
}
}
}