ser(structure): separate struct handling to separate class

This commit is contained in:
Matt Bilker
2018-07-08 18:43:29 -04:00
parent e0ac75e81f
commit 168c481ac5
2 changed files with 103 additions and 44 deletions

View File

@@ -1,5 +1,4 @@
use std::io::{Cursor, Write};
use std::mem;
use std::result::Result as StdResult;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
@@ -9,13 +8,14 @@ use serde::ser::{self, Impossible, Serialize};
use byte_buffer::ByteBufferWrite;
use encoding_type::EncodingType;
use node_types::StandardType;
use sixbit::pack_sixbit;
use super::error::{KbinError, KbinErrorKind};
mod error;
mod structure;
mod tuple;
use self::error::Error;
use self::structure::Struct;
use self::tuple::Tuple;
const SIGNATURE: u8 = 0xA0;
@@ -37,10 +37,11 @@ pub(crate) enum WriteMode {
pub struct Serializer {
encoding: EncodingType,
pub(crate) write_mode: WriteMode,
hierarchy: Vec<&'static str>,
write_mode: WriteMode,
pub(crate) node_buf: ByteBufferWrite,
pub(crate) data_buf: ByteBufferWrite,
node_buf: ByteBufferWrite,
data_buf: ByteBufferWrite,
}
#[derive(Debug)]
@@ -65,6 +66,7 @@ pub fn to_bytes<T>(value: &T) -> Result<Vec<u8>>
{
let mut serializer = Serializer {
encoding: EncodingType::SHIFT_JIS,
hierarchy: Vec::new(),
write_mode: WriteMode::Single,
node_buf: ByteBufferWrite::new(Vec::new()),
data_buf: ByteBufferWrite::new(Vec::new()),
@@ -157,7 +159,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStruct = Struct<'a>;
type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
byte_impl!(bool, serialize_bool, Boolean as u8);
@@ -280,11 +282,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
debug!("serialize_struct => name: {}, len: {}", name, len);
let node_type = StandardType::NodeStart;
self.node_buf.write_u8(node_type.id).context(KbinErrorKind::DataWrite(node_type.name))?;
pack_sixbit(&mut *self.node_buf, name)?;
Ok(self)
Struct::new(self, name, len)
}
fn serialize_struct_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeStructVariant> {
@@ -320,36 +318,3 @@ impl<'a> ser::SerializeMap for &'a mut Serializer {
Ok(None)
}
}
impl<'a> ser::SerializeStruct for &'a mut Serializer {
type Ok = Option<TypeHint>;
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where T: ?Sized + Serialize
{
let size = mem::size_of_val(value);
debug!("SerializeStruct: serialize_field, key: {}, value size: {}", key, size);
let hint = value.serialize(&mut **self)?.ok_or(KbinErrorKind::MissingTypeHint)?;
let array_mask = if hint.is_array { ARRAY_MASK } else { 0 };
debug!("SerializeStruct: serialize_field, key: {}, hint: {:?}", key, hint);
self.node_buf.write_u8(hint.node_type.id | array_mask).context(KbinErrorKind::DataWrite(hint.node_type.name))?;
pack_sixbit(&mut *self.node_buf, key)?;
// TODO: Make sure this does not prematurely end nodes
self.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
Ok(())
}
fn end(self) -> Result<Self::Ok> {
debug!("SerializeStruct: end");
self.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
trace!("SerializeStruct::end() => node_buf: {:02x?}", self.node_buf.get_ref());
Ok(Some(TypeHint::from_type(StandardType::NodeStart)))
}
}

94
src/ser/structure.rs Normal file
View File

@@ -0,0 +1,94 @@
use byteorder::WriteBytesExt;
use failure::ResultExt;
use serde::ser::{Serialize, SerializeStruct};
use node_types::StandardType;
use error::KbinErrorKind;
use ser::{Error, Result, Serializer, TypeHint, ARRAY_MASK};
use sixbit::pack_sixbit;
pub struct Struct<'a> {
ser: &'a mut Serializer,
name: &'static str,
}
impl<'a> Struct<'a> {
pub fn new(ser: &'a mut Serializer, name: &'static str, len: usize) -> Result<Self> {
debug!("Struct::new(name: {}, len: {}) => hierarchy: {:?}", name, len, ser.hierarchy);
// Restrict bounds of immutable borrow from `hierarchy` Vec
{
// The key name would have been pushed to the stack in `serialize_field`
// before calling `serialize` on the value
let name = if let Some(key) = ser.hierarchy.last() {
trace!("Struct::new(name: {}) => found key name: {}", name, key);
key
} else {
name
};
let node_type = StandardType::NodeStart;
ser.node_buf.write_u8(node_type.id).context(KbinErrorKind::DataWrite(node_type.name))?;
pack_sixbit(&mut *ser.node_buf, name)?;
}
// The `Vec` cannot be borrowed as mutable in an `else` condition because
// of the immutable borrow made in the previous if statement, so this is a
// workaround
//if ser.hierarchy.is_empty() {
ser.hierarchy.push(name);
trace!("Struct::new(name: {}) => hierarchy: {:?}", name, ser.hierarchy);
//}
Ok(Self {
ser,
name,
})
}
}
impl<'a> SerializeStruct for Struct<'a> {
type Ok = Option<TypeHint>;
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where T: ?Sized + Serialize
{
// Push key name onto stack so if the value is a struct, it will pick up
// the correct name
self.ser.hierarchy.push(key);
debug!("SerializeStruct(name: {}): serialize_field, key: {}, hierarchy: {:?}", self.name, key, self.ser.hierarchy);
let hint = value.serialize(&mut *self.ser)?.ok_or(KbinErrorKind::MissingTypeHint)?;
let node_type = hint.node_type;
let array_mask = if hint.is_array { ARRAY_MASK } else { 0 };
debug!("SerializeStruct(name: {}): serialize_field, key: {}, hint: {:?}", self.name, key, hint);
// Struct handler outputs the `NodeStart` event by itself. Avoid repeating it.
if node_type != StandardType::NodeStart {
self.ser.node_buf.write_u8(node_type.id | array_mask).context(KbinErrorKind::DataWrite(node_type.name))?;
pack_sixbit(&mut *self.ser.node_buf, key)?;
// TODO: Make sure this does not prematurely end nodes
if node_type != StandardType::Attribute {
self.ser.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
}
}
// Pop the name off the stack that was added earlier
let val = self.ser.hierarchy.pop();
debug!("SerializeStruct(name: {})::serialize_field() => popped: {:?}", self.name, val);
Ok(())
}
fn end(self) -> Result<Self::Ok> {
debug!("SerializeStruct(name: {})::end()", self.name);
self.ser.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
let val = self.ser.hierarchy.pop();
trace!("SerializeStruct(name: {})::end() => popped: {:?}, hierarchy: {:?}, node_buf: {:02x?}", self.name, val, self.ser.hierarchy, self.ser.node_buf.get_ref());
Ok(Some(TypeHint::from_type(StandardType::NodeStart)))
}
}