slightly more graceful config reading: reads entry by entry

reads from default only if an entry is not present, and then writes those defaults to the file if anything was changed
This commit is contained in:
Llywelwyn 2023-08-24 22:59:25 +01:00
parent 6c727b056e
commit 73f511775e

View file

@ -7,6 +7,7 @@ mod load;
use rltk::prelude::*; use rltk::prelude::*;
use toml::de::Error as TomlError; use toml::de::Error as TomlError;
use toml::Value;
use serde::{ Serialize, Deserialize }; use serde::{ Serialize, Deserialize };
lazy_static! { lazy_static! {
@ -69,10 +70,25 @@ impl From<TomlError> for ReadError {
} }
impl Config { impl Config {
pub fn load_from_file(filename: &str) -> Result<Self, ReadError> { pub fn load_from_file(filename: &str) -> Config {
let contents = std::fs::read_to_string(filename).map_err(|e| ReadError::Io(e))?; if let Ok(contents) = std::fs::read_to_string(filename) {
let config: Config = toml::from_str(&contents).map_err(|e| ReadError::Toml(e))?; let parsed_config: Result<Value, _> = toml::from_str(&contents);
return Ok(config); if let Ok(parsed_config) = parsed_config {
let mut config = Config::default();
let mut requires_write = false;
requires_write |= config.logging.apply_values(&parsed_config);
requires_write |= config.visuals.apply_values(&parsed_config);
if requires_write {
if let Err(write_err) = config.save_to_file(filename) {
eprintln!("Error writing config: {:?}", write_err);
}
}
return config;
}
}
Config::default()
} }
pub fn save_to_file(&self, filename: &str) -> Result<(), Box<dyn std::error::Error>> { pub fn save_to_file(&self, filename: &str) -> Result<(), Box<dyn std::error::Error>> {
let toml_string = toml::to_string(self)?; let toml_string = toml::to_string(self)?;
@ -81,23 +97,51 @@ impl Config {
} }
} }
#[cfg(not(target_arch = "wasm32"))] macro_rules! apply_bool_value {
pub fn try_load_configuration() -> Config { ($config:expr, $parsed_config:expr, $changed:expr, $field:ident) => {
let config: Config = match Config::load_from_file("config.toml") { if let Some(value) = $parsed_config.get(stringify!($field)).and_then(|v| v.as_bool()) {
Ok(config) => { if $config.$field != value {
console::log(format!("Successfully loaded config: {:?}", config)); $config.$field = value;
config $changed = true;
}
Err(e) => {
console::log(format!("Error loading config: {:?}", e));
let config = Config::default();
if let Err(write_err) = config.save_to_file("config.toml") {
eprintln!("Error writing default config: {:?}", write_err);
} }
config
} }
}; };
}
trait Section {
fn apply_values(&mut self, parsed_config: &Value) -> bool;
}
impl Section for LogConfig {
fn apply_values(&mut self, parsed_config: &Value) -> bool {
if let Some(section) = parsed_config.get("logging") {
let mut missing = false;
apply_bool_value!(self, section, missing, log_spawning);
apply_bool_value!(self, section, missing, log_ticks);
missing
} else {
true
}
}
}
impl Section for VisualConfig {
fn apply_values(&mut self, parsed_config: &Value) -> bool {
if let Some(section) = parsed_config.get("visuals") {
let mut missing = false;
apply_bool_value!(self, section, missing, with_scanlines);
apply_bool_value!(self, section, missing, with_screen_burn);
apply_bool_value!(self, section, missing, with_darken_by_distance);
missing
} else {
true
}
}
}
#[cfg(not(target_arch = "wasm32"))]
pub fn try_load_configuration() -> Config {
let config: Config = Config::load_from_file("config.toml");
return config; return config;
} }