section_config: improve parser

This commit is contained in:
Dietmar Maurer 2018-11-26 18:01:24 +01:00
parent 07d3fa7289
commit dd193a61d0
1 changed files with 78 additions and 6 deletions

View File

@ -1,3 +1,5 @@
use failure::*;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::collections::HashMap; use std::collections::HashMap;
@ -11,7 +13,12 @@ pub struct SectionConfigPlugin {
pub struct SectionConfig { pub struct SectionConfig {
plugins: HashMap<String, SectionConfigPlugin>, plugins: HashMap<String, SectionConfigPlugin>,
parse_section_header: fn(String) -> Value, parse_section_header: fn(&str) -> Option<(String, String)>,
}
enum ParseState {
BeforeHeader,
InsideSection,
} }
impl SectionConfig { 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() { 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" let raw = r"
lvmthin: local-lvm lvmthin: local-lvm
thinpool data thinpool data
vgname pve5 vgname pve5