node: make attributes and children non-null

This commit is contained in:
Felix
2022-02-02 01:30:10 +00:00
parent 06ca05fd23
commit 78f7a9b93a
3 changed files with 96 additions and 180 deletions

View File

@@ -1,5 +1,4 @@
use std::fmt;
use std::iter::IntoIterator;
use std::mem;
use indexmap::IndexMap;
@@ -27,29 +26,22 @@ fn parse_index(s: &str) -> Option<usize> {
s.parse().ok()
}
pub struct OptionIterator<T: IntoIterator> {
inner: Option<T::IntoIter>,
}
#[derive(Clone, Default, PartialEq)]
pub struct Node {
key: String,
attributes: Option<IndexMap<String, String>>,
children: Option<Vec<Node>>,
attributes: IndexMap<String, String>,
children: Vec<Node>,
value: Option<Value>,
}
impl fmt::Debug for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut d = f.debug_struct("Node");
d.field("key", &self.key);
if let Some(ref attributes) = self.attributes {
d.field("attributes", attributes);
}
if let Some(ref children) = self.children {
d.field("children", children);
}
d.field("key", &self.key);
d.field("attributes", &self.attributes);
d.field("children", &self.children);
if let Some(ref value) = self.value {
d.field("value", value);
}
@@ -65,8 +57,8 @@ impl Node {
{
Self {
key: key.into(),
attributes: None,
children: None,
attributes: IndexMap::new(),
children: Vec::new(),
value: None,
}
}
@@ -77,8 +69,8 @@ impl Node {
{
Self {
key: key.into(),
attributes: Some(convert_attributes(attrs)),
children: None,
attributes: convert_attributes(attrs),
children: Vec::new(),
value: None,
}
}
@@ -89,8 +81,8 @@ impl Node {
{
Self {
key: key.into(),
attributes: None,
children: None,
attributes: IndexMap::new(),
children: Vec::new(),
value: Some(value),
}
}
@@ -102,8 +94,8 @@ impl Node {
{
Self {
key: key.into(),
attributes: None,
children: Some(nodes.into()),
attributes: IndexMap::new(),
children: nodes.into(),
value: None,
}
}
@@ -115,8 +107,8 @@ impl Node {
{
Self {
key: key.into(),
attributes: Some(convert_attributes(attrs)),
children: Some(nodes.into()),
attributes: convert_attributes(attrs),
children: nodes.into(),
value: None,
}
}
@@ -127,8 +119,8 @@ impl Node {
{
Self {
key: key.into(),
attributes: Some(convert_attributes(attrs)),
children: None,
attributes: convert_attributes(attrs),
children: Vec::new(),
value: Some(value),
}
}
@@ -139,23 +131,23 @@ impl Node {
}
#[inline]
pub fn attributes(&self) -> Option<&IndexMap<String, String>> {
self.attributes.as_ref()
pub fn attributes(&self) -> &IndexMap<String, String> {
&self.attributes
}
#[inline]
pub fn attributes_mut(&mut self) -> Option<&mut IndexMap<String, String>> {
self.attributes.as_mut()
pub fn attributes_mut(&mut self) -> &mut IndexMap<String, String> {
&mut self.attributes
}
#[inline]
pub fn children(&self) -> Option<&Vec<Node>> {
self.children.as_ref()
pub fn children(&self) -> &[Node] {
&self.children
}
#[inline]
pub fn children_mut(&mut self) -> Option<&mut Vec<Node>> {
self.children.as_mut()
pub fn children_mut(&mut self) -> &mut Vec<Node> {
&mut self.children
}
#[inline]
@@ -168,32 +160,20 @@ impl Node {
self.value.as_mut()
}
#[inline]
pub fn children_iter(&self) -> OptionIterator<&Vec<Node>> {
OptionIterator::new(self.children())
}
#[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))
self.attributes.get(key).map(String::as_str)
}
pub fn attr_mut(&mut self, key: &str) -> Option<&mut String> {
self.attributes_mut()
.and_then(|attributes| attributes.get_mut(key))
self.attributes.get_mut(key)
}
pub fn into_key_and_value(self) -> (String, Option<Value>) {
(self.key, self.value)
}
pub fn set_key(&mut self, key: String) {
self.key = key;
pub fn set_key<K: Into<String>>(&mut self, key: K) {
self.key = key.into();
}
pub fn set_attr<K, V>(&mut self, key: K, value: V) -> Option<String>
@@ -201,25 +181,19 @@ impl Node {
K: Into<String>,
V: Into<String>,
{
let attributes = self.attributes.get_or_insert_with(Default::default);
attributes.insert(key.into(), value.into())
self.attributes.insert(key.into(), value.into())
}
pub fn remove_attr(&mut self, key: &str) -> Option<String> {
self.attributes
.as_mut()
.and_then(|attributes| attributes.swap_remove(key))
self.attributes.swap_remove(key)
}
pub fn sort_attrs(&mut self) {
if let Some(ref mut attributes) = self.attributes {
attributes.sort_keys();
}
self.attributes.sort_keys();
}
pub fn append_child(&mut self, value: Node) {
let children = self.children.get_or_insert_with(Default::default);
children.push(value);
self.children.push(value);
}
pub fn set_value(&mut self, value: Option<Value>) -> Option<Value> {
@@ -227,11 +201,9 @@ impl 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;
}
for node in self.children.iter() {
if node.key == key {
return true;
}
}
@@ -239,11 +211,9 @@ impl Node {
}
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);
}
for node in self.children.iter() {
if node.key == key {
return Some(node);
}
}
@@ -251,11 +221,9 @@ impl 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);
}
for node in self.children.iter_mut() {
if node.key == key {
return Some(node);
}
}
@@ -263,27 +231,15 @@ impl Node {
}
pub fn remove_child(&mut self, key: &str) -> Option<Node> {
if let Some(ref mut children) = self.children {
let index = children
.iter()
.enumerate()
.find(|(_, child)| child.key() == key)
.map(|(index, _)| index);
let index = self.children.iter().position(|child| child.key() == key);
if let Some(index) = index {
return Some(children.remove(index));
}
if let Some(index) = index {
return Some(self.children.remove(index));
}
None
}
pub fn remove_child_at(&mut self, index: usize) -> Option<Node> {
self.children
.as_mut()
.map(|children| children.remove(index))
}
pub fn pointer<'a>(&'a self, pointer: &[&str]) -> Option<&'a Node> {
if pointer.is_empty() {
return Some(self);
@@ -291,15 +247,13 @@ impl Node {
let mut target = self;
for token in pointer {
let children = match target.children {
Some(ref v) => v,
None => return None,
};
let target_opt = if let Some(index) = parse_index(token) {
children.get(index)
target.children.get(index)
} else {
children.iter().find(|ref child| child.key() == *token)
target
.children
.iter()
.find(|ref child| child.key() == *token)
};
if let Some(t) = target_opt {
@@ -318,15 +272,13 @@ impl Node {
let mut target = self;
for token in pointer {
let children = match target.children {
Some(ref mut v) => v,
None => return None,
};
let target_opt = if let Some(index) = parse_index(token) {
children.get_mut(index)
target.children.get_mut(index)
} else {
children.iter_mut().find(|ref child| child.key() == *token)
target
.children
.iter_mut()
.find(|ref child| child.key() == *token)
};
if let Some(t) = target_opt {
@@ -338,28 +290,3 @@ impl Node {
Some(target)
}
}
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,
}
}
}

View File

@@ -51,15 +51,13 @@ impl ToTextXml for Node {
}
}
if let Some(attributes) = self.attributes() {
for (key, value) in attributes {
let value = BytesText::from_plain_str(&value);
for (key, value) in self.attributes() {
let value = BytesText::from_plain_str(&value);
elem.push_attribute(Attribute {
key: key.as_bytes(),
value: Cow::Borrowed(value.escaped()),
});
}
elem.push_attribute(Attribute {
key: key.as_bytes(),
value: Cow::Borrowed(value.escaped()),
});
}
// Now write the value contents.
@@ -76,10 +74,7 @@ impl ToTextXml for Node {
};
let has_value = start_elem.is_none();
let has_children = match self.children() {
Some(children) => !children.is_empty(),
None => false,
};
let has_children = !self.children().is_empty();
// A `Some` value here means the start element was not written
if let Some(start_elem) = start_elem {
@@ -90,10 +85,8 @@ impl ToTextXml for Node {
}
}
if let Some(children) = self.children() {
for child in children {
child.write(writer)?;
}
for child in self.children() {
child.write(writer)?;
}
if has_value || has_children {

View File

@@ -351,46 +351,42 @@ impl Writeable for Node {
write_value(options, data_buf, node_type, is_array, value)?;
}
if let Some(attributes) = self.attributes() {
for (key, value) in attributes {
trace!("Node write_node => attr: {}, value: {}", key, value);
for (key, value) in self.attributes() {
trace!("Node write_node => attr: {}, value: {}", key, value);
data_buf
.write_str(options.encoding, value)
.context(DataBuffer { node_type })?;
data_buf
.write_str(options.encoding, value)
.context(DataBuffer { node_type })?;
node_buf
.write_u8(StandardType::Attribute as u8)
.context(DataWrite {
node_type: StandardType::Attribute,
})?;
node_buf
.write_u8(StandardType::Attribute as u8)
.context(DataWrite {
node_type: StandardType::Attribute,
})?;
match options.compression {
CompressionType::Compressed => {
Sixbit::pack(&mut **node_buf, &key).context(NodeSixbitName)?
},
CompressionType::Uncompressed => {
let data = options.encoding.encode_bytes(&key).context(
NodeUncompressedNameEncode {
encoding: options.encoding,
},
)?;
let len = (data.len() - 1) as u8;
node_buf
.write_u8(len | ARRAY_MASK)
.context(NodeUncompressedNameLength)?;
node_buf
.write_all(&data)
.context(NodeUncompressedNameData)?;
},
};
}
match options.compression {
CompressionType::Compressed => {
Sixbit::pack(&mut **node_buf, &key).context(NodeSixbitName)?
},
CompressionType::Uncompressed => {
let data = options.encoding.encode_bytes(&key).context(
NodeUncompressedNameEncode {
encoding: options.encoding,
},
)?;
let len = (data.len() - 1) as u8;
node_buf
.write_u8(len | ARRAY_MASK)
.context(NodeUncompressedNameLength)?;
node_buf
.write_all(&data)
.context(NodeUncompressedNameData)?;
},
};
}
if let Some(children) = self.children() {
for child in children {
child.write_node(options, node_buf, data_buf)?;
}
for child in self.children() {
child.write_node(options, node_buf, data_buf)?;
}
// node end always has the array bit set