PIAOZYFBE5EILPMFZT5H7CZ6WODTTZ2DBSL4KIWGPE2Z5I6QXR7QC
let mut it = s.lines().filter(|i| !i.trim().is_empty()).peekable();
let i = it.peek()?;
let dcl = i.find(':')?;
// find out which type of dbtin dump we have here
if dcl != 0 && i[dcl + 1..].find(':').is_some() {
// (OBJ:KEY:VALUE)+
parse_colsv(it)
} else {
// :OBJ\n(KEY:VALUE)+
parse_groups(it)
}
}
fn parse_colsv<'a>(it: impl Iterator<Item = &'a str>) -> Option<Node<'a>> {
let mut ret = Node::Branch(HashMap::new());
for i in it {
let dcl1 = i.find(':')?;
if dcl1 == 0 {
// format error, this indicates a group instead
return None;
}
let kvp = &i[dcl1 + 1..];
let dcl2 = kvp.find(':')?;
let (obj, key, value) = (&i[..dcl1], &kvp[..dcl2], &kvp[dcl2 + 1..]);
let sel = ret.select(obj)?;
if !final_leaf_push(sel, key, value) {
return None;
}
}
Some(ret)
}
fn parse_groups<'a>(it: impl Iterator<Item = &'a str>) -> Option<Node<'a>> {
fn push_to_leaves(&mut self, obj: &'a str, kvm: HashMap<&'a str, &'a str>) -> bool {
let mut sel: &mut HashMap<&'a str, Node> = if let Node::Branch(ref mut b) = self {
b
fn branch_mut<'s>(&'s mut self) -> Option<&'s mut HashMap<&'a str, Node<'a>>> {
if let Node::Branch(ref mut x) = self {
Some(x)
for (key, value) in kvm {
use std::collections::hash_map::Entry;
match sel.entry(key) {
Entry::Occupied(_) => return false,
Entry::Vacant(vac) => vac.insert(Node::Leaf(value)),
};
}
fn select<'s>(&'s mut self, obj: &'a str) -> Option<&'s mut HashMap<&'a str, Node<'a>>> {
obj.split('/')
.filter(|i| !i.is_empty())
.try_fold(self.branch_mut()?, |sel, i| {
sel.entry(i)
.or_insert_with(|| Node::Branch(HashMap::new()))
.branch_mut()
})
}
Some(Node::Branch(inner1))
Some(ex0())
);
}
#[test]
fn ex0_colsv() {
assert_eq!(
parse(
r#"
Schule/Orga/Fach/ETH:trfull:Ethik
Schule/Orga/Fach/ETH:tanken:Ja
Schule/Orga/Fach/RUF:trfull:Rufen
Schule/Orga/Fach/RUF:tanken:Nein
Schule/Orga:locan :bl uüpp
"#
),
Some(ex0())