diff --git a/src/lib.rs b/src/lib.rs index ffa1ccc..ddf96b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,6 @@ mod error; mod ip4; mod kbin_wrapper; mod node; -mod node_definition; mod node_types; mod options; mod printer; diff --git a/src/node/collection.rs b/src/node/collection.rs new file mode 100644 index 0000000..dd09213 --- /dev/null +++ b/src/node/collection.rs @@ -0,0 +1,55 @@ +use std::iter::Iterator; + +use node::NodeDefinition; +use node_types::StandardType; + +/// A collection of node definitions (`NodeDefinition`) +#[derive(Debug)] +pub struct NodeCollection<'buf> { + base: NodeDefinition<'buf>, + attributes: Vec>, + children: Vec>, +} + +impl<'buf> NodeCollection<'buf> { + pub fn from_iter(mut iter: I) -> Option> + where I: Iterator> + { + let base = if let Some(def) = iter.next() { + def + } else { + return None; + }; + + NodeCollection::with_base(base, &mut iter) + } + + fn with_base(base: NodeDefinition<'buf>, iter: &mut I) -> Option> + where I: Iterator> + { + let mut attributes = Vec::new(); + let mut children = Vec::new(); + + loop { + if let Some(def) = iter.next() { + match def.node_type { + StandardType::Attribute => attributes.push(def), + StandardType::NodeEnd | + StandardType::FileEnd => break, + _ => match NodeCollection::with_base(def, iter) { + Some(child) => children.push(child), + None => return None, + }, + } + } else { + break; + } + } + + Some(NodeCollection { + base, + attributes, + children, + }) + } +} diff --git a/src/node_definition.rs b/src/node/definition.rs similarity index 95% rename from src/node_definition.rs rename to src/node/definition.rs index 8395594..0ec9840 100644 --- a/src/node_definition.rs +++ b/src/node/definition.rs @@ -85,11 +85,14 @@ impl<'buf> NodeDefinition<'buf> { pub fn into_node(self) -> Result { trace!("parsing definition: {:?}", self); match (self.node_type, self.data) { - (StandardType::NodeStart, _) | (StandardType::NodeEnd, _) | (StandardType::FileEnd, _) => { return Err(KbinErrorKind::InvalidNodeType(self.node_type).into()); }, + (StandardType::NodeStart, NodeData::Some { key, .. }) => { + let key = key.to_string()?; + Ok(Node::new(key)) + }, (StandardType::Attribute, NodeData::Some { key, value_data }) => { let key = key.to_string()?; let data = strip_trailing_null_bytes(value_data); diff --git a/src/node/mod.rs b/src/node/mod.rs index 7b18649..88245cc 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -4,11 +4,15 @@ use indexmap::IndexMap; use value::Value; +mod collection; pub(crate) mod de; +mod definition; mod extra; mod marshal; mod ser; +pub use self::collection::NodeCollection; +pub use self::definition::{Key, NodeData, NodeDefinition}; pub use self::extra::ExtraNodes; pub use self::marshal::Marshal; diff --git a/src/reader.rs b/src/reader.rs index 08a4478..45b4042 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -7,7 +7,7 @@ use byte_buffer::ByteBufferRead; use compression::Compression; use encoding_type::EncodingType; use error::{KbinErrorKind, Result}; -use node_definition::{Key, NodeData, NodeDefinition}; +use node::{Key, NodeData, NodeDefinition}; use node_types::StandardType; use sixbit::Sixbit;