diff --git a/src/lib.rs b/src/lib.rs index 719f036..9faf589 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,14 +80,7 @@ fn read_node(reader: &mut Reader, def: NodeDefinition) -> Result { debug!("KbinXml::read_node(name: {}) => string value: {:?}", elem.name(), value); elem.append_text_node(value); }, - Value::Array(node_type, values) => { - elem.set_attr("__count", values.len()); - - let value = Value::Array(node_type, values).to_string(); - debug!("KbinXml::read_node(name: {}) => value: {:?}", elem.name(), value); - elem.append_text_node(value); - }, - Value::ArrayNew(values) => { + Value::Array(values) => { elem.set_attr("__count", values.len()); let value = values.to_string(); diff --git a/src/to_element/node.rs b/src/to_element/node.rs index d194fff..9296fc3 100644 --- a/src/to_element/node.rs +++ b/src/to_element/node.rs @@ -27,13 +27,7 @@ impl ToElement for Node { Value::String(value) => { elem.append_text_node(value.as_str()); }, - Value::Array(_, values) => { - elem.set_attr("__count", values.len()); - - let value = Value::array_as_string(values); - elem.append_text_node(value); - }, - Value::ArrayNew(values) => { + Value::Array(values) => { elem.set_attr("__count", values.len()); let value = value.to_string(); diff --git a/src/to_text_xml/node.rs b/src/to_text_xml/node.rs index 4f48736..8e190f8 100644 --- a/src/to_text_xml/node.rs +++ b/src/to_text_xml/node.rs @@ -33,13 +33,7 @@ impl ToTextXml for Node { value: Cow::Owned(data.len().to_string().into_bytes()), }); }, - Value::Array(_, ref values) => { - elem.push_attribute(Attribute { - key: b"__count", - value: Cow::Owned(values.len().to_string().into_bytes()), - }); - }, - Value::ArrayNew(ref values) => { + Value::Array(ref values) => { elem.push_attribute(Attribute { key: b"__count", value: Cow::Owned(values.len().to_string().into_bytes()), diff --git a/src/types/string.rs b/src/types/string.rs index 01a4488..80a4e80 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -5,12 +5,6 @@ use failure::{Fail, ResultExt}; use crate::error::{KbinError, KbinErrorKind}; -/* -pub trait IntoKbinString { - fn write_kbin_string(self, output: &mut String); -} -*/ - pub trait FromKbinString: Sized { fn from_kbin_string(input: &str) -> Result; } diff --git a/src/value/array.rs b/src/value/array.rs index d376664..e7adeb2 100644 --- a/src/value/array.rs +++ b/src/value/array.rs @@ -9,6 +9,7 @@ use std::net::Ipv4Addr; use crate::error::{KbinError, KbinErrorKind}; use crate::node_types::StandardType; use crate::types::{FromKbinBytes, IntoKbinBytes}; +use crate::types::FromKbinString; #[derive(Clone, Debug, PartialEq)] pub enum ValueArray { @@ -103,7 +104,56 @@ macro_rules! type_impl { Ok(Some(value)) } - pub(super) fn to_bytes_inner(&self, output: &mut Vec) -> Result<(), KbinError> { + pub(super) fn from_string(node_type: StandardType, count: usize, input: &str, arr_count: usize) -> Result { + trace!("from_string(count: {}, input: {:?}, arr_count: {})", count, input, arr_count); + + // counter of the number of space characters encountered + let mut i = 0; + + let iter = input.split(|c| { + if c == ' ' { + // increment ths space counter + i += 1; + + // if the space counter is equal to count, then split + let res = i == count; + + // if splitting, then reset the counter + if res { + i = 0; + } + + res + } else { + false + } + }); + + let value = match node_type { + StandardType::NodeStart | + StandardType::NodeEnd | + StandardType::FileEnd | + StandardType::Attribute | + StandardType::Binary | + StandardType::String | + StandardType::Time => return Err(KbinErrorKind::InvalidState.into()), + $( + StandardType::$konst => { + let mut values = Vec::new(); + + for part in iter { + values.push(FromKbinString::from_kbin_string(part)?); + } + + ValueArray::$konst(values) + }, + )* + }; + + Ok(value) + } + + pub fn to_bytes_into(&self, output: &mut Vec) -> Result<(), KbinError> { let node_size = self.standard_type().size; match self { diff --git a/src/value/mod.rs b/src/value/mod.rs index 8f48460..2afacdc 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -14,38 +14,6 @@ mod array; pub use self::array::ValueArray; -fn to_array(node_type: StandardType, count: usize, input: &str, arr_count: usize) -> Result { - let mut i = 0; - trace!("to_array(count: {}, input: {:?}, arr_count: {})", count, input, arr_count); - let iter = input.split(|c| { - if c == ' ' { - // Increment the space counter - i += 1; - - // If the space counter is equal to count, then split - let res = i == count; - - // If splitting, reset the counter - if res { - i = 0; - } - - res - } else { - false - } - }); - - let mut values = Vec::new(); - - for part in iter { - trace!("part: {:?}", part); - values.push(Value::from_string(node_type, part, false, 1)?); - } - - Ok(Value::Array(node_type, values)) -} - macro_rules! construct_types { ( $( @@ -61,8 +29,7 @@ macro_rules! construct_types { Time(u32), Attribute(String), - Array(StandardType, Vec), - ArrayNew(ValueArray), + Array(ValueArray), } $( @@ -104,8 +71,7 @@ macro_rules! construct_types { Value::Binary(_) => StandardType::Binary, Value::Time(_) => StandardType::Time, Value::Attribute(_) => StandardType::Attribute, - Value::Array(node_type, _) => node_type, - Value::ArrayNew(ref value) => value.standard_type(), + Value::Array(ref value) => value.standard_type(), } } } @@ -126,7 +92,7 @@ macro_rules! tuple { }; debug!("Value::from_standard_type({:?}) input: 0x{:02x?} => {:?}", node_type, input, value); - return Ok(Some(Value::ArrayNew(value))); + return Ok(Some(Value::Array(value))); } match node_type { @@ -173,19 +139,12 @@ macro_rules! tuple { } pub fn from_string(node_type: StandardType, input: &str, is_array: bool, arr_count: usize) -> Result { + trace!("Value::from_string({:?}, is_array: {}, arr_count: {}) => input: {:?}", node_type, is_array, arr_count, input); + if is_array { let value = match node_type.count { - 1 => { - // May have a node (i.e. `Ip4`) that is only a single count, but it - // can be part of an array - match arr_count { - 0 => return Err(KbinErrorKind::InvalidState.into()), - 1 => Value::from_string(node_type, input, false, arr_count)?, - _ => to_array(node_type, node_type.count, input, arr_count)?, - } - }, - count if count > 1 => to_array(node_type, count, input, arr_count)?, - _ => return Err(KbinErrorKind::InvalidState.into()), + 0 => return Err(KbinErrorKind::InvalidState.into()), + count => Value::Array(ValueArray::from_string(node_type, count, input, arr_count)?), }; debug!("Value::from_string({:?}) input: {:?} => {:?}", node_type, input, value); @@ -193,6 +152,9 @@ macro_rules! tuple { } let value = match node_type { + StandardType::NodeStart | + StandardType::NodeEnd | + StandardType::FileEnd => return Err(KbinErrorKind::InvalidNodeType(node_type).into()), StandardType::S8 => i8::from_kbin_string(input).map(Value::S8)?, StandardType::U8 => u8::from_kbin_string(input).map(Value::U8)?, StandardType::S16 => i16::from_kbin_string(input).map(Value::S16)?, @@ -212,9 +174,6 @@ macro_rules! tuple { StandardType::Float => f32::from_kbin_string(input).map(Value::Float)?, StandardType::Double => f64::from_kbin_string(input).map(Value::Double)?, StandardType::Boolean => bool::from_kbin_string(input).map(Value::Boolean)?, - StandardType::NodeEnd | - StandardType::FileEnd | - StandardType::NodeStart => return Err(KbinErrorKind::InvalidNodeType(node_type).into()), $( StandardType::$konst => FromKbinString::from_kbin_string(input).map(Value::$konst)?, )* @@ -242,12 +201,7 @@ macro_rules! tuple { Value::Float(n) => n.write_kbin_bytes(output), Value::Double(n) => n.write_kbin_bytes(output), Value::Boolean(v) => v.write_kbin_bytes(output), - Value::Array(_, values) => { - for value in values { - value.to_bytes_inner(output)?; - } - }, - Value::ArrayNew(value) => value.to_bytes_inner(output)?, + Value::Array(value) => value.to_bytes_into(output)?, Value::Attribute(_) | Value::String(_) => return Err(KbinErrorKind::InvalidNodeType(self.standard_type()).into()), $( @@ -290,11 +244,6 @@ impl Value { self.to_bytes_inner(output) } - #[inline] - pub fn array_as_string(values: &[Value]) -> String { - BorrowedValueArray(values).to_string() - } - pub fn as_i8(&self) -> Result { match self { Value::S8(ref n) => Ok(*n), @@ -388,7 +337,7 @@ impl Value { pub fn as_array(&self) -> Result<&ValueArray, KbinError> { match self { - Value::ArrayNew(ref values) => Ok(values), + Value::Array(ref values) => Ok(values), value => Err(KbinErrorKind::ExpectedValueArray(value.clone()).into()), } } @@ -401,16 +350,18 @@ impl Value { } } +/* impl TryFrom for Vec { type Error = KbinError; fn try_from(value: Value) -> Result { match value { - Value::Array(_, values) => Ok(values), + Value::Array(values) => Ok(values), value => Err(KbinErrorKind::ExpectedValueArray(value).into()), } } } +*/ impl TryFrom for Vec { type Error = KbinError; @@ -420,11 +371,9 @@ impl TryFrom for Vec { // array of unsigned 8-bit integers. match value { Value::Binary(data) => Ok(data), - Value::Array(node_type, values) => { - if node_type != StandardType::U8 { - return Err(KbinErrorKind::ValueTypeMismatch(StandardType::U8, Value::Array(node_type, values)).into()); - } - values.iter().map(Value::as_u8).collect() + Value::Array(values) => match values { + ValueArray::U8(values) => Ok(values), + values => Err(KbinErrorKind::ValueTypeMismatch(StandardType::U8, Value::Array(values)).into()), }, value => Err(KbinErrorKind::ValueTypeMismatch(StandardType::Binary, value).into()), } @@ -437,11 +386,9 @@ impl TryFrom<&Value> for Vec { fn try_from(value: &Value) -> Result { match value { Value::Binary(ref data) => Ok(data.to_vec()), - Value::Array(ref node_type, ref values) => { - if *node_type != StandardType::U8 { - return Err(KbinErrorKind::ValueTypeMismatch(StandardType::U8, value.clone()).into()); - } - values.iter().map(Value::as_u8).collect() + Value::Array(ref values) => match values.clone() { + ValueArray::U8(values) => Ok(values), + values => Err(KbinErrorKind::ValueTypeMismatch(StandardType::U8, Value::Array(values)).into()), }, value => Err(KbinErrorKind::ValueTypeMismatch(StandardType::Binary, value.clone()).into()), } @@ -469,12 +416,7 @@ impl fmt::Debug for Value { Value::$konst_debug(ref v) => write!(f, concat!(stringify!($konst_debug), "({:?})"), v), )* Value::Binary(ref v) => write!(f, "Binary(0x{:02x?})", v), - Value::Array(ref node_type, ref a) => if f.alternate() { - write!(f, "Array({:?}, {:#?})", node_type, a) - } else { - write!(f, "Array({:?}, {:?})", node_type, a) - }, - Value::ArrayNew(ref value) => if f.alternate() { + Value::Array(ref value) => if f.alternate() { write!(f, "Array({:#?})", value) } else { write!(f, "Array({:?})", value) @@ -502,22 +444,6 @@ 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 { @@ -566,7 +492,6 @@ impl fmt::Display for Value { true => f.write_str("1"), false => f.write_str("0"), }, - Value::Array(_, values) => BorrowedValueArray(&values).fmt(f), } }; } @@ -575,7 +500,7 @@ impl fmt::Display for Value { simple: [ S8, U8, S16, U16, S32, U32, S64, U64, String, Ip4, Time, Attribute, - ArrayNew + Array ], tuple: [ S8_2, U8_2, S16_2, U16_2, S32_2, U32_2, S64_2, U64_2, diff --git a/src/writer.rs b/src/writer.rs index a3e2c0e..3ecb956 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -29,7 +29,7 @@ fn write_value(options: &Options, data_buf: &mut ByteBufferWrite, node_type: Sta Value::String(text) => { data_buf.write_str(options.encoding, &text)?; }, - Value::Array(node_type, values) => { + Value::Array(values) => { if !is_array { return Err(KbinErrorKind::InvalidState.into()); } @@ -37,9 +37,7 @@ fn write_value(options: &Options, data_buf: &mut ByteBufferWrite, node_type: Sta let total_size = values.len() * node_type.count * node_type.size; let mut data = Vec::with_capacity(total_size); - for value in values { - value.to_bytes_into(&mut data)?; - } + values.to_bytes_into(&mut data)?; data_buf.write_u32::(total_size as u32).context(KbinErrorKind::DataWrite("node size"))?; data_buf.write_all(&data).context(KbinErrorKind::DataWrite(node_type.name))?; @@ -235,7 +233,7 @@ impl Writeable for NodeCollection { impl Writeable for Node { fn write_node(&self, options: &Options, node_buf: &mut ByteBufferWrite, data_buf: &mut ByteBufferWrite) -> Result<()> { let (node_type, is_array) = match self.value() { - Some(Value::Array(node_type, _)) => (*node_type, true), + Some(Value::Array(ref values)) => (values.standard_type(), true), Some(ref value) => (value.standard_type(), false), None => (StandardType::NodeStart, false), };