From 91b00a489c482d24eb711ac3176b12d27c544e52 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Sat, 15 Sep 2018 05:18:36 +0000 Subject: [PATCH] value: add function to convert an array of values to bytes --- src/node/collection.rs | 40 ++++++++++++++++ src/node/mod.rs | 104 +++++++++++++++++++++++++++++------------ src/value/mod.rs | 31 ++++++++---- 3 files changed, 135 insertions(+), 40 deletions(-) diff --git a/src/node/collection.rs b/src/node/collection.rs index 507e4bb..e889b0d 100644 --- a/src/node/collection.rs +++ b/src/node/collection.rs @@ -7,6 +7,13 @@ use node::{Node, NodeDefinition}; use node_types::StandardType; use value::Value; +fn parse_index(s: &str) -> Option { + if s.starts_with('+') || (s.starts_with('0') && s.len() != 1) { + return None; + } + s.parse().ok() +} + /// A collection of node definitions (`NodeDefinition`) #[derive(Debug)] pub struct NodeCollection { @@ -109,6 +116,39 @@ impl NodeCollection { Ok(node) } + + pub fn pointer<'a>(&'a self, pointer: &str) -> Option<&'a NodeCollection> { + if pointer == "" { + return Some(self); + } + if !pointer.starts_with('/') { + return None; + } + let tokens = pointer + .split('/') + .skip(1) + .map(|x| x.replace("~1", "/").replace("~0", "~")); + let mut target = self; + + for token in tokens { + let target_opt = if let Some(index) = parse_index(&token) { + eprintln!("index: {}", index); + target.children().get(index) + } else { + eprintln!("token: {:?}", token); + target.children().iter().find(|ref child| { + child.base().key().ok().and_then(|x| x).expect("key not parseable") == token + }) + }; + + if let Some(t) = target_opt { + target = t; + } else { + return None; + } + } + Some(target) + } } struct DisplayDebugWrapper<'a, T: fmt::Display + 'a>(&'a T, bool); diff --git a/src/node/mod.rs b/src/node/mod.rs index a9715bc..2511837 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -17,6 +17,35 @@ pub use self::definition::{Key, NodeData, NodeDefinition}; pub use self::extra::ExtraNodes; pub use self::marshal::{Marshal, MarshalDeserializer}; +/* +match children.entry(key) { + Entry::Occupied(mut entry) => { + match entry.get_mut() { + child @ Child::Single(_) => { + let old = mem::replace(child, Child::Multiple(Vec::with_capacity(2))); + let node = match old { + Child::Single(node) => node, + Child::Multiple(_) => panic!("`old` was `Child::Multiple` after checking"), + }; + match child { + Child::Multiple(ref mut nodes) => { + nodes.push(node); + nodes.push(value); + }, + _ => panic!("Invalid result of node swap"), + }; + }, + Child::Multiple(ref mut nodes) => { + nodes.push(value); + }, + }; + }, + Entry::Vacant(entry) => { + entry.insert(Child::Single(value)); + }, +}; +*/ + #[derive(Clone, Default, PartialEq)] pub struct Node { key: String, @@ -78,11 +107,22 @@ impl Node { self.children.as_ref() } + #[inline] + pub fn children_mut(&mut self) -> Option<&mut Vec> { + self.children.as_mut() + } + #[inline] pub fn value(&self) -> Option<&Value> { self.value.as_ref() } + pub fn attr(&self, key: &str) -> Option<&str> { + self.attributes().and_then(|attributes| { + attributes.get(key).map(String::as_str) + }) + } + pub fn into_key_and_value(self) -> (String, Option) { (self.key, self.value) } @@ -91,46 +131,48 @@ impl Node { self.key = key; } - pub fn set_attr(&mut self, key: String, value: String) -> Option { + pub fn set_attr(&mut self, key: K, value: V) -> Option + where K: Into, + V: Into + { let attributes = self.attributes.get_or_insert_with(Default::default); - attributes.insert(key, value) + attributes.insert(key.into(), value.into()) } pub fn append_child(&mut self, value: Node) { let children = self.children.get_or_insert_with(Default::default); children.push(value); - - /* - match children.entry(key) { - Entry::Occupied(mut entry) => { - match entry.get_mut() { - child @ Child::Single(_) => { - let old = mem::replace(child, Child::Multiple(Vec::with_capacity(2))); - let node = match old { - Child::Single(node) => node, - Child::Multiple(_) => panic!("`old` was `Child::Multiple` after checking"), - }; - match child { - Child::Multiple(ref mut nodes) => { - nodes.push(node); - nodes.push(value); - }, - _ => panic!("Invalid result of node swap"), - }; - }, - Child::Multiple(ref mut nodes) => { - nodes.push(value); - }, - }; - }, - Entry::Vacant(entry) => { - entry.insert(Child::Single(value)); - }, - }; - */ } pub fn set_value(&mut self, value: Option) -> Option { mem::replace(&mut self.value, value) } + + pub fn get_first(&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 + } + } + + pub fn get_first_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 + } + } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 80db0e3..5d6462f 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -440,6 +440,11 @@ macro_rules! construct_types { self.to_bytes_inner(output) } + #[inline] + pub fn array_as_string(values: &[Value]) -> String { + BorrowedValueArray(values).to_string() + } + pub fn standard_type(&self) -> StandardType { match *self { $( @@ -564,6 +569,22 @@ impl fmt::Debug for Value { } } +/// A separate wrapper struct so `Value::Array` can be formatted by +/// `` and `Value::array_as_string` +struct BorrowedValueArray<'a>(&'a [Value]); + +impl<'a> fmt::Display for BorrowedValueArray<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for (i, v) in self.0.iter().enumerate() { + if i > 0 { + f.write_str(" ")?; + } + fmt::Display::fmt(v, f)?; + } + Ok(()) + } +} + impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { macro_rules! display_value { @@ -612,15 +633,7 @@ impl fmt::Display for Value { true => f.write_str("1"), false => f.write_str("0"), }, - Value::Array(_, values) => { - for (i, v) in values.iter().enumerate() { - if i > 0 { - f.write_str(" ")?; - } - fmt::Display::fmt(v, f)?; - } - Ok(()) - }, + Value::Array(_, values) => BorrowedValueArray(&values).fmt(f), Value::Node(_) => Ok(()), } };