section_config: improve parser
This commit is contained in:
		@ -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<String, SectionConfigPlugin>,
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user