From 770cafbb606ced3f84a727f7b2b20602e342c9d8 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Mon, 3 Sep 2018 21:35:57 -0400 Subject: [PATCH] reader: support deserialization of decompressed identifiers --- src/compression.rs | 9 +++++---- src/lib.rs | 9 +++++---- src/reader.rs | 28 ++++++++++++++-------------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index b685525..e15c88c 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -1,4 +1,5 @@ use error::{KbinError, KbinErrorKind}; +use super::{SIG_COMPRESSED, SIG_UNCOMPRESSED}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Compression { @@ -9,16 +10,16 @@ pub enum Compression { impl Compression { pub fn from_byte(byte: u8) -> Result { match byte { - 0x42 => Ok(Compression::Compressed), - 0x45 => Ok(Compression::Uncompressed), + SIG_COMPRESSED => Ok(Compression::Compressed), + SIG_UNCOMPRESSED => Ok(Compression::Uncompressed), _ => Err(KbinErrorKind::UnknownCompression.into()), } } pub fn _to_byte(&self) -> u8 { match *self { - Compression::Compressed => 0x42, - Compression::Uncompressed => 0x45, + Compression::Compressed => SIG_COMPRESSED, + Compression::Uncompressed => SIG_UNCOMPRESSED, } } } diff --git a/src/lib.rs b/src/lib.rs index 0ad83d8..1fe32f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ #![feature(int_to_from_bytes)] +#![cfg_attr(test, feature(test))] + extern crate byteorder; extern crate encoding; extern crate indexmap; @@ -13,9 +15,6 @@ extern crate serde_bytes; #[macro_use] extern crate log; #[macro_use] extern crate serde; -#[cfg(test)] -#[macro_use] extern crate serde_derive; - use std::fmt::Write as FmtWrite; use std::io::{Cursor, Write}; @@ -60,6 +59,7 @@ pub use value::Value; const SIGNATURE: u8 = 0xA0; const SIG_COMPRESSED: u8 = 0x42; +const SIG_UNCOMPRESSED: u8 = 0x45; const ARRAY_MASK: u8 = 1 << 6; // 1 << 6 = 64 @@ -81,7 +81,7 @@ impl KbinXml { } pub fn is_binary_xml(input: &[u8]) -> bool { - input.len() > 2 && input[0] == SIGNATURE && input[1] == SIG_COMPRESSED + input.len() > 2 && input[0] == SIGNATURE && (input[1] == SIG_COMPRESSED || input[1] == SIG_UNCOMPRESSED) } fn from_binary_internal(&mut self, stack: &mut Vec, input: &[u8]) -> Result<(Element, EncodingType)> { @@ -235,6 +235,7 @@ impl KbinXml { array_mask, count); + // TODO: support uncompressed node_buf.write_u8(node_type.id | array_mask).context(KbinErrorKind::DataWrite(node_type.name))?; Sixbit::pack(&mut **node_buf, input.name())?; diff --git a/src/reader.rs b/src/reader.rs index 79ae2a1..82de4cd 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -9,9 +9,10 @@ use encoding_type::EncodingType; use error::{KbinErrorKind, Result}; use node_types::StandardType; use sixbit::Sixbit; -use super::{ARRAY_MASK, SIGNATURE, SIG_COMPRESSED}; +use super::{ARRAY_MASK, SIGNATURE}; pub struct Reader<'buf> { + compression: Compression, encoding: EncodingType, pub(crate) node_buf: ByteBufferRead<'buf>, @@ -34,13 +35,8 @@ impl<'buf> Reader<'buf> { return Err(KbinErrorKind::HeaderValue("signature").into()); } - // TODO: support uncompressed let compress_byte = node_buf.read_u8().context(KbinErrorKind::HeaderRead("compression"))?; - if compress_byte != SIG_COMPRESSED { - return Err(KbinErrorKind::HeaderValue("compression").into()); - } - - let compressed = Compression::from_byte(compress_byte)?; + let compression = Compression::from_byte(compress_byte)?; let encoding_byte = node_buf.read_u8().context(KbinErrorKind::HeaderRead("encoding"))?; let encoding_negation = node_buf.read_u8().context(KbinErrorKind::HeaderRead("encoding negation"))?; @@ -49,7 +45,7 @@ impl<'buf> Reader<'buf> { return Err(KbinErrorKind::HeaderValue("encoding negation").into()); } - info!("signature: 0x{:X}, compression: 0x{:X} ({:?}), encoding: 0x{:X} ({:?})", signature, compress_byte, compressed, encoding_byte, encoding); + info!("signature: 0x{:X}, compression: 0x{:X} ({:?}), encoding: 0x{:X} ({:?})", signature, compress_byte, compression, encoding_byte, encoding); let len_node = node_buf.read_u32::().context(KbinErrorKind::LenNodeRead)?; info!("len_node: {0} (0x{0:x})", len_node); @@ -62,13 +58,10 @@ impl<'buf> Reader<'buf> { let len_data = data_buf.read_u32::().context(KbinErrorKind::LenDataRead)?; info!("len_data: {0} (0x{0:x})", len_data); - //let node_buf_end = data_buf_start.into(); - Ok(Self { + compression, encoding, - //read_mode: ReadMode::Single, - //first_struct: true, - //node_buf_end, + node_buf, data_buf, @@ -139,7 +132,14 @@ impl<'buf> Reader<'buf> { } pub fn read_node_identifier(&mut self) -> Result { - let value = Sixbit::unpack(&mut *self.node_buf)?; + let value = match self.compression { + Compression::Compressed => Sixbit::unpack(&mut *self.node_buf)?, + Compression::Uncompressed => { + let length = (self.node_buf.read_u8().context(KbinErrorKind::DataRead(1))? & !ARRAY_MASK) + 1; + let bytes = self.node_buf.get(length as u32)?; + self.encoding.decode_bytes(bytes)? + }, + }; debug!("Reader::read_node_identifier() => value: {:?}", value); self.last_node_identifier = Some(value.clone());