diff --git a/src/value/array.rs b/src/value/array.rs new file mode 100644 index 0000000..17e64c5 --- /dev/null +++ b/src/value/array.rs @@ -0,0 +1,522 @@ +//use std::convert::TryFrom; +use std::fmt; +use std::net::Ipv4Addr; +//use std::str::FromStr; + +use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; +use failure::ResultExt; +//use rustc_hex::FromHex; + +use crate::error::{KbinError, KbinErrorKind}; +use crate::node_types::{self, StandardType}; + +#[derive(Clone, Debug, PartialEq)] +pub enum ValueArray { + S8(Vec), + U8(Vec), + S16(Vec), + U16(Vec), + S32(Vec), + U32(Vec), + S64(Vec), + U64(Vec), + Ip4(Vec), + Float(Vec), + Double(Vec), + S8_2(Vec<[i8; 2]>), + U8_2(Vec<[u8; 2]>), + S16_2(Vec<[i16; 2]>), + U16_2(Vec<[u16; 2]>), + S32_2(Vec<[i32; 2]>), + U32_2(Vec<[u32; 2]>), + S64_2(Vec<[i64; 2]>), + U64_2(Vec<[u64; 2]>), + Float2(Vec<[f32; 2]>), + Double2(Vec<[f64; 2]>), + S8_3(Vec<[i8; 3]>), + U8_3(Vec<[u8; 3]>), + S16_3(Vec<[i16; 3]>), + U16_3(Vec<[u16; 3]>), + S32_3(Vec<[i32; 3]>), + U32_3(Vec<[u32; 3]>), + S64_3(Vec<[i64; 3]>), + U64_3(Vec<[u64; 3]>), + Float3(Vec<[f32; 3]>), + Double3(Vec<[f64; 3]>), + S8_4(Vec<[i8; 4]>), + U8_4(Vec<[u8; 4]>), + S16_4(Vec<[i16; 4]>), + U16_4(Vec<[u16; 4]>), + S32_4(Vec<[i32; 4]>), + U32_4(Vec<[u32; 4]>), + S64_4(Vec<[i64; 4]>), + U64_4(Vec<[u64; 4]>), + Float4(Vec<[f32; 4]>), + Double4(Vec<[f64; 4]>), + Vs8(Vec<[i8; 16]>), + Vu8(Vec<[u8; 16]>), + Vs16(Vec<[i16; 8]>), + Vu16(Vec<[u16; 8]>), + Boolean(Vec), + Boolean2(Vec<[bool; 2]>), + Boolean3(Vec<[bool; 3]>), + Boolean4(Vec<[bool; 4]>), + Vb(Vec<[bool; 16]>), +} + +macro_rules! tuple { + ( + byte: [ + s8: [$($s8_konst:ident),*], + u8: [$($u8_konst:ident),*], + bool: [$($bool_konst:ident),*] + ], + multi: [ + $($read_method:ident $write_method:ident $inner_type:ty => [$($multi_konst:ident),*]),* + ] + ) => { + pub fn from_standard_type(node_type: StandardType, input: &[u8]) -> Result, KbinError> { + let node_size = node_type.size * node_type.count; + let len = input.len() / node_size; + + // Prevent reading incomplete input data + if node_size * len != input.len() { + return Err(KbinErrorKind::SizeMismatch(*node_type, node_size, input.len()).into()); + } + + let value = match node_type { + StandardType::NodeStart | + StandardType::NodeEnd | + StandardType::FileEnd | + StandardType::Attribute | + StandardType::Binary | + StandardType::String | + StandardType::Time => return Ok(None), + StandardType::S8 => ValueArray::S8(input.iter().map(|v| *v as i8).collect()), + StandardType::U8 => ValueArray::U8(input.to_vec()), + StandardType::S16 => { + let mut values = vec![0; len]; + BigEndian::read_i16_into(input, &mut values); + ValueArray::S16(values) + }, + StandardType::U16 => { + let mut values = vec![0; len]; + BigEndian::read_u16_into(input, &mut values); + ValueArray::U16(values) + }, + StandardType::S32 => { + let mut values = vec![0; len]; + BigEndian::read_i32_into(input, &mut values); + ValueArray::S32(values) + }, + StandardType::U32 => { + let mut values = vec![0; len]; + BigEndian::read_u32_into(input, &mut values); + ValueArray::U32(values) + }, + StandardType::S64 => { + let mut values = vec![0; len]; + BigEndian::read_i64_into(input, &mut values); + ValueArray::S64(values) + }, + StandardType::U64 => { + let mut values = vec![0; len]; + BigEndian::read_u64_into(input, &mut values); + ValueArray::U64(values) + }, + StandardType::Ip4 => { + let mut values = Vec::with_capacity(len); + + for chunk in input.chunks(4) { + let mut octets = [0; 4]; + octets.copy_from_slice(chunk); + values.push(Ipv4Addr::from(octets)); + } + + ValueArray::Ip4(values) + }, + StandardType::Float => { + let mut values = vec![0.0; len]; + BigEndian::read_f32_into(input, &mut values); + ValueArray::Float(values) + }, + StandardType::Double => { + let mut values = vec![0.0; len]; + BigEndian::read_f64_into(input, &mut values); + ValueArray::Double(values) + }, + StandardType::Boolean => { + let mut values = Vec::with_capacity(len); + + for value in input { + match value { + 0x00 => values.push(false), + 0x01 => values.push(true), + input => return Err(KbinErrorKind::InvalidBooleanInput(*input).into()), + }; + } + + ValueArray::Boolean(values) + }, + $( + StandardType::$s8_konst => { + const COUNT: usize = node_types::$s8_konst.count; + + let mut values = Vec::with_capacity(len); + + for chunk in input.chunks(COUNT) { + let mut value = [0; COUNT]; + for i in 0..COUNT { + value[i] = chunk[i] as i8; + } + values.push(value); + } + + ValueArray::$s8_konst(values) + }, + )* + $( + StandardType::$u8_konst => { + const COUNT: usize = node_types::$u8_konst.count; + + let mut values = Vec::with_capacity(len); + + for chunk in input.chunks(COUNT) { + let mut value = [0; COUNT]; + value[0..COUNT].copy_from_slice(&chunk[0..COUNT]); + values.push(value); + } + + ValueArray::$u8_konst(values) + }, + )* + $( + StandardType::$bool_konst => { + const COUNT: usize = node_types::$bool_konst.count; + + let mut values = Vec::with_capacity(len); + + for chunk in input.chunks(COUNT) { + let mut value: [_; COUNT] = Default::default(); + for i in 0..COUNT { + value[i] = match chunk[i] { + 0x00 => false, + 0x01 => true, + input => return Err(KbinErrorKind::InvalidBooleanInput(input).into()), + }; + } + values.push(value); + } + + ValueArray::$bool_konst(values) + }, + )* + $( + $( + StandardType::$multi_konst => { + const COUNT: usize = node_types::$multi_konst.count; + const SIZE: usize = node_types::$multi_konst.size * COUNT; + + let mut values = Vec::with_capacity(len); + + for chunk in input.chunks(SIZE) { + let mut value: [_; COUNT] = Default::default(); + BigEndian::$read_method(chunk, &mut value); + values.push(value); + } + + ValueArray::$multi_konst(values) + }, + )* + )* + }; + + Ok(Some(value)) + } + + pub(super) fn to_bytes_inner(&self, output: &mut Vec) -> Result<(), KbinError> { + macro_rules! gen_error { + ($konst:ident) => { + KbinErrorKind::DataWrite(StandardType::$konst.name) + }; + } + + let node_size = self.standard_type().size; + + match self { + ValueArray::S8(ref values) => { + output.reserve(values.len()); + for n in values { + output.push(*n as u8); + } + }, + ValueArray::U8(ref values) => output.extend(values), + ValueArray::S16(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_i16::(*n).context(gen_error!(S16))?; + } + }, + ValueArray::U16(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_u16::(*n).context(gen_error!(U16))?; + } + }, + ValueArray::S32(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_i32::(*n).context(gen_error!(S32))?; + } + }, + ValueArray::U32(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_u32::(*n).context(gen_error!(U32))?; + } + }, + ValueArray::S64(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_i64::(*n).context(gen_error!(S64))?; + } + }, + ValueArray::U64(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_u64::(*n).context(gen_error!(U64))?; + } + }, + ValueArray::Ip4(ref values) => { + for addr in values { + output.extend_from_slice(&addr.octets()); + } + }, + ValueArray::Float(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_f32::(*n).context(gen_error!(Float))?; + } + }, + ValueArray::Double(ref values) => { + output.reserve(values.len() * node_size); + for n in values { + output.write_f64::(*n).context(gen_error!(Double))?; + } + }, + ValueArray::Boolean(ref values) => { + output.reserve(values.len() * node_size); + for v in values { + output.push(if *v { 0x01 } else { 0x00 }); + } + }, + $( + ValueArray::$s8_konst(values) => { + output.reserve(values.len() * node_size); + for value in values { + for n in value.into_iter() { + output.push(*n as u8); + } + } + }, + )* + $( + ValueArray::$u8_konst(values) => { + output.reserve(values.len() * node_size); + for value in values { + for n in value.into_iter() { + output.push(*n); + } + } + }, + )* + $( + ValueArray::$bool_konst(values) => { + output.reserve(values.len() * node_size); + for value in values { + for v in value.into_iter() { + output.push(if *v { 0x01 } else { 0x00 }); + } + } + }, + )* + $( + $( + ValueArray::$multi_konst(values) => { + output.reserve(values.len() * node_size); + for value in values { + for v in value.into_iter() { + output.$write_method::(*v).context(gen_error!($multi_konst))?; + } + } + }, + )* + )* + }; + + Ok(()) + } + }; +} + +impl ValueArray { + tuple! { + byte: [ + s8: [S8_2, S8_3, S8_4, Vs8], + u8: [U8_2, U8_3, U8_4, Vu8], + bool: [Boolean2, Boolean3, Boolean4, Vb] + ], + multi: [ + read_i16_into write_i16 i16 => [S16_2, S16_3, S16_4, Vs16], + read_i32_into write_i32 i32 => [S32_2, S32_3, S32_4], + read_i64_into write_i64 i64 => [S64_2, S64_3, S64_4], + read_u16_into write_u16 u16 => [U16_2, U16_3, U16_4, Vu16], + read_u32_into write_u32 u32 => [U32_2, U32_3, U32_4], + read_u64_into write_u64 u64 => [U64_2, U64_3, U64_4], + read_f32_into write_f32 f32 => [Float2, Float3, Float4], + read_f64_into write_f64 f64 => [Double2, Double3, Double4] + ] + } + + pub fn standard_type(&self) -> StandardType { + match self { + ValueArray::S8(_) => StandardType::S8, + ValueArray::U8(_) => StandardType::U8, + ValueArray::S16(_) => StandardType::S16, + ValueArray::U16(_) => StandardType::U16, + ValueArray::S32(_) => StandardType::S32, + ValueArray::U32(_) => StandardType::U32, + ValueArray::S64(_) => StandardType::S64, + ValueArray::U64(_) => StandardType::U64, + ValueArray::Ip4(_) => StandardType::Ip4, + ValueArray::Float(_) => StandardType::Float, + ValueArray::Double(_) => StandardType::Double, + ValueArray::S8_2(_) => StandardType::S8_2, + ValueArray::U8_2(_) => StandardType::U8_2, + ValueArray::S16_2(_) => StandardType::S16_2, + ValueArray::U16_2(_) => StandardType::U16_2, + ValueArray::S32_2(_) => StandardType::S32_2, + ValueArray::U32_2(_) => StandardType::U32_2, + ValueArray::S64_2(_) => StandardType::S64_2, + ValueArray::U64_2(_) => StandardType::U64_2, + ValueArray::Float2(_) => StandardType::Float2, + ValueArray::Double2(_) => StandardType::Double2, + ValueArray::S8_3(_) => StandardType::S8_3, + ValueArray::U8_3(_) => StandardType::U8_3, + ValueArray::S16_3(_) => StandardType::S16_3, + ValueArray::U16_3(_) => StandardType::U16_3, + ValueArray::S32_3(_) => StandardType::S32_3, + ValueArray::U32_3(_) => StandardType::U32_3, + ValueArray::S64_3(_) => StandardType::S64_3, + ValueArray::U64_3(_) => StandardType::U64_3, + ValueArray::Float3(_) => StandardType::Float3, + ValueArray::Double3(_) => StandardType::Double3, + ValueArray::S8_4(_) => StandardType::S8_4, + ValueArray::U8_4(_) => StandardType::U8_4, + ValueArray::S16_4(_) => StandardType::S16_4, + ValueArray::U16_4(_) => StandardType::U16_4, + ValueArray::S32_4(_) => StandardType::S32_4, + ValueArray::U32_4(_) => StandardType::U32_4, + ValueArray::S64_4(_) => StandardType::S64_4, + ValueArray::U64_4(_) => StandardType::U64_4, + ValueArray::Float4(_) => StandardType::Float4, + ValueArray::Double4(_) => StandardType::Double4, + ValueArray::Vs8(_) => StandardType::Vs8, + ValueArray::Vu8(_) => StandardType::Vu8, + ValueArray::Vs16(_) => StandardType::Vs16, + ValueArray::Vu16(_) => StandardType::Vu16, + ValueArray::Boolean(_) => StandardType::Boolean, + ValueArray::Boolean2(_) => StandardType::Boolean2, + ValueArray::Boolean3(_) => StandardType::Boolean3, + ValueArray::Boolean4(_) => StandardType::Boolean4, + ValueArray::Vb(_) => StandardType::Vb, + } + } +} + +fn write_values(f: &mut fmt::Formatter, values: &[T]) -> fmt::Result { + for (i, v) in values.iter().enumerate() { + if i > 0 { + f.write_str(" ")?; + } + fmt::Display::fmt(v, f)?; + } + Ok(()) +} + +macro_rules! write_array { + ($method:ident, $num:expr) => { + fn $method(f: &mut fmt::Formatter, values: &[[T; $num]]) -> fmt::Result { + for (i, v) in values.iter().flat_map(|v| v.into_iter()).enumerate() { + if i > 0 { + f.write_str(" ")?; + } + fmt::Display::fmt(v, f)?; + } + Ok(()) + } + }; +} + +write_array!(write_array_2, 2); +write_array!(write_array_3, 3); +write_array!(write_array_4, 4); +write_array!(write_array_8, 8); +write_array!(write_array_16, 16); + +impl fmt::Display for ValueArray { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ValueArray::S8(v) => write_values(f, v), + ValueArray::U8(v) => write_values(f, v), + ValueArray::S16(v) => write_values(f, v), + ValueArray::U16(v) => write_values(f, v), + ValueArray::S32(v) => write_values(f, v), + ValueArray::U32(v) => write_values(f, v), + ValueArray::S64(v) => write_values(f, v), + ValueArray::U64(v) => write_values(f, v), + ValueArray::Ip4(v) => write_values(f, v), + ValueArray::Float(v) => write_values(f, v), + ValueArray::Double(v) => write_values(f, v), + ValueArray::S8_2(v) => write_array_2(f, v), + ValueArray::U8_2(v) => write_array_2(f, v), + ValueArray::S16_2(v) => write_array_2(f, v), + ValueArray::U16_2(v) => write_array_2(f, v), + ValueArray::S32_2(v) => write_array_2(f, v), + ValueArray::U32_2(v) => write_array_2(f, v), + ValueArray::S64_2(v) => write_array_2(f, v), + ValueArray::U64_2(v) => write_array_2(f, v), + ValueArray::Float2(v) => write_array_2(f, v), + ValueArray::Double2(v) => write_array_2(f, v), + ValueArray::S8_3(v) => write_array_3(f, v), + ValueArray::U8_3(v) => write_array_3(f, v), + ValueArray::S16_3(v) => write_array_3(f, v), + ValueArray::U16_3(v) => write_array_3(f, v), + ValueArray::S32_3(v) => write_array_3(f, v), + ValueArray::U32_3(v) => write_array_3(f, v), + ValueArray::S64_3(v) => write_array_3(f, v), + ValueArray::U64_3(v) => write_array_3(f, v), + ValueArray::Float3(v) => write_array_3(f, v), + ValueArray::Double3(v) => write_array_3(f, v), + ValueArray::S8_4(v) => write_array_4(f, v), + ValueArray::U8_4(v) => write_array_4(f, v), + ValueArray::S16_4(v) => write_array_4(f, v), + ValueArray::U16_4(v) => write_array_4(f, v), + ValueArray::S32_4(v) => write_array_4(f, v), + ValueArray::U32_4(v) => write_array_4(f, v), + ValueArray::S64_4(v) => write_array_4(f, v), + ValueArray::U64_4(v) => write_array_4(f, v), + ValueArray::Float4(v) => write_array_4(f, v), + ValueArray::Double4(v) => write_array_4(f, v), + ValueArray::Vs8(v) => write_array_16(f, v), + ValueArray::Vu8(v) => write_array_16(f, v), + ValueArray::Vs16(v) => write_array_8(f, v), + ValueArray::Vu16(v) => write_array_8(f, v), + ValueArray::Boolean(v) => write_values(f, &v), + ValueArray::Boolean2(v) => write_array_2(f, v), + ValueArray::Boolean3(v) => write_array_3(f, v), + ValueArray::Boolean4(v) => write_array_4(f, v), + ValueArray::Vb(v) => write_array_16(f, v), + } + } +} diff --git a/src/value.rs b/src/value/mod.rs similarity index 87% rename from src/value.rs rename to src/value/mod.rs index 33d4666..7d85a3e 100644 --- a/src/value.rs +++ b/src/value/mod.rs @@ -9,6 +9,74 @@ use rustc_hex::FromHex; use crate::error::{KbinError, KbinErrorKind}; use crate::node_types::{self, StandardType}; +use crate::types::FromKbinBytes; + +mod array; + +pub use self::array::ValueArray; + +#[inline] +fn parse(node_type: StandardType, input: &str) -> Result + where T: FromStr, + T::Err: Fail +{ + // Check for space character + if input.find(' ').is_some() { + return Err(KbinErrorKind::InvalidState.into()); + } + + let n = input.parse::().context(KbinErrorKind::StringParse(node_type.name))?; + Ok(n) +} + +#[inline] +fn parse_tuple(node_type: StandardType, input: &str, output: &mut [T]) -> Result<(), KbinError> + where T: FromStr, + T::Err: Fail +{ + let count = input.split(' ').count(); + if count != node_type.count { + return Err(KbinErrorKind::SizeMismatch(*node_type, node_type.count, count).into()); + } + + for (i, part) in input.split(' ').enumerate() { + output[i] = part.parse::().context(KbinErrorKind::StringParse(node_type.name))?; + } + + Ok(()) +} + +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 { ( @@ -26,6 +94,7 @@ macro_rules! construct_types { Attribute(String), Array(StandardType, Vec), + ArrayNew(ValueArray), } $( @@ -68,6 +137,7 @@ macro_rules! construct_types { Value::Time(_) => StandardType::Time, Value::Attribute(_) => StandardType::Attribute, Value::Array(node_type, _) => node_type, + Value::ArrayNew(ref value) => value.standard_type(), } } } @@ -119,28 +189,20 @@ macro_rules! tuple { StandardType::FileEnd | StandardType::Attribute | StandardType::String => return Ok(None), - StandardType::S8 => Value::S8(input[0] as i8), - StandardType::U8 => Value::U8(input[0]), - StandardType::S16 => Value::S16(BigEndian::read_i16(input)), - StandardType::U16 => Value::U16(BigEndian::read_u16(input)), - StandardType::S32 => Value::S32(BigEndian::read_i32(input)), - StandardType::U32 => Value::U32(BigEndian::read_u32(input)), - StandardType::S64 => Value::S64(BigEndian::read_i64(input)), - StandardType::U64 => Value::U64(BigEndian::read_u64(input)), + StandardType::S8 => i8::from_kbin_bytes(input).map(Value::S8)?, + StandardType::U8 => u8::from_kbin_bytes(input).map(Value::U8)?, + StandardType::S16 => i16::from_kbin_bytes(input).map(Value::S16)?, + StandardType::U16 => u16::from_kbin_bytes(input).map(Value::U16)?, + StandardType::S32 => i32::from_kbin_bytes(input).map(Value::S32)?, + StandardType::U32 => u32::from_kbin_bytes(input).map(Value::U32)?, + StandardType::S64 => i64::from_kbin_bytes(input).map(Value::S64)?, + StandardType::U64 => u64::from_kbin_bytes(input).map(Value::U64)?, StandardType::Binary => Value::Binary(input.to_vec()), - StandardType::Time => Value::Time(BigEndian::read_u32(input)), - StandardType::Ip4 => { - let mut octets = [0; 4]; - octets[0..4].copy_from_slice(&input[0..4]); - Value::Ip4(Ipv4Addr::from(octets)) - }, - StandardType::Float => Value::Float(BigEndian::read_f32(input)), - StandardType::Double => Value::Double(BigEndian::read_f64(input)), - StandardType::Boolean => Value::Boolean(match input[0] { - 0x00 => false, - 0x01 => true, - input => return Err(KbinErrorKind::InvalidBooleanInput(input).into()), - }), + StandardType::Time => u32::from_kbin_bytes(input).map(Value::Time)?, + StandardType::Ip4 => Ipv4Addr::from_kbin_bytes(input).map(Value::Ip4)?, + StandardType::Float => f32::from_kbin_bytes(input).map(Value::Float)?, + StandardType::Double => f64::from_kbin_bytes(input).map(Value::Double)?, + StandardType::Boolean => bool::from_kbin_bytes(input).map(Value::Boolean)?, $( StandardType::$s8_konst => { const COUNT: usize = node_types::$s8_konst.count; @@ -164,11 +226,7 @@ macro_rules! tuple { const COUNT: usize = node_types::$bool_konst.count; let mut value: [_; COUNT] = Default::default(); for i in 0..COUNT { - value[i] = match input[i] { - 0x00 => false, - 0x01 => true, - input => return Err(KbinErrorKind::InvalidBooleanInput(input).into()), - }; + value[i] = bool::from_kbin_bytes(&input[i..i + 1])?; } Value::$bool_konst(value) }, @@ -191,67 +249,6 @@ macro_rules! tuple { } pub fn from_string(node_type: StandardType, input: &str, is_array: bool, arr_count: usize) -> Result { - #[inline] - fn parse(node_type: StandardType, input: &str) -> Result - where T: FromStr, - T::Err: Fail - { - // TODO(mbilker): Add string check for spaces - let n = input.parse::().context(KbinErrorKind::StringParse(node_type.name))?; - Ok(n) - } - - #[inline] - fn parse_tuple(node_type: StandardType, input: &str, output: &mut [T]) -> Result<(), KbinError> - where T: FromStr, - T::Err: Fail - { - - let mut i = 0; - for part in input.split(' ') { - output[i] = part.parse::().context(KbinErrorKind::StringParse(node_type.name))?; - i += 1; - } - - if i != node_type.count { - return Err(KbinErrorKind::SizeMismatch(*node_type, node_type.count, i).into()); - } - - Ok(()) - } - - 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)) - } - if is_array { let value = match node_type.count { 1 => { @@ -395,6 +392,7 @@ macro_rules! tuple { value.to_bytes_inner(output)?; } }, + Value::ArrayNew(value) => value.to_bytes_inner(output)?, Value::Attribute(_) | Value::String(_) => return Err(KbinErrorKind::InvalidNodeType(self.standard_type()).into()), $( @@ -649,9 +647,14 @@ impl fmt::Debug for Value { )* 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) + write!(f, "Array({:?}, {:#?})", node_type, a) } else { - write!(f, "Array({:?}, {:?}", node_type, a) + write!(f, "Array({:?}, {:?})", node_type, a) + }, + Value::ArrayNew(ref value) => if f.alternate() { + write!(f, "Array({:#?})", value) + } else { + write!(f, "Array({:?})", value) }, } }; @@ -748,7 +751,8 @@ impl fmt::Display for Value { display_value! { simple: [ S8, U8, S16, U16, S32, U32, S64, U64, - String, Ip4, Time, Attribute + String, Ip4, Time, Attribute, + ArrayNew ], tuple: [ S8_2, U8_2, S16_2, U16_2, S32_2, U32_2, S64_2, U64_2,