From 0b2480f849e8d22facb3baa2b3c0b3ade2b6b666 Mon Sep 17 00:00:00 2001 From: Bruce Leidl Date: Wed, 30 Jan 2019 14:09:34 -0500 Subject: [PATCH] Refactor to chain realm specific config to global config Now if a variable is not set in a realm config file (or the file does not exist), the 'global' config file will also be searched in the parent directory (ie: /storage/realms/config). If the variable is still not found, the value from the default instance is returned. --- citadel-realms/src/config.rs | 170 +++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 55 deletions(-) diff --git a/citadel-realms/src/config.rs b/citadel-realms/src/config.rs index da7bc2b..4e748e4 100644 --- a/citadel-realms/src/config.rs +++ b/citadel-realms/src/config.rs @@ -1,112 +1,172 @@ use std::path::Path; -use std::fs::File; -use std::io::Read; +use std::fs; use toml; -use crate::Result; -fn default_true() -> bool { - true +lazy_static! { + pub static ref GLOBAL_CONFIG: RealmConfig = RealmConfig::load_global_config(); } fn default_zone() -> String { "clear".to_owned() } +fn default_realmfs() -> String { + "base".to_owned() +} + #[derive (Deserialize,Clone)] pub struct RealmConfig { - #[serde(default = "default_true", rename="use-shared-dir")] - use_shared_dir: bool, + #[serde(rename="use-shared-dir")] + use_shared_dir: Option, - #[serde(default, rename="use-ephemeral-home")] - use_ephemeral_home: bool, + #[serde(rename="use-ephemeral-home")] + use_ephemeral_home: Option, - #[serde(default = "default_true", rename="use-sound")] - use_sound: bool, + #[serde(rename="use-sound")] + use_sound: Option, - #[serde(default = "default_true", rename="use-x11")] - use_x11: bool, + #[serde(rename="use-x11")] + use_x11: Option, - #[serde(default = "default_true", rename="use-wayland")] - use_wayland: bool, + #[serde(rename="use-wayland")] + use_wayland: Option, - #[serde(default, rename="use-kvm")] - use_kvm: bool, + #[serde(rename="use-kvm")] + use_kvm: Option, - #[serde(default,rename="use-gpu")] - use_gpu: bool, + #[serde(rename="use-gpu")] + use_gpu: Option, - #[serde(default = "default_true", rename="use-network")] - use_network: bool, + #[serde(rename="use-network")] + use_network: Option, + + #[serde(rename="network-zone")] + network_zone: Option, + + realmfs: Option, + + #[serde(rename="realmfs-write")] + realmfs_write: Option, + + #[serde(skip)] + parent: Option>, - #[serde(default = "default_zone", rename="network-zone")] - network_zone: String, } impl RealmConfig { - pub fn load_or_default(path: &Path) -> Result { - if path.exists() { - let s = load_as_string(&path)?; - let config = toml::from_str::(&s)?; - Ok(config) - } else { - Ok(RealmConfig::default()) + + pub fn load_or_default>(path: P) -> RealmConfig { + match RealmConfig::load_config(path) { + Some(config) => config, + None => GLOBAL_CONFIG.clone() } } + fn load_global_config() -> RealmConfig { + if let Some(mut global) = RealmConfig::load_config("/storage/realms/config") { + global.parent = Some(Box::new(RealmConfig::default())); + return global; + } + RealmConfig::default() + } + + fn load_config>(path: P) -> Option { + if path.as_ref().exists() { + match fs::read_to_string(path.as_ref()) { + Ok(s) => return toml::from_str::(&s).ok(), + Err(e) => warn!("Error reading config file: {}", e), + } + } + None + } + pub fn default() -> RealmConfig { RealmConfig { - use_shared_dir: true, - use_ephemeral_home: false, - use_sound: true, - use_x11: true, - use_wayland: true, - use_kvm: false, - use_gpu: false, - use_network: true, - network_zone: default_zone(), + use_shared_dir: Some(true), + use_ephemeral_home: Some(false), + use_sound: Some(true), + use_x11: Some(true), + use_wayland: Some(true), + use_kvm: Some(false), + use_gpu: Some(false), + use_network: Some(true), + network_zone: Some(default_zone()), + realmfs: Some(default_realmfs()), + realmfs_write: Some(false), + parent: None, } } pub fn kvm(&self) -> bool { - self.use_kvm + self.bool_value(|c| c.use_kvm) } pub fn gpu(&self) -> bool { - self.use_gpu + self.bool_value(|c| c.use_gpu) } pub fn shared_dir(&self) -> bool { - self.use_shared_dir + self.bool_value(|c| c.use_shared_dir) } pub fn emphemeral_home(&self) -> bool { - self.use_ephemeral_home + self.bool_value(|c| c.use_ephemeral_home) } pub fn sound(&self) -> bool { - self.use_sound + self.bool_value(|c| c.use_sound) } pub fn x11(&self) -> bool { - self.use_x11 + self.bool_value(|c| c.use_x11) } pub fn wayland(&self) -> bool { - self.use_wayland + self.bool_value(|c| c.use_network) } pub fn network(&self) -> bool { - self.use_network + self.bool_value(|c| c.use_network) } pub fn network_zone(&self) -> &str { - &self.network_zone + self.str_value(|c| c.network_zone.as_ref()) + } + + pub fn realmfs(&self) -> &str { + self.str_value(|c| c.realmfs.as_ref()) + } + + pub fn realmfs_write(&self) -> bool { + self.bool_value(|c| c.realmfs_write) + } + + fn str_value(&self, get: F) -> &str + where F: Fn(&RealmConfig) -> Option<&String> + { + if let Some(ref val) = get(self) { + return val + } + if let Some(ref parent) = self.parent { + if let Some(val) = get(parent) { + return val; + } + } + "" + + } + + fn bool_value(&self, get: F) -> bool + where F: Fn(&RealmConfig) -> Option + { + if let Some(val) = get(self) { + return val + } + + if let Some(ref parent) = self.parent { + return get(parent).unwrap_or(false); + } + false + } } - -fn load_as_string(path: &Path) -> Result { - let mut f = File::open(path)?; - let mut buffer = String::new(); - f.read_to_string(&mut buffer)?; - Ok(buffer) -}