use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ConfigMap {
flat: IndexMap<String, String>,
sections: IndexMap<String, IndexMap<String, String>>,
}
impl ConfigMap {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn insert_flat(&mut self, key: String, value: String) {
self.flat.insert(key, value);
}
pub fn insert_sectioned(&mut self, section: String, key: String, value: String) {
self.sections.entry(section).or_default().insert(key, value);
}
pub fn get_flat(&self, key: &str) -> Option<&str> {
self.flat.get(key).map(String::as_str)
}
pub fn get_in_section(&self, section: &str, key: &str) -> Option<&str> {
self.sections
.get(section)
.and_then(|s| s.get(key))
.map(String::as_str)
}
#[must_use]
pub fn get_section(&self, section: &str) -> Option<&IndexMap<String, String>> {
self.sections.get(section)
}
#[must_use]
pub fn has_section(&self, section: &str) -> bool {
self.sections.contains_key(section)
}
pub fn flat_iter(&self) -> impl Iterator<Item = (&str, &str)> {
self.flat.iter().map(|(k, v)| (k.as_str(), v.as_str()))
}
pub fn sections(&self) -> impl Iterator<Item = (&str, &IndexMap<String, String>)> {
self.sections.iter().map(|(k, v)| (k.as_str(), v))
}
#[must_use]
pub fn len(&self) -> usize {
self.flat.len() + self.sections.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.flat.is_empty() && self.sections.is_empty()
}
#[must_use]
pub fn contains_key(&self, key: &str) -> bool {
if self.flat.contains_key(key) {
return true;
}
self.sections.values().any(|s| s.contains_key(key))
}
}