lib: fully working kbin writing

This commit is contained in:
Matt Bilker
2018-06-11 19:49:50 +00:00
parent 8d8df1de0f
commit c1da9724d0
5 changed files with 315 additions and 61 deletions

View File

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

View File

@@ -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<u8>) -> Result<String, KbinError> {
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<Vec<u8>, 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)
}
}

View File

@@ -3,6 +3,8 @@ use std::string::FromUtf8Error;
use failure::{Backtrace, Context, Fail};
use node_types::KbinType;
#[derive(Debug)]
pub struct KbinError {
inner: Context<KbinErrorKind>,
@@ -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 {

View File

@@ -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<T>(&self, data_buf: &Cursor<T>) -> 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<Vec<u8>, KbinError> {
let size = data_buf.read_u32::<BigEndian>().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<Vec<u8>>, data: &[u8]) -> Result<(), KbinError> {
data_buf.write_u32::<BigEndian>(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<String, KbinError> {
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<Vec<u8>>, 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<Vec<u8>, 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<u64>) -> 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<Vec<u8>>, 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::<BigEndian>(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::<BigEndian>(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<Element, KbinError> {
fn data_buf_realign_reads(&self, data_buf: &mut Cursor<&[u8]>, size: Option<u64>) -> 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<Vec<u8>>, size: Option<u64>) -> 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<Element>, input: &[u8]) -> Result<Element, KbinError> {
// 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::<BigEndian>().context(KbinErrorKind::LenDataRead)?;
info!("len_data: {} (0x{:x})", len_data, len_data);
let mut stack: Vec<Element> = 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<W>(&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<Vec<u8>>, data_buf: &mut Cursor<Vec<u8>>, 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::<i8>().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::<BigEndian>(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::<BigEndian>(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::<BigEndian>(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::<BigEndian>(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<Element, KbinError> {
let mut kbinxml = KbinXml::new();
kbinxml.from_binary_internal(input)
let mut stack: Vec<Element> = 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<Vec<u8>, KbinError> {

View File

@@ -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<u8>, 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<u8>, 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<bool> for bool {
}
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
trace!("KbinWrapperType<bool> to bytes => input: {}", input);
let value = match input {
"0" => 0x00,
"1" => 0x01,
v => panic!("Unsupported value for boolean: {}", v),
};
trace!("KbinWrapperType<bool> to bytes => input: '{}', output: {}", input, value);
output.write_u8(value).context(KbinErrorKind::DataWrite("bool"))?;
Ok(())
@@ -102,7 +102,7 @@ impl KbinWrapperType<bool> for bool {
struct Ip4;
impl KbinWrapperType<Ip4> for Ip4 {
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
trace!("KbinWrapperType<Ip4> => input: {:02x?}", input);
trace!("KbinWrapperType<Ip4> 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<Ip4> for Ip4 {
}
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError> {
trace!("KbinWrapperType<Ip4> => self: Ip4 (needs implementation!)");
trace!("KbinWrapperType<Ip4> to bytes => input: '{}'", input);
for part in input.split('.') {
let num = part.parse::<u8>().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<T>(&self, output: &mut Vec<u8>, input: &str, arr_count: usize) -> Result<(), KbinError>
where T: KbinWrapperType<T>
{
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<T>(&self, data_buf: &mut Vec<u8>, input: &str, arr_count: usize) -> Result<(), KbinError>
fn to_bytes_inner<T>(&self, input: &str, arr_count: usize) -> Result<Vec<u8>, KbinError>
where T: KbinWrapperType<T>
{
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::<T>(data_buf, input, arr_count)?;
self.to_array::<T>(&mut output, input, arr_count)?;
}
} else if self.count > 1 {
self.to_array::<T>(data_buf, input, arr_count)?;
self.to_array::<T>(&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<u8>, input: &str, arr_count: usize) -> Result<(), KbinError> {
pub fn to_bytes(&self, input: &str, arr_count: usize) -> Result<Vec<u8>, 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),
)+
}
}