mirror of
https://github.com/mbilker/kbinxml-rs.git
synced 2026-09-09 02:55:30 -05:00
node: new container object ExtraNodes for storing extra struct nodes
This commit is contained in:
@@ -8,10 +8,36 @@ use node::Node;
|
||||
use node_types::StandardType;
|
||||
use value::Value;
|
||||
|
||||
struct NodeVisitor {
|
||||
pub(crate) struct NodeVisitor {
|
||||
key: Option<String>,
|
||||
}
|
||||
|
||||
impl<'de> NodeVisitor {
|
||||
pub(crate) fn map_to_node<A>(node_type: StandardType, key: &str, map: &mut A) -> Result<Node, A::Error>
|
||||
where A: MapAccess<'de>
|
||||
{
|
||||
match node_type {
|
||||
StandardType::Attribute => Err(A::Error::custom("`Attribute` nodes must be handled elsewhere")),
|
||||
StandardType::NodeStart => {
|
||||
let value = try!(map.next_value_seed(NodeValueSeed(key.to_owned())));
|
||||
debug!("NodeVisitor::map_to_node() => value: {:?}", value);
|
||||
|
||||
Ok(value)
|
||||
},
|
||||
// TODO: roll up `NodeStart` and everything else into a single map handler
|
||||
_ => {
|
||||
let value = try!(map.next_value());
|
||||
debug!("NodeVisitor::map_to_node() => value: {:?}", value);
|
||||
|
||||
let node = Node::new(key.to_owned(), Some(value));
|
||||
debug!("NodeVisitor::map_to_node() => node_type: {:?}, node: {:?}", node_type, node);
|
||||
|
||||
Ok(node)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for NodeVisitor {
|
||||
type Value = Node;
|
||||
|
||||
@@ -45,18 +71,9 @@ impl<'de> Visitor<'de> for NodeVisitor {
|
||||
return Err(A::Error::custom("`Attribute` node must have `Value::Attribute` value"));
|
||||
}
|
||||
},
|
||||
StandardType::NodeStart => {
|
||||
let value = map.next_value_seed(NodeValueSeed(key.clone()))?;
|
||||
debug!("NodeVisitor::visit_map() => value: {:?}", value);
|
||||
|
||||
nodes.insert(key, value);
|
||||
},
|
||||
_ => {
|
||||
let value = map.next_value();
|
||||
debug!("NodeVisitor::visit_map() => value: {:?}", value);
|
||||
|
||||
let node = Node::new(key.clone(), Some(try!(value)));
|
||||
debug!("NodeVisitor::visit_map() => node_type: {:?}, node: {:?}", node_type, node);
|
||||
let node = NodeVisitor::map_to_node(node_type, &key, &mut map)?;
|
||||
debug!("NodeVisitor::visit_map() => node: {:?}", node);
|
||||
|
||||
if !nodes.contains_key(&key) {
|
||||
nodes.insert(key, node);
|
||||
@@ -113,12 +130,12 @@ impl<'de> DeserializeSeed<'de> for NodeValueSeed {
|
||||
/// Node classifier that gets the key name and the type of the node before the
|
||||
/// main `Node` object handles getting the value based on the type and the
|
||||
/// attributes.
|
||||
struct NodeSeed;
|
||||
pub(crate) struct NodeSeed;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NodeStart {
|
||||
key: String,
|
||||
node_type: StandardType,
|
||||
pub(crate) struct NodeStart {
|
||||
pub(crate) key: String,
|
||||
pub(crate) node_type: StandardType,
|
||||
}
|
||||
|
||||
impl<'de> DeserializeSeed<'de> for NodeSeed {
|
||||
|
||||
60
src/node/extra/de.rs
Normal file
60
src/node/extra/de.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use std::fmt;
|
||||
|
||||
use serde::de::{self, Deserialize, Error, MapAccess, Visitor};
|
||||
|
||||
use node::ExtraNodes;
|
||||
use node::de::{NodeSeed, NodeStart, NodeVisitor};
|
||||
use node_types::StandardType;
|
||||
use value::Value;
|
||||
|
||||
impl<'de> Deserialize<'de> for ExtraNodes {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: de::Deserializer<'de>
|
||||
{
|
||||
struct ExtraNodesVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ExtraNodesVisitor {
|
||||
type Value = ExtraNodes;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("any valid map of kbin nodes")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where A: MapAccess<'de>
|
||||
{
|
||||
trace!("ExtraNodesVisitor::visit_map()");
|
||||
|
||||
let mut extra = ExtraNodes::new();
|
||||
|
||||
while let Some(NodeStart { key, node_type }) = try!(map.next_key_seed(NodeSeed)) {
|
||||
debug!("ExtraNodesVisitor::visit_map() => key: {:?}, node_type: {:?}", key, node_type);
|
||||
|
||||
match node_type {
|
||||
StandardType::Attribute => {
|
||||
let value = try!(map.next_value());
|
||||
debug!("ExtraNodesVisitor::visit_map() => value: {:?}", value);
|
||||
|
||||
if let Value::Attribute(s) = value {
|
||||
let key = String::from(&key["attr_".len()..]);
|
||||
extra.attributes.insert(key, s);
|
||||
} else {
|
||||
return Err(A::Error::custom("`Attribute` node must have `Value::Attribute` value"));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let node = NodeVisitor::map_to_node(node_type, &key, &mut map)?;
|
||||
debug!("ExtraNodesVisitor::visit_map() => node: {:?}", node);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Ok(extra)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(ExtraNodesVisitor)
|
||||
}
|
||||
}
|
||||
41
src/node/extra/mod.rs
Normal file
41
src/node/extra/mod.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use node::Node;
|
||||
|
||||
mod de;
|
||||
mod ser;
|
||||
|
||||
/// Container for extra `Node` and `Attribute` objects that are not part of a
|
||||
/// parent object
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct ExtraNodes {
|
||||
attributes: IndexMap<String, String>,
|
||||
nodes: IndexMap<String, Node>,
|
||||
}
|
||||
|
||||
impl ExtraNodes {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
attributes: IndexMap::new(),
|
||||
nodes: IndexMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn attributes(&self) -> &IndexMap<String, String> {
|
||||
&self.attributes
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn nodes(&self) -> &IndexMap<String, Node> {
|
||||
&self.nodes
|
||||
}
|
||||
|
||||
pub fn set_attr(&mut self, key: String, value: String) -> Option<String> {
|
||||
self.attributes.insert(key, value)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: String, value: Node) -> Option<Node> {
|
||||
self.nodes.insert(key, value)
|
||||
}
|
||||
}
|
||||
24
src/node/extra/ser.rs
Normal file
24
src/node/extra/ser.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use serde::ser::{Serialize, SerializeMap};
|
||||
|
||||
use node::ExtraNodes;
|
||||
|
||||
impl Serialize for ExtraNodes {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: ::serde::Serializer
|
||||
{
|
||||
trace!("<ExtraNodes as Serialize>::serialize()");
|
||||
|
||||
let len = self.attributes.len() + self.nodes.len();
|
||||
let mut map = serializer.serialize_map(Some(len))?;
|
||||
|
||||
for (k, v) in &self.attributes {
|
||||
map.serialize_entry(k, v)?;
|
||||
}
|
||||
for (k, v) in &self.nodes {
|
||||
map.serialize_entry(k, v)?;
|
||||
}
|
||||
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,12 @@ use indexmap::IndexMap;
|
||||
use value::Value;
|
||||
|
||||
mod de;
|
||||
mod extra;
|
||||
mod ser;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub use self::extra::ExtraNodes;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct Node {
|
||||
key: String,
|
||||
attributes: Option<IndexMap<String, String>>,
|
||||
@@ -23,11 +26,26 @@ impl Node {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn key(&self) -> &str {
|
||||
&self.key
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn attributes(&self) -> Option<&IndexMap<String, String>> {
|
||||
self.attributes.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn children(&self) -> Option<&IndexMap<String, Node>> {
|
||||
self.children.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn value(&self) -> Option<&Value> {
|
||||
self.value.as_ref()
|
||||
}
|
||||
|
||||
pub fn set_attr(&mut self, key: String, value: String) -> Option<String> {
|
||||
let attributes = self.attributes.get_or_insert_with(Default::default);
|
||||
attributes.insert(key, value)
|
||||
|
||||
Reference in New Issue
Block a user