//! Functions for burritos.cfg configuration file parsing. //! Needed to set-up machine and system constants without //! recompiling. use std::{ fs::File, path::Path, collections::HashMap, io::{ BufReader, BufRead, Error } }; /// Aliases the rather long HashMap type /// to a rather simpler to understand Settings. pub type Settings = HashMap; /// Keys for the Settings HashMap, represented as enums for /// maintainability. #[derive(Eq, Hash, PartialEq, Debug)] pub enum MachineSettingKey { /// Number of physical pages. NumPhysPages, /// Stack size. UserStackSize, /// Maximum size of a file name MaxFileNameSize, /// Number of directory entries NumDirEntries, /// Processor Frequency ProcessorFrequency, /// Disk sector size SectorSize, /// Memory page size PageSize, /// Maximum number of Virtual Pages MaxVirtPages, /// In case of unknown key in configuration file. Unknown } /// Allows for converting string slices to correspoding MachineSettingKey /// enum value. impl From<&str> for MachineSettingKey { fn from(s: &str) -> Self { match s { "NumPhysPages" => MachineSettingKey::NumPhysPages, "UserStackSize" => MachineSettingKey::UserStackSize, "MaxFileNameSize" => MachineSettingKey::MaxFileNameSize, "NumDirEntries" => MachineSettingKey::NumDirEntries, "ProcessorFrequency" => MachineSettingKey::ProcessorFrequency, "SectorSize" => MachineSettingKey::SectorSize, "PageSize" => MachineSettingKey::PageSize, "MaxVirtPages" => MachineSettingKey::MaxVirtPages, _ => MachineSettingKey::Unknown } } } /// Tries to return a HashMap containing the user defined burritos configuration /// in the burritos.cfg file. /// /// If the file is not found, the function will return an io error. /// /// If the configuration is invalid, the function may return a HashMap with missing or /// non-sensical settings. /// It is up to the caller to determine whether or not default values should be placed /// instead of halting the program. pub fn read_settings() -> Result { // Opening file let file = { let file_path = "./burritos.cfg"; let file_path = Path::new(file_path); match File::open(file_path) { Ok(opened_file) => opened_file, Err(error_message) => Err(error_message)? } }; let file_reader = BufReader::new(file); let filtered_setting_strings = filter_garbage(file_reader); let mut settings_map = Settings::new(); // Reading settings for line in filtered_setting_strings { let mut split_line = line.split_whitespace(); let key = split_line.next().unwrap_or("_"); split_line.next(); // Skipping '=' character let setting = split_line.next().unwrap_or("_"); settings_map = update_settings_map(settings_map, key, setting); } Ok(settings_map) } fn filter_garbage(reader: BufReader) -> Vec { reader.lines() .map(|l| l.unwrap()) .filter(|l| !l.is_empty() && !l.starts_with("#")) .collect() } fn update_settings_map(mut settings_map: Settings, key: &str, setting: &str) -> Settings { let key = MachineSettingKey::from(key); let setting = i32::from_str_radix(setting, 10).unwrap_or(0); settings_map.insert(key, setting); settings_map }