riscii

An emulator for the RISC II
Log | Files | Refs | LICENSE

commit 4e5686762875bf86a41238b951d111a6e052a54b
parent 05c903f535e52bfb5a4c7979eb87ba5e75d54dc2
Author: Ryan Jeffrey <ryan@ryanmj.xyz>
Date:   Wed,  8 Jun 2022 17:39:43 -0700

Configuration paths customization

Diffstat:
Msrc/config.rs | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 80 insertions(+), 13 deletions(-)

diff --git a/src/config.rs b/src/config.rs @@ -16,7 +16,10 @@ // Struct definitions. use std::env; +use std::env::JoinPathsError; +use std::ffi::OsString; use std::fmt; +use std::path::Path; /// Configuration of the emulator. pub struct Config { @@ -24,22 +27,65 @@ pub struct Config { mem: u32, /// Number of CPUs the system will have. ncpu: u32, + /// Path to the configuration directory. config_path: String, + /// Path to the configuration file. + config_file_path: String, + /// Path to the system cache directory. + cache_path: String, } // Struct impls. impl Config { - pub fn new() -> Config { - Config { + pub fn new() -> Result<Config, String> { + let home_dir = match env::var("HOME") { + Ok(v) => format!("{}", v), + Err(e) => { + eprintln!("$HOME is not set. Defaulting to current directory."); + format!( + "{}", + match env::current_dir() { + Ok(r) => os_string_result_to_strings(r.into_os_string().into_string())?, + Err(e) => format!("{}", e), + } + ) + } + }; + + let config_path = match env::var("XDG_CONFIG_HOME") { + Ok(v) => format!("{}", v), + Err(e) => format!("{}", home_dir), + }; + + let cache_dir = ".cache/riscii".to_string(); + Ok(Config { mem: 0, ncpu: 0, - config_path: format!(""), - } + config_file_path: concat_paths( + &config_path, + &".config/riscii/config.toml".to_string(), + )?, + cache_path: match env::var("XDG_CACHE_HOME") { + Ok(v) => concat_paths(&v, &cache_dir)?, + Err(v) => concat_paths(&home_dir, &cache_dir)?, + }, + config_path: config_path, + }) } pub fn init() -> Result<Config, String> { - let mut config = Self::new(); + let mut config = Self::new()?; + config.parse_cmd_args()?; + config.read_config_file()?; + Ok(config) + } + + fn read_config_file(&mut self) -> Result<(), String> { + Ok(()) + } + + fn parse_cmd_args(&mut self) -> Result<(), String> { let args: Vec<String> = env::args().collect(); let mut skips = 1i32; @@ -51,21 +97,21 @@ impl Config { match arg.as_str() { "--mem" => { - config.mem = args_get_next_uint(&args, i, &format!("mem"))?; + self.mem = args_get_next_uint(&args, i, &format!("mem"))?; skips += 1; } "--ncpu" => { - config.ncpu = args_get_next_uint(&args, i, &format!("ncpu"))?; + self.ncpu = args_get_next_uint(&args, i, &format!("ncpu"))?; skips += 1; } "--config" => { - config.config_path = args_get_next_arg(&args, i, &format!("config"))?.clone(); + self.config_path = args_get_next_arg(&args, i, &format!("config"))?.clone(); skips += 1; } _ => { println!( "Usage: riscii [OPTIONS] ---config Path to configuration file (default=~/.config/riscii/config.toml) +--config Path to configuration file (default=~/.config/riscii/self.toml) --mem Size of memory (in megabytes) (default=512) --ncpu Number of cores to emulate (default=1) " @@ -74,8 +120,7 @@ impl Config { } } } - - Ok(config) + Ok(()) } } @@ -122,8 +167,30 @@ impl fmt::Display for Config { f, "Number of cpus: {} Memory (MB): {} -Configuration file: {}", - self.ncpu, self.mem, self.config_path +Configuration directory: {} +Configuration file: {} +Cache Directory: {}", + self.ncpu, self.mem, self.config_path, self.config_file_path, self.cache_path ) } } + +// Local functions. + +fn os_string_result_to_strings(r: Result<String, OsString>) -> Result<String, String> { + match r { + Err(e) => Err(match e.into_string() { + Ok(s) => s, + Err(ee) => "Could not coerce OS string into utf8 string".to_string(), + }), + Ok(rr) => Ok(rr.to_string()), + } +} + +fn concat_paths(base: &String, rest: &String) -> Result<String, String> { + let p = Path::new(&base).join(&rest); + match p.to_str() { + None => Err(format!("{} and {} joined is not valid utf8", base, rest)), + Some(s) => Ok(s.to_string()), + } +}