dbtin: add parser for double-colon-separated format (similar to the passwd format)

fogti
Aug 26, 2021, 5:39 PM
PIAOZYFBE5EILPMFZT5H7CZ6WODTTZ2DBSL4KIWGPE2Z5I6QXR7QC

Dependencies

Change contents

  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 15
    [2.2308]
    [2.2308]
    ```
    or alternatively:
    ```text
    PATH/TO/OBJECT:KEY1:VALUE1
    PATH/TO/OBJECT:KEY2:VALUE2
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 26
    [2.2361]
    [2.2361]
    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>> {
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 74
    [2.2681][2.2681:2772]()
    for i in s.lines() {
    if i.trim().is_empty() {
    continue;
    }
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 75
    [2.2773]
    [2.2773]
    for i in it {
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 92
    [2.3187]
    [2.3187]
    }
    fn final_leaf_push<'a>(sel: &mut HashMap<&'a str, Node<'a>>, key: &'a str, value: &'a str) -> bool {
    use std::collections::hash_map::Entry;
    match sel.entry(key) {
    Entry::Occupied(_) => return false,
    Entry::Vacant(vac) => vac.insert(Node::Leaf(value)),
    };
    true
  • replacement in crates/zhed-misc-parsers/src/dbtin.rs at line 104
    [2.3210][2.3210:3404]()
    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
    [2.3210]
    [2.3404]
    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)
  • replacement in crates/zhed-misc-parsers/src/dbtin.rs at line 108
    [2.3421][2.3421:3746]()
    return false;
    };
    for i in obj.split('/').filter(|i| !i.is_empty()) {
    if let Node::Branch(ref mut x) =
    sel.entry(i).or_insert_with(|| Node::Branch(HashMap::new()))
    {
    sel = x;
    } else {
    return false;
    };
    [2.3421]
    [2.3746]
    None
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 110
    [2.3756]
    [2.3756]
    }
  • replacement in crates/zhed-misc-parsers/src/dbtin.rs at line 112
    [2.3757][2.3757:4023]()
    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)),
    };
    }
    [2.3757]
    [2.4023]
    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()
    })
    }
  • replacement in crates/zhed-misc-parsers/src/dbtin.rs at line 122
    [2.4024][2.4024:4037]()
    true
    [2.4024]
    [2.4037]
    fn push_to_leaves(&mut self, obj: &'a str, kvm: HashMap<&'a str, &'a str>) -> bool {
    if let Some(sel) = self.select(obj) {
    kvm.into_iter()
    .all(|(key, value)| final_leaf_push(sel, key, value))
    } else {
    false
    }
  • replacement in crates/zhed-misc-parsers/src/dbtin.rs at line 135
    [2.4089][2.4089:4118]()
    #[test]
    fn ex_ok() {
    [2.4089]
    [2.4118]
    fn ex0() -> Node<'static> {
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 158
    [2.4905]
    [2.4905]
    Node::Branch(inner1)
    }
  • edit in crates/zhed-misc-parsers/src/dbtin.rs at line 162
    [2.4906]
    [2.4906]
    #[test]
    fn ex0_groups() {
  • replacement in crates/zhed-misc-parsers/src/dbtin.rs at line 177
    [2.5112][2.5112:5151]()
    Some(Node::Branch(inner1))
    [2.5112]
    [2.5151]
    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())