use std::collections::HashMap;
// this implementation merges the header and the sections
pub fn parse<'a>(s: &'a str, trtab: &HashMap<&'a str, &'a str>) -> HashMap<&'a str, Vec<&'a str>> {
let mut ret = HashMap::new();
let mut it = s.lines().peekable();
// parse header
// KEY: VALUE
while let Some(x) = it.peek() {
if !x.trim().is_empty() {
if x.starts_with('%') {
break;
}
if let Some(p) = x.find(": ") {
if p != 0 {
ret.insert(&x[..p], vec![x[p+2..].trim_start()]);
}
}
// else: regard it as comment
}
it.next();
}
// parse sections
// %KEY\nVALUE...
let mut section = None;
for i in it {
if i.starts_with('%') {
if let Some((key, value)) = section.take() {
ret.insert(key, value);
}
section = Some((&i[1..].trim_end(), Vec::new()));
} else if let Some((_, value)) = &mut section {
value.push(i);
} else {
unreachable!();
}
}
if let Some((key, value)) = section {
ret.insert(key, value);
}
// perform translation substitution, e.g. cleanup keys
for (from, to) in trtab {
if ret.contains_key(to) {
// don't do conflict handling for now
continue;
}
if let Some(x) = ret.remove(from) {
// move element
ret.insert(to, x);
}
}
// cleanup values
for val in ret.values_mut() {
while val.last().map(|i| i.trim().is_empty()) == Some(true) {
val.pop();
}
val.shrink_to_fit();
}
return ret;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ex0() {
let mut trtab = HashMap::new();
trtab.insert("Kategorie", "Category");
trtab.insert("Zutaten", "Ingredients");
trtab.insert("Zubereitung", "Making");
trtab.insert("Bemerkungen", "Remarks");
trtab.insert("Quellen", "Sources");
let mut res = HashMap::new();
res.insert("Name", vec!["Fränkische Kohlsuppe"]);
res.insert("Kategorie", vec!["Nullprodukt"]);
res.insert("Category", vec!["nully..."]);
res.insert("Ingredients", vec!["Salz"]);
res.insert("Making", vec!["Mit Wasser abschmecken", " - oder so... "]);
res.insert("Remarks", vec!["was soll das?"]);
res.insert("Sources", vec!["keine"]);
assert_eq!(parse(r#"
Name: Fränkische Kohlsuppe
Kategorie: Nullprodukt
Das ist nur ein Kommentar, kein Doppelpunkt...
: Das auch: ...
Category: nully...
%Zutaten
Salz
%Zubereitung
Mit Wasser abschmecken
- oder so...
%Bemerkungen
was soll das?
%Quellen
keine
"#, &trtab), res);
}
}