reader: support deserialization of decompressed identifiers

This commit is contained in:
Matt Bilker
2018-09-03 21:35:57 -04:00
parent aee6c5182b
commit 770cafbb60
3 changed files with 24 additions and 22 deletions

View File

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

View File

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

View File

@@ -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::<BigEndian>().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::<BigEndian>().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<String> {
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());