photoncloud-monorepo/crates/photon-config/src/lib.rs

58 lines
1.6 KiB
Rust

use anyhow::Context;
use serde::de::DeserializeOwned;
use std::fs;
use std::path::Path;
pub fn load_toml_config<T>(path: &Path) -> anyhow::Result<T>
where
T: DeserializeOwned + Default,
{
if !path.exists() {
return Ok(T::default());
}
let contents = fs::read_to_string(path)
.with_context(|| format!("failed to read config file {}", path.display()))?;
toml::from_str(&contents)
.with_context(|| format!("failed to parse config file {}", path.display()))
}
#[cfg(test)]
mod tests {
use super::load_toml_config;
use serde::Deserialize;
use std::fs;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Default, Deserialize, PartialEq)]
struct TestConfig {
value: String,
}
fn temp_path(name: &str) -> PathBuf {
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
std::env::temp_dir().join(format!("{}-{}-{}.toml", name, std::process::id(), nanos))
}
#[test]
fn returns_default_when_file_is_missing() {
let path = temp_path("photon-config-missing");
let config: TestConfig = load_toml_config(&path).unwrap();
assert_eq!(config, TestConfig::default());
}
#[test]
fn loads_existing_toml_file() {
let path = temp_path("photon-config-load");
fs::write(&path, "value = \"hello\"\n").unwrap();
let config: TestConfig = load_toml_config(&path).unwrap();
assert_eq!(config.value, "hello");
let _ = fs::remove_file(path);
}
}