extern crate serde; extern crate serde_json; extern crate serde_yaml; use serde::{Deserialize, Serialize}; extern crate log; use log::warn; // mod utils; pub mod utils; use utils::SettingsType; #[allow(dead_code)] const RULESET_CURRENT_VERSION: &'static str = "1"; #[derive(Debug, Deserialize, Serialize)] pub struct Settings { #[serde(default = "Settings::get_ruleset_version")] version: String, #[serde(default)] categories: Vec<(String, String)>, #[serde(default)] rules: Vec<(String, String)>, } /// Representation inside the crate of LangEvolve’s settings. impl Settings { /// Creates a new empty instance of `Settings` /// /// # Example /// /// ``` /// let s = lang_evolve_core::settings::Settings::new(); /// let content_yaml = r#"--- /// version: "1" /// categories: [] /// rules: []"#; /// let content_json = r#"{"version":"1","categories":[],"rules":[]}"#; /// assert_eq!(content_yaml, serde_yaml::to_string(&s).unwrap()); /// assert_eq!(content_json, serde_json::to_string(&s).unwrap()); /// ``` pub fn new() -> Self { Self { version: Self::get_ruleset_version(), categories: Vec::new(), rules: Vec::new(), } } /// Import settings from an imput file. The currently allowed file formats /// are: /// - JSON - with the `.json` extension /// - Yaml - with the `.yaml` or `.yml` extension /// The format will be automatically detected based on the filename /// extension. /// /// # Arguments /// /// * `path` - File to open and load settings from /// /// # Example /// /// ```no_run /// use std::path::Path; /// use lang_evolve_core::settings::Settings; /// let path_json = Path::new("settings.json"); /// let _s_json = Settings::import(&path_json).unwrap(); /// /// let path_yaml = Path::new("settings.yaml"); /// let _s_yaml = Settings::import(&path_yaml).unwrap(); /// /// let path_yml = Path::new("settings.yml"); /// let _s_yml = Settings::import(&path_yml).unwrap(); /// ``` pub fn import(path: &std::path::Path) -> std::io::Result { use SettingsType::*; let display = path.display(); let file_type = utils::get_file_type(&path).unwrap(); let content = match utils::read_file(&path) { Err(e) => { warn!("Could not read file {}: {}", display, e.to_string()); return Err(e); } Ok(content) => content, }; let settings: Settings = match file_type { Yaml => match serde_yaml::from_str(&content) { Err(e) => { warn!("Could not import settings: {}", e.to_string()); return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, e, )); } Ok(val) => val, }, Json => match serde_json::from_str(&content) { Err(e) => { warn!("Could not import settings: {}", e.to_string()); return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, e, )); } Ok(val) => val, }, }; Ok(settings) } /// Export the current rules to a file. The allowed file formats are either /// a YAML file or a Json file, hence the allowed filename extension are: /// * "yml" or "yaml" for Yaml files /// * "json" for Json files /// The format is detected automatically depending on the extension of the /// filename. /// /// # Arguments /// /// * `path` - Path to write and export settings to /// /// # Example /// /// ``` /// use std::path::Path; /// let s = lang_evolve_core::settings::Settings::new(); /// /// // Export to JSON /// let path_json = Path::new("./output.json"); /// s.export(&path_json).unwrap(); /// /// // Export to Yaml, both ".yml" and ".yaml" work /// let path_yaml = Path::new("./output.yaml"); /// s.export(&path_yaml).unwrap(); /// let path_yml = Path::new("./output.yml"); /// s.export(&path_yml).unwrap(); /// ``` pub fn export(&self, path: &std::path::Path) -> std::io::Result<()> { let filetype = utils::get_file_type(&path).unwrap(); let content = match filetype { SettingsType::Yaml => match serde_yaml::to_string(&self) { Err(e) => { warn!("Could not serialize settings: {}", e.to_string()); return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, e, )); } Ok(val) => val, }, SettingsType::Json => match serde_json::to_string(&self) { Err(e) => { warn!("Could not serialize settings: {}", e.to_string()); return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, e, )); } Ok(val) => val, }, }; utils::write_file(&path, &content) } /// Get the current ruleset version of LangEvolve. fn get_ruleset_version() -> String { String::from(RULESET_CURRENT_VERSION) } } impl PartialEq for Settings { fn eq(&self, other: &Self) -> bool { self.version == other.version && self.categories == other.categories && self.rules == other.rules } } impl Eq for Settings {} #[test] fn write_settings() { let s = Settings::new(); let path = std::path::Path::new("test.yaml"); let settings = r#"--- version: "1" categories: [] rules: []"#; utils::write_file(&path, serde_yaml::to_string(&s).unwrap()).unwrap(); assert_eq!(settings, utils::read_file(&path).unwrap()); } #[test] fn read_settings() { let s1 = Settings::new(); let path = std::path::Path::new("test.yml"); s1.export(&path).unwrap(); let s2 = Settings::import(&path).unwrap(); assert_eq!(s1, s2); }