use std::collections::HashMap; use crate::config::parser::{ParserError, parse_config}; use crate::time::{parse_finite_time_span, FiniteTimeSpan, TimeSpan, parse_time_span}; use crate::unit::Unit; pub mod loader; pub mod parser; #[derive(Clone, Debug, Default)] pub struct Config { name: String, file_pointer: usize, files: HashMap, sections: HashMap, } impl Config { pub(crate) fn add_file(&mut self, file_name: String) -> usize { let id = self.file_pointer; self.file_pointer += 1; self.files.insert(id, file_name); id } pub fn section(&self, name: &str) -> Option<&Section> { self.sections.get(name) } pub fn section_mut(&mut self, name: &str) -> &mut Section { self.sections.entry(name.to_string()).or_default() } pub fn load_file(&mut self, file_name: &str, file_contents: &str) -> Result<(), ParserError> { parse_config(self, file_name.to_string(), file_contents.to_string()) } pub fn get_unit(&self) -> Option { Unit::load_from_config(&self.name, self) } pub fn new(name: &str) -> Config { Config { name: name.to_string(), file_pointer: 0, files: Default::default(), sections: Default::default(), } } } #[derive(Clone, Debug, Default)] pub struct Section { name: String, entries: HashMap, } impl Section { pub fn new(name: String) -> Section { Section { name, entries: HashMap::new(), } } pub fn entry(&self, name: &str) -> Option<&Entry> { self.entries.get(name) } pub fn get_string(&self, name: &str) -> Option<&str> { self.entries.get(name).map(|x| x.get_string()) } pub fn get_boolean(&self, name: &str) -> Option { self.entries.get(name).and_then(|x| x.get_boolean()) } pub fn get_list(&self, name: &str) -> Option> { self.entries.get(name).map(|x| x.get_list()) } pub fn get_finite_time_span(&self, name: &str) -> Option { self.entries.get(name).and_then(|x| x.get_finite_time_span()) } pub fn get_time_span(&self, name: &str) -> Option { self.entries.get(name).and_then(|x| x.get_time_span()) } pub fn get_space_separated_list(&self, name: &str) -> Vec<&str> { self .get_list(name) .unwrap_or(vec![]) .iter() .flat_map(|x| x.split(" ")) .filter(|x| x.len() > 0) .collect() } pub fn get_space_separated_string(&self, name: &str) -> Vec<&str> { self .get_string(name) .unwrap_or("") .trim() .split(" ") .filter(|x| x.len() > 0) .collect() } } #[derive(Clone, Debug, Default)] pub struct Entry { name: String, values: Vec, } impl Entry { pub fn new(name: String) -> Entry { Entry { name, values: Vec::new(), } } pub fn add(&mut self, value: &str, file_id: usize) { self.values.push(EntryValue { value: value.to_string(), file_id }) } pub fn get_string(&self) -> &str { self.last_value().unwrap_or("") } pub fn get_list(&self) -> Vec<&str> { self.values.iter() .map(|x| x.value.as_str()) .fold(Vec::new(), |mut acc, val| { if val == "" { acc.clear() } else { acc.push(val) } acc }) } fn last_value(&self) -> Option<&str> { self.values.last().map(|x| x.value.as_str()) } pub fn get_boolean(&self) -> Option { self.last_value().and_then(|value| { match value { "yes" | "true" | "1" | "on" => { Some(true) } "no" | "false" | "0" | "off" => { Some(false) } _ => None } }) } pub fn get_time_span(&self) -> Option { self.last_value().and_then(parse_time_span) } pub fn get_finite_time_span(&self) -> Option { self.last_value().and_then(parse_finite_time_span) } } #[derive(Clone, Debug, Default)] struct EntryValue { value: String, file_id: usize, }