use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use crate::TokuError;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(default)]
pub struct TokuConfig {
pub default_format: String,
pub color: String,
pub metadata_source: String,
}
impl Default for TokuConfig {
fn default() -> Self {
Self {
default_format: "table".to_string(),
color: "auto".to_string(),
metadata_source: "openlibrary".to_string(),
}
}
}
const CONFIG_FILENAME: &str = "config.toml";
impl TokuConfig {
pub fn config_path(data_dir: &Path) -> PathBuf {
data_dir.join(CONFIG_FILENAME)
}
pub fn load(data_dir: &Path) -> Result<Self, TokuError> {
let path = Self::config_path(data_dir);
if !path.exists() {
return Ok(Self::default());
}
let contents =
std::fs::read_to_string(&path).map_err(|e| TokuError::Config(e.to_string()))?;
let config: TokuConfig =
toml::from_str(&contents).map_err(|e| TokuError::Config(e.to_string()))?;
Ok(config)
}
pub fn save(&self, data_dir: &Path) -> Result<(), TokuError> {
std::fs::create_dir_all(data_dir).map_err(|e| TokuError::Config(e.to_string()))?;
let contents =
toml::to_string_pretty(self).map_err(|e| TokuError::Config(e.to_string()))?;
let path = Self::config_path(data_dir);
std::fs::write(&path, contents).map_err(|e| TokuError::Config(e.to_string()))?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_has_sensible_values() {
let cfg = TokuConfig::default();
assert_eq!(cfg.default_format, "table");
assert_eq!(cfg.color, "auto");
assert_eq!(cfg.metadata_source, "openlibrary");
}
#[test]
fn load_missing_file_returns_defaults() {
let dir = std::env::temp_dir().join("toku-test-config-missing");
let _ = std::fs::remove_file(TokuConfig::config_path(&dir));
let cfg = TokuConfig::load(&dir).expect("load should succeed");
assert_eq!(cfg, TokuConfig::default());
}
#[test]
fn save_and_load_roundtrip() {
let dir = std::env::temp_dir().join("toku-test-config-roundtrip");
let _ = std::fs::remove_dir_all(&dir);
let cfg = TokuConfig {
default_format: "json".to_string(),
color: "never".to_string(),
metadata_source: "google".to_string(),
};
cfg.save(&dir).expect("save should succeed");
let loaded = TokuConfig::load(&dir).expect("load should succeed");
assert_eq!(loaded, cfg);
let _ = std::fs::remove_dir_all(&dir);
}
}