node: support a whole bunch of creation methods, get_first => get_child

This commit is contained in:
Matt Bilker
2018-09-19 03:15:54 +00:00
parent 91b00a489c
commit 1824da0237
3 changed files with 115 additions and 15 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "kbinxml"
version = "0.10.1"
version = "0.11.2"
authors = ["Matt Bilker <me@mbilker.us>"]
[dependencies]

View File

@@ -15,7 +15,7 @@ fn parse_index(s: &str) -> Option<usize> {
}
/// A collection of node definitions (`NodeDefinition`)
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct NodeCollection {
base: NodeDefinition,
attributes: VecDeque<NodeDefinition>,

View File

@@ -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<String, String> {
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<T: IntoIterator> {
inner: Option<T::IntoIter>,
}
#[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<K>(key: K) -> Self
where K: Into<String>
{
Self {
key,
key: key.into(),
attributes: None,
children: None,
value: None,
}
}
pub fn with_value(key: String, value: Value) -> Self {
pub fn with_attrs<K>(key: K, attrs: &[(&str, &str)]) -> Self
where K: Into<String>
{
Self {
key,
key: key.into(),
attributes: Some(convert_attributes(attrs)),
children: None,
value: None,
}
}
pub fn with_value<K>(key: K, value: Value) -> Self
where K: Into<String>
{
Self {
key: key.into(),
attributes: None,
children: None,
value: Some(value),
}
}
pub fn with_nodes<K, N>(key: K, nodes: N) -> Self
where K: Into<String>,
N: Into<Vec<Node>>
{
Self {
key: key.into(),
attributes: None,
children: Some(nodes.into()),
value: None,
}
}
pub fn with<K, N>(key: K, attrs: &[(&str, &str)], nodes: N) -> Self
where K: Into<String>,
N: Into<Vec<Node>>
{
Self {
key: key.into(),
attributes: Some(convert_attributes(attrs)),
children: Some(nodes.into()),
value: None,
}
}
pub fn with_attrs_value<K>(key: K, attrs: &[(&str, &str)], value: Value) -> Self
where K: Into<String>
{
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<Node>> {
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<T> OptionIterator<T>
where T: IntoIterator
{
pub fn new(inner: Option<T>) -> Self {
OptionIterator {
inner: inner.map(|inner| inner.into_iter()),
}
}
}
impl<T> Iterator for OptionIterator<T>
where T: IntoIterator
{
type Item = T::Item;
fn next(&mut self) -> Option<Self::Item> {
match self.inner {
Some(ref mut inner) => inner.next(),
None => None,
}
}
}