You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.4 KiB
Rust

use std::collections::HashMap;
use crate::config::parser::{ParserError, parse_config};
use crate::time::{parse_finite_time_span, FiniteTimeSpan, TimeSpan, parse_time_span};
4 years ago
use crate::unit::Unit;
pub mod loader;
pub mod parser;
#[derive(Clone, Debug, Default)]
pub struct Config {
name: String,
file_pointer: usize,
files: HashMap<usize, String>,
sections: HashMap<String, Section>,
}
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
}
4 years ago
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()
}
4 years ago
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> {
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<String, Entry>,
}
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<bool> {
self.entries.get(name).and_then(|x| x.get_boolean())
}
pub fn get_list(&self, name: &str) -> Option<Vec<&str>> {
self.entries.get(name).map(|x| x.get_list())
}
pub fn get_finite_time_span(&self, name: &str) -> Option<FiniteTimeSpan> {
self.entries.get(name).and_then(|x| x.get_finite_time_span())
}
pub fn get_time_span(&self, name: &str) -> Option<TimeSpan> {
self.entries.get(name).and_then(|x| x.get_time_span())
}
4 years ago
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<EntryValue>,
}
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<bool> {
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<TimeSpan> {
self.last_value().and_then(parse_time_span)
}
pub fn get_finite_time_span(&self) -> Option<FiniteTimeSpan> {
self.last_value().and_then(parse_finite_time_span)
}
}
#[derive(Clone, Debug, Default)]
struct EntryValue {
value: String,
file_id: usize,
}