value: remove old array implementation and clean up string parsing

This commit is contained in:
Matt Bilker
2019-07-08 23:56:33 +00:00
parent b195bd89bf
commit e4bbc431d1
7 changed files with 80 additions and 132 deletions

View File

@@ -80,14 +80,7 @@ fn read_node(reader: &mut Reader, def: NodeDefinition) -> Result<Element> {
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();

View File

@@ -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();

View File

@@ -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()),

View File

@@ -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<Self, KbinError>;
}

View File

@@ -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<u8>) -> Result<(), KbinError> {
pub(super) fn from_string(node_type: StandardType, count: usize, input: &str, arr_count: usize) -> Result<Self, KbinError> {
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<u8>) -> Result<(), KbinError> {
let node_size = self.standard_type().size;
match self {

View File

@@ -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<Value, KbinError> {
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<Value>),
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<Value, KbinError> {
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<i8, KbinError> {
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<Value> for Vec<Value> {
type Error = KbinError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::Array(_, values) => Ok(values),
Value::Array(values) => Ok(values),
value => Err(KbinErrorKind::ExpectedValueArray(value).into()),
}
}
}
*/
impl TryFrom<Value> for Vec<u8> {
type Error = KbinError;
@@ -420,11 +371,9 @@ impl TryFrom<Value> for Vec<u8> {
// 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<u8> {
fn try_from(value: &Value) -> Result<Self, Self::Error> {
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
/// `<Value as fmt::Display>` 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,

View File

@@ -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::<BigEndian>(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),
};