#![warn(missing_docs)]
#![warn(unsafe_code)]
use std::{fs::File, io::BufReader, path::Path, sync::RwLock};
use serde::{Deserialize, Serialize};
pub mod config_data;
pub mod error;
pub mod petscii;
#[derive(Clone, Serialize, Deserialize)]
pub struct SystemConfig {
pub version: String,
pub character_set_map: petscii::PetsciiConfig,
}
#[derive(Serialize, Deserialize)]
pub struct Config {
pub version: String,
pub petscii: SystemConfig,
}
pub static CONFIG: RwLock<Option<Config>> = RwLock::new(None);
pub trait Configuration {
fn load() -> std::result::Result<Config, error::Error>;
fn load_from_file(filename: &str) -> std::result::Result<Config, error::Error>;
}
impl Configuration for Config {
fn load() -> std::result::Result<Config, error::Error> {
let json_str = config_data::CONFIG_DATA;
let config: Config = serde_json::from_str(json_str)?;
Ok(config)
}
fn load_from_file(filename: &str) -> std::result::Result<Config, error::Error> {
let path = Path::new(filename);
let file = File::open(path)?;
let reader = BufReader::new(file);
let config: Config = serde_json::from_reader(reader)?;
Ok(config)
}
}
#[cfg(test)]
mod tests {
use crate::{Config, Configuration};
#[test]
fn config_works() {
let config = Config::load().expect("Error loading config");
let key: String = 167.to_string();
let res: Option<&serde_json::Value> = config
.petscii
.character_set_map
.c64_petscii_unshifted_codes_to_screen_codes
.get(&key);
match res.unwrap() {
serde_json::Value::Array(v) => {
assert_eq!(v.first().unwrap().as_u64().unwrap(), 1);
assert_eq!(v.get(1).unwrap().as_u64().unwrap(), 103);
}
_ => {
assert!(false);
}
}
let key: String = 103.to_string();
let res = config
.petscii
.character_set_map
.c64_screen_codes_set_1_to_unicode_codes
.get(&key);
assert!(res.is_none());
}
#[test]
fn config_from_file_works() {
let config_fn = String::from("data/config.json");
let config = Config::load_from_file(&config_fn).expect("error loading config file");
let version: String = config.version;
assert_eq!(version, "0.2.0");
}
}