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 toml::de::Error as TomlError;
use toml::Value;
use serde::{ Serialize, Deserialize };
lazy_static! {
@ -69,10 +70,25 @@ impl From<TomlError> for ReadError {
}
impl Config {
pub fn load_from_file(filename: &str) -> Result<Self, ReadError> {
let contents = std::fs::read_to_string(filename).map_err(|e| ReadError::Io(e))?;
let config: Config = toml::from_str(&contents).map_err(|e| ReadError::Toml(e))?;
return Ok(config);
pub fn load_from_file(filename: &str) -> Config {
if let Ok(contents) = std::fs::read_to_string(filename) {
let parsed_config: Result<Value, _> = toml::from_str(&contents);
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>> {
let toml_string = toml::to_string(self)?;
@ -81,23 +97,51 @@ impl Config {
}
}
#[cfg(not(target_arch = "wasm32"))]
pub fn try_load_configuration() -> Config {
let config: Config = match Config::load_from_file("config.toml") {
Ok(config) => {
console::log(format!("Successfully loaded config: {:?}", config));
config
macro_rules! apply_bool_value {
($config:expr, $parsed_config:expr, $changed:expr, $field:ident) => {
if let Some(value) = $parsed_config.get(stringify!($field)).and_then(|v| v.as_bool()) {
if $config.$field != value {
$config.$field = value;
$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;
}