use std::collections::HashMap;
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();
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 + 1..].trim_start()]);
}
}
}
it.next();
}
let mut section = None;
for i in it {
if let Some(j) = i.strip_prefix('%') {
if let Some((key, value)) = section.take() {
ret.insert(key, value);
}
section = Some((j.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);
}
for (from, to) in trtab {
if ret.contains_key(to) {
continue;
}
if let Some(x) = ret.remove(from) {
ret.insert(to, x);
}
}
ret.values_mut().for_each(|val| {
while let Some(x) = val.pop() {
if !x.trim().is_empty() {
val.push(x);
break;
}
}
});
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
);
}
}