use crate::prelude::*;
-use configparser::ini::Ini; // xxx ignores empty sections, fix or replace
-
#[derive(hippotat_macros::ResolveConfig)]
#[derive(Debug,Clone)]
pub struct InstanceConfig {
}
pub use SectionName as SN;
-#[derive(Debug,Clone)]
-struct RawVal { raw: Option<String>, loc: Arc<PathBuf> }
-type SectionMap = HashMap<String, RawVal>;
-
#[derive(Debug)]
struct RawValRef<'v,'l,'s> {
- raw: Option<&'v str>,
+ raw: Option<&'v str>, // todo: not Option any more
key: &'static str,
- loc: &'l Path,
+ loc: &'l ini::Loc,
section: &'s SectionName,
}
struct Aggregate {
end: LinkEnd,
keys_allowed: HashMap<&'static str, SectionKindList>,
- sections: HashMap<SectionName, SectionMap>,
+ sections: HashMap<SectionName, ini::Section>,
}
type OkAnyway<'f,A> = &'f dyn Fn(ErrorKind) -> Option<A>;
#[throws(AE)] // AE does not include path
fn read_string(&mut self, s: String, path_for_loc: &Path) {
- let mut ini = Ini::new_cs();
- ini.set_default_section(OUTSIDE_SECTION);
- ini.read(s).map_err(|e| anyhow!("{}", e)).context("parse as INI")?;
- let map = mem::take(ini.get_mut_map());
+ let mut map: ini::Parsed = default();
+ ini::read(&mut map, &mut s.as_bytes(), path_for_loc)
+ .context("parse as INI")?;
if map.get(OUTSIDE_SECTION).is_some() {
throw!(anyhow!("INI file contains settings outside a section"));
}
- let loc = Arc::new(path_for_loc.to_owned());
-
- for (sn, vars) in map {
+ for (sn, section) in map {
let sn = sn.parse().dcontext(&sn)?;
+ let vars = §ion.values;
for key in vars.keys() {
let skl = if key == "server" {
}
}
- let ent = self.sections.entry(sn).or_default();
- for (key, raw) in vars {
- let raw = match raw {
- Some(raw) if raw.starts_with('\'') || raw.starts_with('"') => Some(
- (||{
- if raw.contains('\\') {
- throw!(
- anyhow!("quoted value contains backslash, not supported")
- );
- }
- let unq = raw[1..].strip_suffix(&raw[0..1])
- .ok_or_else(
- || anyhow!("mismatched quotes around quoted value")
- )?
- .to_owned();
- Ok::<_,AE>(unq)
- })()
- .with_context(|| format!("key {:?}", key))
- .dcontext(path_for_loc)?
- ),
- x => x,
+ let ent = self.sections.entry(sn)
+ .or_insert_with(|| ini::Section {
+ loc: section.loc.clone(),
+ values: default(),
+ });
+
+ for (key, ini::Val { val: raw, loc }) in vars {
+ let val = if raw.starts_with('\'') || raw.starts_with('"') {
+ (||{
+ if raw.contains('\\') {
+ throw!(
+ anyhow!("quoted value contains backslash, not supported")
+ );
+ }
+ let unq = raw[1..].strip_suffix(&raw[0..1])
+ .ok_or_else(
+ || anyhow!("mismatched quotes around quoted value")
+ )?
+ .to_owned();
+ Ok::<_,AE>(unq)
+ })()
+ .with_context(|| format!("key {:?}", key))
+ .dcontext(path_for_loc)?
+ } else {
+ raw.clone()
};
let key = key.replace('-',"_");
- ent.insert(key, RawVal { raw, loc: loc.clone() });
+ ent.values.insert(key, ini::Val { val, loc: loc.clone() });
}
}
}
};
for (section, vars) in &self.sections {
- let has_secret = || vars.contains_key("secret");
+ let has_secret = || vars.values.contains_key("secret");
//dbg!(§ion, has_secret());
match section {
where S: Iterator<Item=&'s SectionName>
{
for section in sections {
- if let Some(raw) = self.sections
+ if let Some(val) = self.sections
.get(section)
- .and_then(|vars: &SectionMap| vars.get(key))
+ .and_then(|s: &ini::Section| s.values.get(key))
{
return Some(RawValRef {
- raw: raw.raw.as_deref(),
- loc: &raw.loc,
+ raw: Some(&val.val),
+ loc: &val.loc,
section, key,
})
}