section_config: add write - first try
This commit is contained in:
parent
92fb0784d4
commit
e189c93b8c
@ -3,6 +3,9 @@ use failure::*;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::LinkedList;
|
||||
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use std::sync::Arc;
|
||||
@ -27,6 +30,7 @@ pub struct SectionConfig {
|
||||
id_schema: Arc<Schema>,
|
||||
parse_section_header: fn(&str) -> Option<(String, String)>,
|
||||
parse_section_content: fn(&str) -> Option<(String, String)>,
|
||||
format_section_header: fn(type_name: &str, section_id: &str, data: &Value) -> String,
|
||||
}
|
||||
|
||||
enum ParseState<'a> {
|
||||
@ -36,22 +40,23 @@ enum ParseState<'a> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SectionConfigData {
|
||||
sections: HashMap<String, Value>,
|
||||
order: HashMap<String, usize>,
|
||||
sections: HashMap<String, (String, Value)>,
|
||||
order: LinkedList<String>,
|
||||
}
|
||||
|
||||
impl SectionConfigData {
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self { sections: HashMap::new(), order: HashMap::new() }
|
||||
Self { sections: HashMap::new(), order: LinkedList::new() }
|
||||
}
|
||||
|
||||
pub fn set_data(&mut self, section_id: &str, config: Value) {
|
||||
self.sections.insert(section_id.to_string(), config);
|
||||
pub fn set_data(&mut self, section_id: &str, type_name: &str, config: Value) {
|
||||
// fixme: verify section_id schema here??
|
||||
self.sections.insert(section_id.to_string(), (type_name.to_string(), config));
|
||||
}
|
||||
|
||||
fn set_order(&mut self, section_id: &str, pri: usize) {
|
||||
self.order.insert(section_id.to_string(), pri);
|
||||
fn record_order(&mut self, section_id: &str) {
|
||||
self.order.push_back(section_id.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +68,7 @@ impl SectionConfig {
|
||||
id_schema: id_schema,
|
||||
parse_section_header: SectionConfig::default_parse_section_header,
|
||||
parse_section_content: SectionConfig::default_parse_section_content,
|
||||
format_section_header: SectionConfig::default_format_section_header,
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +76,61 @@ impl SectionConfig {
|
||||
self.plugins.insert(plugin.type_name.clone(), plugin);
|
||||
}
|
||||
|
||||
pub fn write(&self, filename: &str, config: &SectionConfigData) -> Result<(), Error> {
|
||||
|
||||
let mut list = LinkedList::new();
|
||||
|
||||
let mut done = HashSet::new();
|
||||
|
||||
for id in &config.order {
|
||||
if config.sections.get(id) == None { continue };
|
||||
list.push_back(id);
|
||||
done.insert(id);
|
||||
}
|
||||
|
||||
for (id, _) in &config.sections {
|
||||
if done.contains(id) { continue };
|
||||
list.push_back(id);
|
||||
}
|
||||
|
||||
let mut raw = String::new();
|
||||
|
||||
for id in list {
|
||||
let (type_name, section_config) = config.sections.get(id).unwrap();
|
||||
let plugin = self.plugins.get(type_name).unwrap();
|
||||
|
||||
// fixme: verify json data
|
||||
println!("REAL WRITE {} {} {:?}\n", id, type_name, section_config);
|
||||
|
||||
let head = (self.format_section_header)(type_name, id, section_config);
|
||||
|
||||
if !raw.is_empty() { raw += "\n" }
|
||||
|
||||
raw += &head;
|
||||
|
||||
for (key, value) in section_config.as_object().unwrap() {
|
||||
let text = match value {
|
||||
Value::Null => { continue; }, // do nothing ?
|
||||
Value::Bool(bv) => bv.to_string(),
|
||||
Value::String(str) => str.to_string(),
|
||||
Value::Number(num) => num.to_string(),
|
||||
_ => {
|
||||
bail!("file {}: got unsupported type in section {} key {}", filename, id, key);
|
||||
},
|
||||
};
|
||||
raw += "\t";
|
||||
raw += &key;
|
||||
raw += " ";
|
||||
raw += &text;
|
||||
raw += "\n";
|
||||
}
|
||||
println!("CONFIG:\n{}", raw);
|
||||
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn parse(&self, filename: &str, raw: &str) -> Result<SectionConfigData, Error> {
|
||||
|
||||
let mut line_no = 0;
|
||||
@ -87,18 +148,14 @@ impl SectionConfig {
|
||||
|
||||
let mut result = SectionConfigData::new();
|
||||
|
||||
let mut pri = 1;
|
||||
let mut create_section = |section_id: &str, config| {
|
||||
result.set_data(section_id, config);
|
||||
result.set_order(section_id, pri);
|
||||
pri += 1;
|
||||
let mut create_section = |section_id: &str, type_name: &str, config| {
|
||||
result.set_data(section_id, type_name, config);
|
||||
result.record_order(section_id);
|
||||
};
|
||||
|
||||
for line in raw.lines() {
|
||||
line_no += 1;
|
||||
|
||||
if line.trim().is_empty() { continue; }
|
||||
|
||||
match state {
|
||||
|
||||
ParseState::BeforeHeader => {
|
||||
@ -128,7 +185,7 @@ impl SectionConfig {
|
||||
if let Err(err) = test_required_properties(config, &plugin.properties) {
|
||||
bail!("file '{}' line {} - {}", filename, line_no, err.to_string());
|
||||
}
|
||||
create_section(section_id, config.take());
|
||||
create_section(section_id, &plugin.type_name, config.take());
|
||||
state = ParseState::BeforeHeader;
|
||||
continue;
|
||||
}
|
||||
@ -163,15 +220,20 @@ impl SectionConfig {
|
||||
|
||||
if let ParseState::InsideSection(plugin, section_id, config) = state {
|
||||
// finish section
|
||||
|
||||
if let Err(err) = test_required_properties(&config, &plugin.properties) {
|
||||
bail!("file '{}' line {} - {}", filename, line_no, err.to_string());
|
||||
}
|
||||
create_section(§ion_id, config);
|
||||
create_section(§ion_id, &plugin.type_name, config);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn default_format_section_header(type_name: &str, section_id: &str, data: &Value) -> String {
|
||||
return format!("{}: {}\n", type_name, section_id);
|
||||
}
|
||||
|
||||
pub fn default_parse_section_content(line: &str) -> Option<(String, String)> {
|
||||
|
||||
if line.is_empty() { return None; }
|
||||
@ -258,9 +320,15 @@ lvmthin: local-lvm
|
||||
thinpool data
|
||||
vgname pve5
|
||||
content rootdir,images
|
||||
|
||||
lvmthin: local-lvm2
|
||||
thinpool data
|
||||
vgname pve5
|
||||
content rootdir,images
|
||||
";
|
||||
|
||||
let res = config.parse(filename, &raw);
|
||||
println!("RES: {:?}", res);
|
||||
config.write(filename, &res.unwrap());
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user