// SPDX-License-Identifier: GPL-3.0-or-later
// There is NO WARRANTY.
+use crate::prelude::*;
+
+use std::io::BufRead;
+
+#[derive(Debug,Clone)]
+#[derive(Hash,Eq,PartialEq,Ord,PartialOrd)]
pub struct Loc {
pub file: Arc<PathBuf>,
- pub line: usize,
+ pub lno: usize,
pub section: Option<Arc<String>>,
}
#[derive(Debug,Clone)]
-pub struct RawVal {
- pub raw: String,
+pub struct Val {
+ pub val: String,
pub loc: Loc,
}
pub struct Section {
/// Location of first encounter
pub loc: Loc,
- pub values: HashMap<String, RawVal>,
+ pub values: HashMap<String, Val>,
}
impl Display for Loc {
#[throws(fmt::Error)]
fn fmt(&self, f: &mut fmt::Formatter) {
- write!(f, "{}:{}", &self.file, self.line)?;
+ write!(f, "{:?}:{}", &self.file, self.lno)?;
if let Some(s) = &self.section {
- let dbg = format!("{:?}", &m);
+ let dbg = format!("{:?}", &s);
if let Some(mid) = (||{
let mid = dbg.strip_prefix(r#"""#)?;
let mid = mid.strip_suffix(r#"""#)?;
}
#[throws(AE)]
-pub fn read(parsed: &mut Parsed, file: &dyn BufRead, path_for_loc: &Path) {
- let path = path_for_loc.to_owned().into();
+pub fn read(parsed: &mut Parsed, file: &mut dyn BufRead, path_for_loc: &Path) {
+ let path: Arc<PathBuf> = path_for_loc.to_owned().into();
let section: Option<&mut Section> = None;
for (lno, line) in file.lines().enumerate() {
let line = line.context("read")?;
- (||{
- let line = line.trim();
+ let line = line.trim();
- if line.is_empty() { continue }
- if regex_is_match!(r#"^ [;#] "#x, line) { continue }
+ if line.is_empty() { continue }
+ if regex_is_match!(r#"^ [;#] "#x, line) { continue }
- let mut loc = Loc {
- line,
- file: path.clone(),
- section: section.as_ref().map(|s| s.section.clone()),
- };
+ let mut loc = Loc {
+ lno,
+ file: path.clone(),
+ section: section.as_ref().map(|s| s.loc.section.unwrap().clone()),
+ };
+ (|| Ok::<(),AE>({
- if let Some((_,section,)) =
+ if let Some((_,new,)) =
regex_captures!(r#"^ \[ \s* (.+?) \s* \] $"#x, line)
{
- let sname = Some(section.to_owned().into());
- section = Some(parsed.entry(sname.clone())
- .get_or_insert_with(|| {
- Section {
- loc: Loc { section: sname, ..loc },
- values: default(),
- }
- }));
- continue;
- }
+ let new: Arc<String> = new.to_owned().into();
+ section = Some(
+ parsed.entry(new.clone())
+ .or_insert_with(|| {
+ Section {
+ loc: Loc { section: Some(new), ..loc },
+ values: default(),
+ }
+ })
+ );
- if let Some((_,k,v)) =
+ } else if let Some((_, key, val)) =
regex_captures!(r#"^ ( [^\[] .*? ) \s* = \s* (.*) $"#, line)
{
- section.values.insert(k.into(), RawVal {
- loc,
- raw: v.into(),
- });
- continue;
- }
+ let val = Val { loc, val: val.into() };
+
+ section
+ .as_mut()
+ .ok_or_else(|| anyhow!("value outside section"))?
+ .values
+ .insert(key.into(), val);
- throw!(if line.starts_with("[") {
- anyhow!(r#"syntax error (section missing final "]"?)"#)
} else {
- anyhow!(r#"syntax error (setting missing "="?)"#)
- })
+ throw!(if line.starts_with("[") {
+ anyhow!(r#"syntax error (section missing final "]"?)"#)
+ } else {
+ anyhow!(r#"syntax error (setting missing "="?)"#)
+ })
+ }
- })().with_context(|| loc().to_string())?
+ }))().with_context(|| loc.to_string())?
}
}