From 1824da0237d41d2479fb5a45939fd4c623237d79 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Wed, 19 Sep 2018 03:15:54 +0000 Subject: [PATCH] node: support a whole bunch of creation methods, get_first => get_child --- Cargo.toml | 2 +- src/node/collection.rs | 2 +- src/node/mod.rs | 126 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 115 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed0132f..3131a73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kbinxml" -version = "0.10.1" +version = "0.11.2" authors = ["Matt Bilker "] [dependencies] diff --git a/src/node/collection.rs b/src/node/collection.rs index e889b0d..4951f71 100644 --- a/src/node/collection.rs +++ b/src/node/collection.rs @@ -15,7 +15,7 @@ fn parse_index(s: &str) -> Option { } /// A collection of node definitions (`NodeDefinition`) -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct NodeCollection { base: NodeDefinition, attributes: VecDeque, diff --git a/src/node/mod.rs b/src/node/mod.rs index 2511837..d68a118 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::iter::IntoIterator; use std::mem; use indexmap::IndexMap; @@ -46,6 +47,19 @@ match children.entry(key) { }; */ +// The attributes argument is very hard to generalize +fn convert_attributes(attrs: &[(&str, &str)]) -> IndexMap { + let mut attributes = IndexMap::with_capacity(attrs.len()); + for (key, value) in attrs.iter() { + attributes.insert(String::from(*key), String::from(*value)); + } + attributes +} + +pub struct OptionIterator { + inner: Option, +} + #[derive(Clone, Default, PartialEq)] pub struct Node { key: String, @@ -74,24 +88,74 @@ impl fmt::Debug for Node { } impl Node { - pub fn new(key: String) -> Self { + pub fn new(key: K) -> Self + where K: Into + { Self { - key, + key: key.into(), attributes: None, children: None, value: None, } } - pub fn with_value(key: String, value: Value) -> Self { + pub fn with_attrs(key: K, attrs: &[(&str, &str)]) -> Self + where K: Into + { Self { - key, + key: key.into(), + attributes: Some(convert_attributes(attrs)), + children: None, + value: None, + } + } + + pub fn with_value(key: K, value: Value) -> Self + where K: Into + { + Self { + key: key.into(), attributes: None, children: None, value: Some(value), } } + pub fn with_nodes(key: K, nodes: N) -> Self + where K: Into, + N: Into> + { + Self { + key: key.into(), + attributes: None, + children: Some(nodes.into()), + value: None, + } + } + + pub fn with(key: K, attrs: &[(&str, &str)], nodes: N) -> Self + where K: Into, + N: Into> + { + Self { + key: key.into(), + attributes: Some(convert_attributes(attrs)), + children: Some(nodes.into()), + value: None, + } + } + + pub fn with_attrs_value(key: K, attrs: &[(&str, &str)], value: Value) -> Self + where K: Into + { + Self { + key: key.into(), + attributes: Some(convert_attributes(attrs)), + children: None, + value: Some(value), + } + } + #[inline] pub fn key(&self) -> &str { &self.key @@ -117,6 +181,11 @@ impl Node { self.value.as_ref() } + #[inline] + pub fn children_iter_mut(&mut self) -> OptionIterator<&mut Vec> { + OptionIterator::new(self.children_mut()) + } + pub fn attr(&self, key: &str) -> Option<&str> { self.attributes().and_then(|attributes| { attributes.get(key).map(String::as_str) @@ -148,31 +217,62 @@ impl Node { mem::replace(&mut self.value, value) } - pub fn get_first(&self, key: &str) -> Option<&Node> { + pub fn has(&self, key: &str) -> bool { + if let Some(ref children) = self.children { + for node in children { + if node.key == key { + return true; + } + } + } + + false + } + + pub fn get_child(&self, key: &str) -> Option<&Node> { if let Some(ref children) = self.children { for node in children { if node.key == key { return Some(node); } } - - None - } else { - None } + + None } - pub fn get_first_mut(&mut self, key: &str) -> Option<&mut Node> { + pub fn get_child_mut(&mut self, key: &str) -> Option<&mut Node> { if let Some(ref mut children) = self.children { for node in children { if node.key == key { return Some(node); } } + } - None - } else { - None + None + } +} + +impl OptionIterator + where T: IntoIterator +{ + pub fn new(inner: Option) -> Self { + OptionIterator { + inner: inner.map(|inner| inner.into_iter()), + } + } +} + +impl Iterator for OptionIterator + where T: IntoIterator +{ + type Item = T::Item; + + fn next(&mut self) -> Option { + match self.inner { + Some(ref mut inner) => inner.next(), + None => None, } } }