From: Ian Jackson Date: Sat, 7 Aug 2021 19:51:32 +0000 (+0100) Subject: ini: wip new module X-Git-Tag: hippotat/1.0.0~261 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=bbfac470b93e9791549ce99512ba4b89bd56923c;p=hippotat.git ini: wip new module Signed-off-by: Ian Jackson --- diff --git a/src/ini.rs b/src/ini.rs index a8c9558..67817f5 100644 --- a/src/ini.rs +++ b/src/ini.rs @@ -2,15 +2,21 @@ // 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, - pub line: usize, + pub lno: usize, pub section: Option>, } #[derive(Debug,Clone)] -pub struct RawVal { - pub raw: String, +pub struct Val { + pub val: String, pub loc: Loc, } @@ -19,15 +25,15 @@ pub type Parsed = HashMap, Section>; pub struct Section { /// Location of first encounter pub loc: Loc, - pub values: HashMap, + pub values: HashMap, } 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#"""#)?; @@ -42,53 +48,56 @@ impl Display for Loc { } #[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 = 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 = 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())? } } diff --git a/src/prelude.rs b/src/prelude.rs index 277513a..355f588 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -32,7 +32,7 @@ pub use hyper::Uri; pub use hyper_tls::HttpsConnector; pub use ipnet::IpNet; pub use itertools::{iproduct, Itertools}; -pub use lazy_regex::{regex_is_match, regex_replace_all}; +pub use lazy_regex::{regex_captures, regex_is_match, regex_replace_all}; pub use log::{trace, debug, info, warn, error}; pub use structopt::StructOpt; pub use thiserror::Error;