From dd193a61d0d133d54a894b7d74fc0aeb3b9d26af Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Mon, 26 Nov 2018 18:01:24 +0100 Subject: [PATCH] section_config: improve parser --- src/section_config.rs | 84 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/src/section_config.rs b/src/section_config.rs index 910e20b5..980554e7 100644 --- a/src/section_config.rs +++ b/src/section_config.rs @@ -1,3 +1,5 @@ +use failure::*; + use std::fs::File; use std::io::Read; use std::collections::HashMap; @@ -11,7 +13,12 @@ pub struct SectionConfigPlugin { pub struct SectionConfig { plugins: HashMap, - parse_section_header: fn(String) -> Value, + parse_section_header: fn(&str) -> Option<(String, String)>, +} + +enum ParseState { + BeforeHeader, + InsideSection, } impl SectionConfig { @@ -23,18 +30,82 @@ impl SectionConfig { } } - pub fn parse(&self, filename: &str, raw: &str) { + pub fn parse(&self, filename: &str, raw: &str) -> Result<(), Error> { + + let mut line_no = 0; + + //let error_prefix = format!("file '{}' line {}", filename, line_no); + const ERROR_FORMAT: &str = "file '{}' line {} - {}"; + + let mut state = ParseState::BeforeHeader; for line in raw.lines() { - println!("LINE:{}", line); + line_no += 1; + + if line.trim().is_empty() { continue; } + + match state { + + ParseState::BeforeHeader => { + + if line.trim().is_empty() { continue; } + + if let Some((section_type, section_id)) = (self.parse_section_header)(line) { + println!("OKLINE: type: {} ID: {}", section_type, section_id); + state = ParseState::InsideSection; + } else { + println!("file '{}' line {} - {}", filename, line_no, "syntax error - expected header"); + } + } + ParseState::InsideSection => { + + if line.trim().is_empty() { + // finish section + state = ParseState::BeforeHeader; + continue; + } + println!("CONTENT: {}", line); + } + } } + + if let ParseState::InsideSection = state { + // finish section + } + + Ok(()) } - fn default_parse_section_header(line: String) -> Value { + pub fn default_parse_section_header(line: &str) -> Option<(String, String)> { - let config = json!({}); + if line.len() == 0 { return None; }; - config + let first_char = line.chars().next().unwrap(); + + if !first_char.is_alphabetic() { return None } + + let mut head_iter = line.splitn(2, ':'); + + let section_type = match head_iter.next() { + Some(v) => v, + None => return None, + }; + + let section_type = section_type.trim(); + + if section_type.len() == 0 { return None; } + + // fixme: verify format + + let section_id = match head_iter.next() { + Some(v) => v, + None => return None, + }; + + let section_id = section_id.trim(); + + + Some((section_type.into(), section_id.into())) } @@ -55,6 +126,7 @@ fn test_section_config1() { let raw = r" + lvmthin: local-lvm thinpool data vgname pve5