1 // Copyright 2021-2022 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later WITH Hippotat-OpenSSL-Exception
3 // There is NO WARRANTY.
10 #[derive(Debug,Clone)]
11 #[derive(Hash,Eq,PartialEq,Ord,PartialOrd)]
13 pub file: Arc<PathBuf>,
15 pub section: Option<Arc<str>>,
18 #[derive(Debug,Clone)]
24 pub type Parsed = HashMap<Arc<str>, Section>;
28 /// Location of first encounter
30 pub values: HashMap<String, Val>,
33 impl Display for Loc {
35 fn fmt(&self, f: &mut fmt::Formatter) {
36 write!(f, "{:?}:{}", &self.file, self.lno)?;
37 if let Some(s) = &self.section {
39 let dbg = format!("{:?}", &s);
40 if let Some(mid) = (||{
41 let mid = dbg.strip_prefix(r#"""#)?;
42 let mid = mid.strip_suffix(r#"""#)?;
45 write!(f, "[{}]", mid)?;
47 write!(f, "{}", dbg)?;
55 pub fn read(parsed: &mut Parsed, file: &mut dyn BufRead, path_for_loc: &Path)
58 let parsed = Rc::new(RefCell::new(parsed));
59 let path: Arc<PathBuf> = path_for_loc.to_owned().into();
60 let mut section: Option<RefMut<Section>> = None;
61 for (lno, line) in file.lines().enumerate() {
62 let line = line.context("read")?;
63 let line = line.trim();
65 if line.is_empty() { continue }
66 if regex_is_match!(r#"^ [;\#] "#x, line) { continue }
71 section: section.as_ref().map(|s| s.loc.section.as_ref().unwrap().clone()),
75 if let Some((_,new,)) =
76 regex_captures!(r#"^ \[ \s* (.+?) \s* \] $"#x, line)
78 let new: Arc<str> = new.to_owned().into();
80 section.take(); // drops previous RefCell borrow of parsed
82 let new_section = RefMut::map(parsed.borrow_mut(), |p| {
87 loc: Loc { section: Some(new), file: path.clone(), lno },
94 section = Some(new_section);
96 } else if let Some((_, key, val)) =
97 regex_captures!(r#"^ ( [^\[] .*? ) \s* = \s* (.*) $"#x, line)
99 let val = Val { loc: loc.clone(), val: val.into() };
103 .ok_or_else(|| anyhow!("value outside section"))?
105 .insert(key.into(), val);
108 throw!(if line.starts_with("[") {
109 anyhow!(r#"syntax error (section missing final "]"?)"#)
111 anyhow!(r#"syntax error (setting missing "="?)"#)
115 }))().with_context(|| loc.to_string())?