diff --git a/src/bin/kbinxml.rs b/src/bin/kbinxml.rs index ee32916..5f7598a 100644 --- a/src/bin/kbinxml.rs +++ b/src/bin/kbinxml.rs @@ -1,5 +1,8 @@ +#![feature(int_to_from_bytes)] + extern crate failure; extern crate kbinxml; +extern crate minidom; extern crate pretty_env_logger; extern crate quick_xml; @@ -9,22 +12,77 @@ use std::io::{Cursor, Error as IoError, ErrorKind as IoErrorKind, Read, Write, s use failure::Fail; use kbinxml::KbinXml; +use minidom::Element; use quick_xml::Writer; fn display_err(err: impl Fail) -> IoError { let mut fail: &Fail = &err; + eprintln!("e: {}", err); while let Some(cause) = fail.cause() { eprintln!("Cause: {}", cause); fail = cause; } - if let Some(backtrace) = err.cause().and_then(|cause| cause.backtrace()) { + if let Some(backtrace) = err.backtrace() { eprintln!("{}", backtrace); } IoError::new(IoErrorKind::Other, "Error parsing kbin") } +fn display_element(element: &Element) -> Result<(), IoError> { + let inner = Cursor::new(Vec::new()); + let mut writer = Writer::new_with_indent(inner, b' ', 2); + element.to_writer(&mut writer).map_err(|e| IoError::new(IoErrorKind::Other, format!("{:?}", e)))?; + + let buf = writer.into_inner().into_inner(); + let stdout = stdout(); + stdout.lock().write_all(&buf)?; + println!(); + + Ok(()) +} + +fn compare_slice(left: &[u8], right: &[u8]) { + let mut buf = [0; 4]; + buf.clone_from_slice(&left[4..8]); + let node_buf_length = u32::from_be(u32::from_bytes(buf)); + //println!("node_buf_length: {}", node_buf_length); + + let data_buf_start = 8 + node_buf_length as usize; + let data_buf_len_end = data_buf_start + 4; + //println!("data_buf start: {} + 8 = {}", node_buf_length, data_buf_start); + + buf.clone_from_slice(&left[data_buf_start..data_buf_len_end]); + //let data_buf_length = u32::from_be(u32::from_bytes(buf)); + //println!("data_buf_length: {}", data_buf_length); + + let mut i = 0; + let mut mismatches = Vec::new(); + while i < left.len() && i < right.len() { + if left[i] != right[i] { + mismatches.push((i, left[i], right[i])); + } + i += 1; + } + + if let Some(ref first) = mismatches.first() { + eprintln!("Left does not equal right at the following indexes:"); + for (i, left, right) in &mismatches { + let (section, offset) = if *i < data_buf_start { + ("node buffer", (*i as isize) - 8) + } else { + ("data buffer", (*i as isize) - 4 - (data_buf_start as isize)) + }; + eprintln!("index {0} ({3}, offset: {4}), left: {1:3} (0x{1:x}),\tright: {2:3} (0x{2:x})", i, left, right, section, offset); + } + + let (i, _, _) = first; + eprintln!(r#" left: `{:?}` + right: `{:?}`"#, &left[*i..], &right[*i..]); + } +} + fn main() -> std::io::Result<()> { pretty_env_logger::init(); @@ -37,18 +95,13 @@ fn main() -> std::io::Result<()> { let element = KbinXml::from_binary(&contents).map_err(display_err)?; //println!("element: {:#?}", element); - - let inner = Cursor::new(Vec::new()); - let mut writer = Writer::new_with_indent(inner, b' ', 2); - element.to_writer(&mut writer).map_err(|e| IoError::new(IoErrorKind::Other, format!("{:?}", e)))?; - - let buf = writer.into_inner().into_inner(); - let stdout = stdout(); - stdout.lock().write_all(&buf)?; - println!(); + display_element(&element)?; let buf = KbinXml::to_binary(&element).map_err(display_err)?; - assert_eq!(buf, contents); + compare_slice(&buf, &contents); + + let element = KbinXml::from_binary(&buf).map_err(display_err)?; + display_element(&element)?; } Ok(()) } diff --git a/src/encoding_type.rs b/src/encoding_type.rs index 82d315c..9a28e0a 100644 --- a/src/encoding_type.rs +++ b/src/encoding_type.rs @@ -1,6 +1,6 @@ use error::{KbinError, KbinErrorKind}; -use encoding::{DecoderTrap, Encoding}; +use encoding::{DecoderTrap, EncoderTrap, Encoding}; use encoding::all::{ASCII, EUC_JP, ISO_8859_1, WINDOWS_31J}; #[allow(non_camel_case_types)] @@ -46,7 +46,7 @@ impl EncodingType { /// crate. A `None` value indicates Rust's own UTF-8 handling should be used. pub fn decode_bytes(&self, input: Vec) -> Result { let decoder_fail = |e| { - format_err!("{}", e).context(KbinErrorKind::EncodingDecode) + format_err!("{}", e).context(KbinErrorKind::Encoding) }; let result = match *self { @@ -61,4 +61,29 @@ impl EncodingType { Ok(result) } + + /// Encode bytes using the encoding definition from the `encoding` crate. + /// + /// A `Some` value indicates the encoding should be used from the `encoding` + /// crate. A `None` value indicates Rust's own UTF-8 handling should be used. + pub fn encode_bytes(&self, input: &str) -> Result, KbinError> { + let encoder_fail = |e| { + format_err!("{}", e).context(KbinErrorKind::Encoding) + }; + + let mut result = match *self { + EncodingType::None | + EncodingType::UTF_8 => input.as_bytes().to_vec(), + + EncodingType::ASCII => ASCII.encode(input, EncoderTrap::Strict).map_err(encoder_fail)?, + EncodingType::ISO_8859_1 => ISO_8859_1.encode(input, EncoderTrap::Strict).map_err(encoder_fail)?, + EncodingType::EUC_JP => EUC_JP.encode(input, EncoderTrap::Strict).map_err(encoder_fail)?, + EncodingType::SHIFT_JIS => WINDOWS_31J.encode(input, EncoderTrap::Strict).map_err(encoder_fail)?, + }; + + // Add trailing null byte + result.push(0); + + Ok(result) + } } diff --git a/src/error.rs b/src/error.rs index 3bd5a60..ca2f382 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,8 @@ use std::string::FromUtf8Error; use failure::{Backtrace, Context, Fail}; +use node_types::KbinType; + #[derive(Debug)] pub struct KbinError { inner: Context, @@ -43,9 +45,6 @@ pub enum KbinErrorKind { #[fail(display = "Unable to read encoding negation byte")] EncodingNegationRead, - #[fail(display = "Unknown encoding")] - UnknownEncoding, - #[fail(display = "Unable to read len_node")] LenNodeRead, @@ -79,17 +78,26 @@ pub enum KbinErrorKind { #[fail(display = "Unable to interpret string as UTF-8")] Utf8, + #[fail(display = "Unknown encoding")] + UnknownEncoding, + #[fail(display = "Unable to interpret string as alternate encoding")] - EncodingDecode, + Encoding, #[fail(display = "Unable to write {} header field", _0)] HeaderWrite(&'static str), - #[fail(display = "Unable to write a {} node", _0)] + #[fail(display = "Unable to write a {}", _0)] DataWrite(&'static str), + #[fail(display = "Size Mismatch, type: {}, expected size: {}, actual size: {}", _0, _1, _2)] + SizeMismatch(KbinType, usize, usize), + #[fail(display = "Unable to interpret input as {}", _0)] StringParse(&'static str), + + #[fail(display = "Unable to convert from hexadecimal")] + HexError, } impl fmt::Display for KbinError { diff --git a/src/lib.rs b/src/lib.rs index 0a52514..7ba1125 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,6 +36,8 @@ const SIGNATURE: u8 = 0xA0; const SIG_COMPRESSED: u8 = 0x42; +const ARRAY_MASK: u8 = 1 << 6; // 1 << 6 = 64 + pub struct KbinXml { offset_1: u64, offset_2: u64, @@ -50,7 +52,7 @@ impl KbinXml { } #[inline] - fn data_buf_offset(&self, data_buf: &Cursor<&[u8]>) -> u64 { + fn data_buf_offset(&self, data_buf: &Cursor) -> u64 { // Position is not the index of the previously read byte, it is the current // index (offset). // @@ -61,15 +63,29 @@ impl KbinXml { fn data_buf_read(&mut self, data_buf: &mut Cursor<&[u8]>) -> Result, KbinError> { let size = data_buf.read_u32::().context(KbinErrorKind::DataReadSize)?; + debug!("data_buf_read => index: {}, size: {}", data_buf.position(), size); + let mut data = vec![0; size as usize]; data_buf.read_exact(&mut data).context(KbinErrorKind::DataRead)?; - trace!("data_buf_read => size: {}, data: 0x{:02x?}", data.len(), data); + trace!("data_buf_read => index: {}, size: {}, data: 0x{:02x?}", data_buf.position(), data.len(), data); self.data_buf_realign_reads(data_buf, None)?; Ok(data) } + fn data_buf_write(&mut self, data_buf: &mut Cursor>, data: &[u8]) -> Result<(), KbinError> { + data_buf.write_u32::(data.len() as u32).context(KbinErrorKind::DataWrite("data length integer"))?; + debug!("data_buf_write => index: {}, size: {}", data_buf.position(), data.len()); + + data_buf.write_all(data).context(KbinErrorKind::DataWrite("data block"))?; + trace!("data_buf_write => index: {}, size: {}, data: 0x{:02x?}", data_buf.position(), data.len(), data); + + self.data_buf_realign_writes(data_buf, None)?; + + Ok(()) + } + fn data_buf_read_str(&mut self, data_buf: &mut Cursor<&[u8]>, encoding: EncodingType) -> Result { let mut data = self.data_buf_read(data_buf)?; @@ -85,6 +101,15 @@ impl KbinXml { encoding.decode_bytes(data) } + fn data_buf_write_str(&mut self, data_buf: &mut Cursor>, data: &str, encoding: EncodingType) -> Result<(), KbinError> { + trace!("data_buf_write_str => input: {}", data); + + let bytes = encoding.encode_bytes(data)?; + self.data_buf_write(data_buf, &bytes)?; + + Ok(()) + } + fn data_buf_get(&mut self, data_buf: &mut Cursor<&[u8]>, size: u32) -> Result, KbinError> { let mut data = vec![0; size as usize]; data_buf.read_exact(&mut data).context(KbinErrorKind::DataRead)?; @@ -103,6 +128,7 @@ impl KbinXml { let old_pos = self.data_buf_offset(data_buf); let size = data_type.size * data_type.count; trace!("data_buf_get_aligned => old_pos: {}, size: {}", old_pos, size); + let (check_old, data) = match size { 1 => { data_buf.seek(SeekFrom::Start(self.offset_1)).context(KbinErrorKind::Seek)?; @@ -145,19 +171,95 @@ impl KbinXml { Ok(data) } - fn data_buf_realign_reads(&mut self, data_buf: &mut Cursor<&[u8]>, size: Option) -> Result<(), KbinError> { - let size = size.unwrap_or(4); - trace!("data_buf_realign => position: {}, size: {}", data_buf.position(), size); - - while data_buf.position() % size > 0 { - data_buf.seek(SeekFrom::Current(1)).context(KbinErrorKind::Seek)?; + fn data_buf_write_aligned(&mut self, data_buf: &mut Cursor>, data_type: KbinType, data: &[u8]) -> Result<(), KbinError> { + if self.offset_1 % 4 == 0 { + self.offset_1 = self.data_buf_offset(data_buf); + } + if self.offset_2 % 4 == 0 { + self.offset_2 = self.data_buf_offset(data_buf); + } + + let old_pos = self.data_buf_offset(data_buf); + let size = (data_type.size as usize) * (data_type.count as usize); + trace!("data_buf_write_aligned => old_pos: {}, size: {}", old_pos, size); + + if size != data.len() { + return Err(KbinErrorKind::SizeMismatch(data_type, size, data.len()).into()); + } + + let check_old = match size { + 1 => { + // Make room for new DWORD + if self.offset_1 % 4 == 0 { + data_buf.write_u32::(0).context(KbinErrorKind::DataWrite("empty DWORD"))?; + } + + data_buf.seek(SeekFrom::Start(self.offset_1)).context(KbinErrorKind::Seek)?; + data_buf.write_u8(data[0]).context(KbinErrorKind::DataWrite("1 byte value"))?; + self.offset_1 += 1; + + true + }, + 2 => { + // Make room for new DWORD + if self.offset_2 % 4 == 0 { + data_buf.write_u32::(0).context(KbinErrorKind::DataWrite("empty DWORD"))?; + } + + data_buf.seek(SeekFrom::Start(self.offset_2)).context(KbinErrorKind::Seek)?; + data_buf.write_u8(data[0]).context(KbinErrorKind::DataWrite("first byte of 2 byte value"))?; + data_buf.write_u8(data[1]).context(KbinErrorKind::DataWrite("second byte of 2 byte value"))?; + self.offset_2 += 2; + + true + }, + _ => { + data_buf.write_all(data).context(KbinErrorKind::DataWrite("large value"))?; + self.data_buf_realign_writes(data_buf, None)?; + + false + }, + }; + + if check_old { + data_buf.seek(SeekFrom::Start(old_pos)).context(KbinErrorKind::Seek)?; + + let trailing = max(self.offset_1, self.offset_2); + trace!("data_buf_write_aligned => old_pos: {}, trailing: {}", old_pos, trailing); + if old_pos < trailing { + data_buf.seek(SeekFrom::Start(trailing)).context(KbinErrorKind::Seek)?; + self.data_buf_realign_writes(data_buf, None)?; + } } - trace!("data_buf_realign => realigned to: {}", data_buf.position()); Ok(()) } - fn from_binary_internal(&mut self, input: &[u8]) -> Result { + fn data_buf_realign_reads(&self, data_buf: &mut Cursor<&[u8]>, size: Option) -> Result<(), KbinError> { + let size = size.unwrap_or(4); + trace!("data_buf_realign_reads => position: {}, size: {}", data_buf.position(), size); + + while data_buf.position() % size > 0 { + data_buf.seek(SeekFrom::Current(1)).context(KbinErrorKind::Seek)?; + } + trace!("data_buf_realign_reads => realigned to: {}", data_buf.position()); + + Ok(()) + } + + fn data_buf_realign_writes(&self, data_buf: &mut Cursor>, size: Option) -> Result<(), KbinError> { + let size = size.unwrap_or(4); + trace!("data_buf_realign_writes => position: {}, size: {}", data_buf.position(), size); + + while data_buf.position() % size > 0 { + data_buf.write_u8(0).context(KbinErrorKind::Seek)?; + } + trace!("data_buf_realign_writes => realigned to: {}", data_buf.position()); + + Ok(()) + } + + fn from_binary_internal(&mut self, stack: &mut Vec, input: &[u8]) -> Result { // Node buffer starts from the beginning. // Data buffer starts later after reading `len_data`. let mut node_buf = Cursor::new(&input[..]); @@ -198,7 +300,6 @@ impl KbinXml { let len_data = data_buf.read_u32::().context(KbinErrorKind::LenDataRead)?; info!("len_data: {} (0x{:x})", len_data, len_data); - let mut stack: Vec = Vec::new(); { let node_buf_end = data_buf_start.into(); while node_buf.position() < node_buf_end { @@ -316,9 +417,8 @@ impl KbinXml { Ok(stack.pop().expect("Stack must have root node")) } - fn write_node(&mut self, node_buf: &mut W, data_buf: &mut W, input: &Element) -> Result<(), KbinError> - where W: Write - { + fn write_node(&mut self, node_buf: &mut Cursor>, data_buf: &mut Cursor>, input: &Element) -> Result<(), KbinError> { + let encoding = EncodingType::SHIFT_JIS; let text = input.text(); let node_type = match input.attr("__type") { Some(name) => StandardType::from_name(name), @@ -333,16 +433,22 @@ impl KbinXml { let (array_mask, count) = match input.attr("__count") { Some(count) => { - let array_mask = 1 << 6; let count = count.parse::().context(KbinErrorKind::StringParse("array count"))?; - (array_mask, count) + debug!("write_node => __count = {}", count); + (ARRAY_MASK, count) }, None => { - (0, 0) + (0, 1) }, }; - println!("input name: {}", input.name()); + debug!("write_node => name: {}, type: {:?}, type_size: {}, type_count: {}, is_array: {}, size: {}", + input.name(), + node_type, + node_type.size, + node_type.count, + array_mask, + count); node_buf.write_u8(node_type.id | array_mask).context(KbinErrorKind::DataWrite(node_type.name))?; pack_sixbit(node_buf, input.name())?; @@ -351,23 +457,54 @@ impl KbinXml { StandardType::NodeStart => {}, StandardType::Binary => { - let bin = text.from_hex(); - println!("data: {:?}", bin); + let data = text.from_hex().context(KbinErrorKind::HexError)?; + trace!("data: 0x{:02x?}", data); + + let size = (data.len() as u32) * (node_type.size as u32); + data_buf.write_u32::(size).context(KbinErrorKind::DataWrite("binary node size"))?; + data_buf.write(&data).context(KbinErrorKind::DataWrite("binary"))?; + self.data_buf_realign_writes(data_buf, None)?; }, StandardType::String => { - println!("str: {}", text); + self.data_buf_write_str(data_buf, &text, encoding)?; }, _ => { + let data = node_type.to_bytes(&text, count as usize)?; + if array_mask > 0 { + let total_size = (count as u32) * (node_type.count as u32) * (node_type.size as u32); + trace!("write_node data_buf array => total_size: {}, data: 0x{:02x?}", total_size, data); + + data_buf.write_u32::(total_size).context(KbinErrorKind::DataWrite("node size"))?; + data_buf.write_all(&data).context(KbinErrorKind::DataWrite(node_type.name))?; + self.data_buf_realign_writes(data_buf, None)?; + } else { + self.data_buf_write_aligned(data_buf, *node_type, &data)?; + } }, } + for (key, value) in input.attrs() { + match key { + "__count" | "__size" | "__type" => continue, + _ => {}, + }; + + trace!("write_node => attr: {}, value: {}", key, value); + + self.data_buf_write_str(data_buf, value, encoding)?; + + let node_type = StandardType::Attribute; + node_buf.write_u8(node_type.id).context(KbinErrorKind::DataWrite(node_type.name))?; + pack_sixbit(node_buf, key)?; + } + for child in input.children() { self.write_node(node_buf, data_buf, child)?; } // Always has the array bit set - node_buf.write_u8(StandardType::NodeEnd.id | 64).context(KbinErrorKind::DataWrite("node end"))?; + node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?; Ok(()) } @@ -386,15 +523,18 @@ impl KbinXml { self.write_node(&mut node_buf, &mut data_buf, input)?; - node_buf.write_u8(StandardType::FileEnd.id | 64).context(KbinErrorKind::DataWrite("file end"))?; + node_buf.write_u8(StandardType::FileEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("file end"))?; + self.data_buf_realign_writes(&mut node_buf, None)?; let mut output = header.into_inner(); let node_buf = node_buf.into_inner(); + debug!("to_binary_internal => node_buf len: {0} (0x{0:x})", node_buf.len()); output.write_u32::(node_buf.len() as u32).context(KbinErrorKind::HeaderWrite("node buffer length"))?; output.extend_from_slice(&node_buf); let data_buf = data_buf.into_inner(); + debug!("to_binary_internal => data_buf len: {0} (0x{0:x})", data_buf.len()); output.write_u32::(data_buf.len() as u32).context(KbinErrorKind::HeaderWrite("data buffer length"))?; output.extend_from_slice(&data_buf); @@ -403,7 +543,14 @@ impl KbinXml { pub fn from_binary(input: &[u8]) -> Result { let mut kbinxml = KbinXml::new(); - kbinxml.from_binary_internal(input) + let mut stack: Vec = Vec::new(); + + kbinxml.from_binary_internal(&mut stack, input).map_err(|e| { + if let Some(first) = stack.first() { + println!("{:?}", first); + } + e + }) } pub fn to_binary(input: &Element) -> Result, KbinError> { diff --git a/src/node_types.rs b/src/node_types.rs index 642165c..429065c 100644 --- a/src/node_types.rs +++ b/src/node_types.rs @@ -1,6 +1,6 @@ use error::{KbinError, KbinErrorKind}; -use std::fmt::Write; +use std::fmt::{self, Write}; use std::ops::Deref; use byteorder::WriteBytesExt; @@ -27,9 +27,9 @@ macro_rules! number_impl { } fn to_kbin_bytes(output: &mut Vec, input: &str) -> Result<(), KbinError> { - trace!("KbinWrapperType<{}> to bytes => input: {}", stringify!($inner_type), input); - let num = input.parse::<$inner_type>().context(KbinErrorKind::StringParse(stringify!($inner_type)))?; + trace!("KbinWrapperType<{}> to bytes => input: '{}', output: {}", stringify!($inner_type), input, num); + let data = $inner_type::to_bytes($inner_type::to_be(num)); output.extend_from_slice(&data); @@ -55,9 +55,9 @@ macro_rules! number_impl { } fn to_kbin_bytes(output: &mut Vec, input: &str) -> Result<(), KbinError> { - trace!("KbinWrapperType<{}> to bytes => input: {}", stringify!($inner_type), input); - let num = input.parse::<$inner_type>().context(KbinErrorKind::StringParse(stringify!($inner_type)))?; + trace!("KbinWrapperType<{}> to bytes => input: '{}', output: {}", stringify!($inner_type), input, num); + let data = $intermediate::to_bytes($intermediate::to_be(num.to_bits())); output.extend_from_slice(&data); @@ -86,13 +86,13 @@ impl KbinWrapperType for bool { } fn to_kbin_bytes(output: &mut Vec, input: &str) -> Result<(), KbinError> { - trace!("KbinWrapperType to bytes => input: {}", input); - let value = match input { "0" => 0x00, "1" => 0x01, v => panic!("Unsupported value for boolean: {}", v), }; + + trace!("KbinWrapperType to bytes => input: '{}', output: {}", input, value); output.write_u8(value).context(KbinErrorKind::DataWrite("bool"))?; Ok(()) @@ -102,7 +102,7 @@ impl KbinWrapperType for bool { struct Ip4; impl KbinWrapperType for Ip4 { fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> { - trace!("KbinWrapperType => input: {:02x?}", input); + trace!("KbinWrapperType from bytes => input: {:02x?}", input); if input.len() != 4 { panic!("Ip4 type requires exactly 4 bytes of data, input: {:02x?}", input); @@ -115,7 +115,7 @@ impl KbinWrapperType for Ip4 { } fn to_kbin_bytes(output: &mut Vec, input: &str) -> Result<(), KbinError> { - trace!("KbinWrapperType => self: Ip4 (needs implementation!)"); + trace!("KbinWrapperType to bytes => input: '{}'", input); for part in input.split('.') { let num = part.parse::().context(KbinErrorKind::StringParse("ip4 segment"))?; @@ -158,13 +158,18 @@ impl KbinType { { let size = self.size as usize; let count = self.count as usize; + let total_nodes = count * arr_count; + + let total_size = size * total_nodes; + if total_size != input.len() { + return Err(KbinErrorKind::SizeMismatch(*self, total_size, input.len()).into()); + } { let first = &input[..size]; T::from_kbin_bytes(output, first)?; } - let total_nodes = count * arr_count; for i in 1..total_nodes { let offset = i * size; let end = (i + 1) * size; @@ -209,30 +214,47 @@ impl KbinType { fn to_array(&self, output: &mut Vec, input: &str, arr_count: usize) -> Result<(), KbinError> where T: KbinWrapperType { + for part in input.split(' ') { + T::to_kbin_bytes(output, part)?; + } + + let type_size = (self.size as usize) * (self.count as usize); + let total_size = arr_count * type_size; + if total_size != output.len() { + return Err(KbinErrorKind::SizeMismatch(*self, total_size, output.len()).into()); + } + Ok(()) } - #[allow(dead_code)] - fn to_bytes_inner(&self, data_buf: &mut Vec, input: &str, arr_count: usize) -> Result<(), KbinError> + fn to_bytes_inner(&self, input: &str, arr_count: usize) -> Result, KbinError> where T: KbinWrapperType { debug!("to_bytes_inner({}) => size: {}, count: {}, input_len: {}, arr_count: {}", self.name, self.size, self.count, input.len(), arr_count); + let mut output = Vec::new(); + if self.count == -1 { panic!("Tried to write special type: {}", self.name); } else if self.count == 1 { // May have a node (i.e. Ip4) that is only a single count, but it // can be part of an array if arr_count == 1 { - T::to_kbin_bytes(data_buf, input)?; + T::to_kbin_bytes(&mut output, input)?; } else { - self.to_array::(data_buf, input, arr_count)?; + self.to_array::(&mut output, input, arr_count)?; } } else if self.count > 1 { - self.to_array::(data_buf, input, arr_count)?; + self.to_array::(&mut output, input, arr_count)?; } - Ok(()) + Ok(output) + } +} + +impl fmt::Display for KbinType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) } } @@ -286,11 +308,10 @@ macro_rules! construct_types { } } - #[allow(dead_code)] - pub fn to_bytes(&self, output: &mut Vec, input: &str, arr_count: usize) -> Result<(), KbinError> { + pub fn to_bytes(&self, input: &str, arr_count: usize) -> Result, KbinError> { match *self { $( - StandardType::$konst => self.to_bytes_inner::<$inner_type>(output, input, arr_count), + StandardType::$konst => self.to_bytes_inner::<$inner_type>(input, arr_count), )+ } }