From 9b50c161036acf6ad2a4faa7be70a5b980240d2c Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 15 Feb 2019 12:13:15 +0100 Subject: [PATCH] section_config.rs: simplify parser by using new try_block macro --- src/config/datastore.rs | 16 ++--- src/section_config.rs | 132 ++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 77 deletions(-) diff --git a/src/config/datastore.rs b/src/config/datastore.rs index 2a916eec..704dc051 100644 --- a/src/config/datastore.rs +++ b/src/config/datastore.rs @@ -37,18 +37,12 @@ const DATASTORE_CFG_FILENAME: &str = "/etc/proxmox-backup/datastore.cfg"; pub fn config() -> Result { - let mut file = match OpenOptions::new() - .create(true) - .read(true) - .write(true) - .open(DATASTORE_CFG_FILENAME) { - Ok(file) => file, - Err(err) => bail!("Unable to open '{}' - {}", - DATASTORE_CFG_FILENAME, err), - }; - let mut contents = String::new(); - file.read_to_string(&mut contents)?; + + try_block!({ + let mut file = std::fs::File::open(DATASTORE_CFG_FILENAME)?; + file.read_to_string(&mut contents) + }).map_err(|e| format_err!("unable to read '{}' - {}", DATASTORE_CFG_FILENAME, e))?; CONFIG.parse(DATASTORE_CFG_FILENAME, &contents) } diff --git a/src/section_config.rs b/src/section_config.rs index 0a057a73..8f552977 100644 --- a/src/section_config.rs +++ b/src/section_config.rs @@ -145,8 +145,6 @@ impl SectionConfig { pub fn parse(&self, filename: &str, raw: &str) -> Result { - let mut line_no = 0; - let mut state = ParseState::BeforeHeader; let test_required_properties = |value: &Value, schema: &ObjectSchema| -> Result<(), Error> { @@ -158,87 +156,89 @@ impl SectionConfig { Ok(()) }; - let mut result = SectionConfigData::new(); + let mut line_no = 0; - let mut create_section = |section_id: &str, type_name: &str, config| { - result.set_data(section_id, type_name, config); - result.record_order(section_id); - }; + try_block!({ - for line in raw.lines() { - line_no += 1; + let mut result = SectionConfigData::new(); - match state { + let mut create_section = |section_id: &str, type_name: &str, config| { + result.set_data(section_id, type_name, config); + result.record_order(section_id); + }; - ParseState::BeforeHeader => { + try_block!({ + for line in raw.lines() { + line_no += 1; - if line.trim().is_empty() { continue; } + match state { - if let Some((section_type, section_id)) = (self.parse_section_header)(line) { - //println!("OKLINE: type: {} ID: {}", section_type, section_id); - if let Some(ref plugin) = self.plugins.get(§ion_type) { - if let Err(err) = parse_simple_value(§ion_id, &self.id_schema) { - bail!("file '{}' line {} - syntax error in section identifier: {}", - filename, line_no, err.to_string()); - } - state = ParseState::InsideSection(plugin, section_id, json!({})); - } else { - bail!("file '{}' line {} - unknown section type '{}'", - filename, line_no, section_type); - } - } else { - bail!("file '{}' line {} - syntax error (expected header)", filename, line_no); - } - } - ParseState::InsideSection(plugin, ref mut section_id, ref mut config) => { + ParseState::BeforeHeader => { - if line.trim().is_empty() { - // finish section - if let Err(err) = test_required_properties(config, &plugin.properties) { - bail!("file '{}' line {} - {}", filename, line_no, err.to_string()); - } - create_section(section_id, &plugin.type_name, config.take()); - state = ParseState::BeforeHeader; - continue; - } - if let Some((key, value)) = (self.parse_section_content)(line) { - //println!("CONTENT: key: {} value: {}", key, value); + if line.trim().is_empty() { continue; } - if let Some((_optional, prop_schema)) = plugin.properties.properties.get::(&key) { - match parse_simple_value(&value, prop_schema) { - Ok(value) => { - if config[&key] == Value::Null { - config[key] = value; - } else { - bail!("file '{}' line {} - duplicate property '{}'", - filename, line_no, key); + if let Some((section_type, section_id)) = (self.parse_section_header)(line) { + //println!("OKLINE: type: {} ID: {}", section_type, section_id); + if let Some(ref plugin) = self.plugins.get(§ion_type) { + if let Err(err) = parse_simple_value(§ion_id, &self.id_schema) { + bail!("syntax error in section identifier: {}", err.to_string()); } + state = ParseState::InsideSection(plugin, section_id, json!({})); + } else { + bail!("unknown section type '{}'", section_type); } - Err(err) => { - bail!("file '{}' line {} - property '{}': {}", - filename, line_no, key, err.to_string()); - } + } else { + bail!("syntax error (expected header)"); + } + } + ParseState::InsideSection(plugin, ref mut section_id, ref mut config) => { + + if line.trim().is_empty() { + // finish section + test_required_properties(config, &plugin.properties)?; + create_section(section_id, &plugin.type_name, config.take()); + state = ParseState::BeforeHeader; + continue; + } + if let Some((key, value)) = (self.parse_section_content)(line) { + //println!("CONTENT: key: {} value: {}", key, value); + + if let Some((_optional, prop_schema)) = plugin.properties.properties.get::(&key) { + match parse_simple_value(&value, prop_schema) { + Ok(value) => { + if config[&key] == Value::Null { + config[key] = value; + } else { + bail!("duplicate property '{}'", key); + } + } + Err(err) => { + bail!("property '{}': {}", key, err.to_string()); + } + } + } else { + bail!("unknown property '{}'", key) + } + } else { + bail!("syntax error (expected section properties)"); } - } else { - bail!("file '{}' line {} - unknown property '{}'", filename, line_no, key) } - } else { - bail!("file '{}' line {} - syntax error (expected section properties)", filename, line_no); } } - } - } - if let ParseState::InsideSection(plugin, section_id, config) = state { - // finish section + if let ParseState::InsideSection(plugin, section_id, config) = state { + // finish section + test_required_properties(&config, &plugin.properties)?; + create_section(§ion_id, &plugin.type_name, config); + } - if let Err(err) = test_required_properties(&config, &plugin.properties) { - bail!("file '{}' line {} - {}", filename, line_no, err.to_string()); - } - create_section(§ion_id, &plugin.type_name, config); - } + Ok(()) - Ok(result) + }).map_err(|e| format_err!("line {} - {}", line_no, e))?; + + Ok(result) + + }).map_err(|e: Error| format_err!("parsing '{}' failed: {}", filename, e)) } pub fn default_format_section_header(type_name: &str, section_id: &str, _data: &Value) -> String {