mirror of
https://github.com/mbilker/kbinxml-rs.git
synced 2026-09-08 10:35:32 -05:00
ser(tuple): separate tuple and sequence processing to handle tuple types
This commit is contained in:
@@ -98,6 +98,9 @@ pub enum KbinErrorKind {
|
||||
#[fail(display = "Unable to convert from hexadecimal")]
|
||||
HexError,
|
||||
|
||||
#[fail(display = "Missing base kbin type where one is required")]
|
||||
MissingBaseType,
|
||||
|
||||
#[fail(display = "Missing type hint where one is required")]
|
||||
MissingTypeHint,
|
||||
|
||||
@@ -153,6 +156,7 @@ impl From<FromUtf8Error> for KbinError {
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Error {
|
||||
Message(String),
|
||||
StaticMessage(&'static str),
|
||||
|
||||
Wrapped(Compat<KbinError>),
|
||||
}
|
||||
@@ -179,6 +183,7 @@ impl StdError for Error {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
Error::Message(ref msg) => msg,
|
||||
Error::StaticMessage(ref msg) => msg,
|
||||
Error::Wrapped(ref err) => err.description(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,6 +287,25 @@ impl fmt::Display for KbinType {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! find_type {
|
||||
($($base:ident => [$($size:tt $alternate:ident)+])+) => {
|
||||
pub fn find_type(base: StandardType, len: usize) -> StandardType {
|
||||
match base {
|
||||
$(
|
||||
StandardType::$base => match len {
|
||||
1 => StandardType::$base,
|
||||
$(
|
||||
$size => StandardType::$alternate,
|
||||
)+
|
||||
_ => panic!("Unsupported len, base: {:?}, len: {}", base, len),
|
||||
},
|
||||
)*
|
||||
_ => panic!("Unsupported base, base: {:?}, len: {}", base, len),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! construct_types {
|
||||
(
|
||||
$(
|
||||
@@ -345,6 +364,18 @@ macro_rules! construct_types {
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
find_type! {
|
||||
S8 => [ 2 S8_2 3 S8_3 4 S8_4 ]
|
||||
U8 => [ 2 U8_2 3 U8_3 4 U8_4 ]
|
||||
S16 => [ 2 S16_2 3 S16_3 4 S16_4 ]
|
||||
U16 => [ 2 U16_2 3 U16_3 4 U16_4 ]
|
||||
S32 => [ 2 S32_2 3 S32_3 4 S32_4 ]
|
||||
U32 => [ 2 U32_2 3 U32_3 4 U32_4 ]
|
||||
Float => [ 2 Float2 3 Float3 4 Float4 ]
|
||||
Double => [ 2 Double2 3 Double3 4 Double4 ]
|
||||
Boolean => [ 2 Boolean2 3 Boolean3 4 Boolean4 ]
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for StandardType {
|
||||
|
||||
174
src/ser/buffer.rs
Normal file
174
src/ser/buffer.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use failure::ResultExt;
|
||||
use serde::ser::{self, Impossible, Serialize};
|
||||
|
||||
use error::{Error, KbinErrorKind};
|
||||
use node_types::StandardType;
|
||||
|
||||
pub struct BufferSerializer {
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl BufferSerializer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buffer: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_ref(&self) -> &[u8] {
|
||||
&self.buffer
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> Vec<u8> {
|
||||
self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! ser_type {
|
||||
(byte; $inner_type:ident, $method:ident, $standard_type:ident $($cast:tt)*) => {
|
||||
fn $method(self, value: $inner_type) -> Result<Self::Ok, Self::Error> {
|
||||
let node_type = StandardType::$standard_type;
|
||||
|
||||
trace!("BufferSerializer::{}(node_type: {}, value: {})", stringify!($method), stringify!($standard_type), value);
|
||||
self.buffer.write_u8(value $($cast)*).context(KbinErrorKind::DataWrite(node_type.name))?;
|
||||
|
||||
Ok(node_type)
|
||||
}
|
||||
};
|
||||
(large; $inner_type:ident, $method:ident, $write_method:ident, $standard_type:ident $($cast:tt)*) => {
|
||||
fn $method(self, value: $inner_type) -> Result<Self::Ok, Self::Error> {
|
||||
trace!(concat!("BufferSerializer::{}(node_type: {}, value: {})"), stringify!($method), stringify!($standard_type), value);
|
||||
|
||||
//self.buffer.push(Value::$standard_type(value));
|
||||
let node_type = StandardType::$standard_type;
|
||||
self.buffer.$write_method::<BigEndian>(value $($cast)*).context(KbinErrorKind::DataWrite(node_type.name))?;
|
||||
|
||||
Ok(node_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::Serializer for &'a mut BufferSerializer {
|
||||
type Ok = StandardType;
|
||||
type Error = Error;
|
||||
|
||||
type SerializeSeq = Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeTuple = Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeMap = Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeStruct = Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
ser_type!(byte; bool, serialize_bool, Boolean as u8);
|
||||
ser_type!(byte; u8, serialize_u8, U8);
|
||||
ser_type!(byte; i8, serialize_i8, S8 as u8);
|
||||
ser_type!(large; u16, serialize_u16, write_u16, U16);
|
||||
ser_type!(large; i16, serialize_i16, write_i16, S16);
|
||||
ser_type!(large; u32, serialize_u32, write_u32, U32);
|
||||
ser_type!(large; i32, serialize_i32, write_i32, S32);
|
||||
ser_type!(large; u64, serialize_u64, write_u64, U64);
|
||||
ser_type!(large; i64, serialize_i64, write_i64, S64);
|
||||
ser_type!(large; f32, serialize_f32, write_f32, Float);
|
||||
ser_type!(large; f64, serialize_f64, write_f64, Double);
|
||||
|
||||
fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_char(value: {})", value);
|
||||
Err(Error::StaticMessage("char not supported"))
|
||||
}
|
||||
|
||||
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_str(value: {})", value);
|
||||
Err(Error::StaticMessage("str not supported"))
|
||||
}
|
||||
|
||||
// Binary data is handled separately from other array types.
|
||||
// Binary data should also be the only element of its node.
|
||||
fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_bytes(value: {:02x?})", value);
|
||||
Err(Error::StaticMessage("bytes not supported"))
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_none()");
|
||||
Err(Error::StaticMessage("option not supported"))
|
||||
}
|
||||
|
||||
fn serialize_some<T>(self, _v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
trace!("BufferSerializer::serialize_some()");
|
||||
Err(Error::StaticMessage("option not supported"))
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_unit()");
|
||||
Err(Error::StaticMessage("unit not supported"))
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_unit_struct(name: {})", name);
|
||||
Err(Error::StaticMessage("unit struct not supported"))
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self, name: &'static str, variant_index: u32, variant: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_unit_variant(name: {}, variant_index: {}, variant: {})", name, variant_index, variant);
|
||||
Err(Error::StaticMessage("unit variant not supported"))
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T>(self, name: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
trace!("BufferSerializer::serialize_newtype_struct(name: {})", name);
|
||||
Err(Error::StaticMessage("newtype struct not supported"))
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T>(self, name: &'static str, variant_index: u32, variant: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
trace!("BufferSerializer::serialize_newtype_variant(name: {}, variant_index: {}, variant: {})", name, variant_index, variant);
|
||||
Err(Error::StaticMessage("newtype variant not supported"))
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_seq(len: {:?})", len);
|
||||
Err(Error::StaticMessage("sequences not supported"))
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_tuple(len: {})", len);
|
||||
Err(Error::StaticMessage("tuple not supported"))
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_tuple_struct(name: {}, len: {})", name, len);
|
||||
Err(Error::StaticMessage("tuple struct not supported"))
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_tuple_variant(name: {}, variant_index: {}, variant: {}, len: {})", name, variant_index, variant, len);
|
||||
Err(Error::StaticMessage("tuple variant not supported"))
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_map(len: {:?})", len);
|
||||
Err(Error::StaticMessage("map not supported"))
|
||||
}
|
||||
|
||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_struct(name: {}, len: {})", name, len);
|
||||
Err(Error::StaticMessage("struct not supported"))
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
trace!("BufferSerializer::serialize_struct_variant(name: {}, variant_index: {}, variant: {}, len: {})", name, variant_index, variant, len);
|
||||
Err(Error::StaticMessage("struct variant not supported"))
|
||||
}
|
||||
}
|
||||
@@ -12,14 +12,17 @@ use error::{Error, KbinError, KbinErrorKind};
|
||||
use sixbit::pack_sixbit;
|
||||
use super::{ARRAY_MASK, SIGNATURE, SIG_COMPRESSED};
|
||||
|
||||
mod buffer;
|
||||
mod custom;
|
||||
mod map;
|
||||
mod structure;
|
||||
mod seq;
|
||||
mod tuple;
|
||||
|
||||
use self::custom::Custom;
|
||||
use self::map::Map;
|
||||
use self::structure::Struct;
|
||||
use self::seq::Seq;
|
||||
use self::tuple::Tuple;
|
||||
|
||||
pub type Result<T> = StdResult<T, Error>;
|
||||
@@ -122,7 +125,7 @@ impl Serializer {
|
||||
macro_rules! ser_type {
|
||||
(byte; $inner_type:ident, $method:ident, $standard_type:ident $($cast:tt)*) => {
|
||||
fn $method(self, value: $inner_type) -> Result<Self::Ok> {
|
||||
trace!(concat!("Serializer::", stringify!($method), " => value: {}"), value);
|
||||
trace!(concat!("Serializer::", stringify!($method), "(value: {})"), value);
|
||||
|
||||
let node_type = StandardType::$standard_type;
|
||||
match self.write_mode {
|
||||
@@ -141,7 +144,7 @@ macro_rules! ser_type {
|
||||
};
|
||||
(large; $inner_type:ident, $method:ident, $write_method:ident, $standard_type:ident $($cast:tt)*) => {
|
||||
fn $method(self, value: $inner_type) -> Result<Self::Ok> {
|
||||
trace!(concat!("Serializer::", stringify!($method), " => value: {}"), value);
|
||||
trace!(concat!("Serializer::", stringify!($method), "(value: {})"), value);
|
||||
|
||||
let node_type = StandardType::$standard_type;
|
||||
match self.write_mode {
|
||||
@@ -165,7 +168,7 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
||||
type Ok = Option<TypeHint>;
|
||||
type Error = Error;
|
||||
|
||||
type SerializeSeq = Tuple<'a>;
|
||||
type SerializeSeq = Seq<'a>;
|
||||
type SerializeTuple = Tuple<'a>;
|
||||
type SerializeTupleStruct = Custom<'a>;
|
||||
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
|
||||
@@ -234,45 +237,44 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
||||
|
||||
// TODO: Figure out a good way to serialize this
|
||||
fn serialize_none(self) -> Result<Self::Ok> {
|
||||
debug!("serialize_none");
|
||||
trace!("Serializer::serialize_none()");
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn serialize_some<T>(self, v: &T) -> Result<Self::Ok>
|
||||
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
trace!("Serializer::serialize_some()");
|
||||
v.serialize(&mut *self)
|
||||
value.serialize(&mut *self)
|
||||
}
|
||||
|
||||
// TODO: Figure out a good way to serialize this
|
||||
fn serialize_unit(self) -> Result<Self::Ok> {
|
||||
debug!("serialize_unit");
|
||||
unimplemented!();
|
||||
trace!("Serializer::serialize_unit()");
|
||||
Err(Error::StaticMessage("unit not supported"))
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
|
||||
debug!("serialize_unit_struct => name: {}", name);
|
||||
let hint = name.serialize(&mut *self)?;
|
||||
Ok(hint)
|
||||
trace!("Serializer::serialize_unit_struct(name: {})", name);
|
||||
name.serialize(&mut *self)
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self, name: &'static str, variant_index: u32, variant: &'static str) -> Result<Self::Ok> {
|
||||
debug!("serialize_unit_variant => name: {}, variant_index: {}, variant: {}", name, variant_index, variant);
|
||||
trace!("Serializer::serialize_unit_variant(name: {}, variant_index: {}, variant: {})", name, variant_index, variant);
|
||||
variant.serialize(&mut *self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Self::Ok>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
debug!("serialize_newtype_struct => name: {}", name);
|
||||
trace!("Serializer::serialize_newtype_struct(name: {})", name);
|
||||
value.serialize(&mut *self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T>(self, name: &'static str, variant_index: u32, variant: &'static str, value: &T) -> Result<Self::Ok>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
debug!("serialize_newtype_variant => name: {}, variant_index: {}, variant: {}", name, variant_index, variant);
|
||||
trace!("Serializer::serialize_newtype_variant(name: {}, variant_index: {}, variant: {})", name, variant_index, variant);
|
||||
variant.serialize(&mut *self)?;
|
||||
let hint = value.serialize(&mut *self)?.map(|mut hint| {
|
||||
hint.is_array = false;
|
||||
@@ -282,24 +284,25 @@ impl<'a> ser::Serializer for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
|
||||
debug!("serialize_seq => len: {:?}", len);
|
||||
let len = len.ok_or(Error::Message("unsized sequences not supported".to_string()))?;
|
||||
Ok(Tuple::new(self, len))
|
||||
trace!("Serializer::serialize_seq(len: {:?})", len);
|
||||
|
||||
let len = len.ok_or(Error::StaticMessage("unsized sequences not supported"))?;
|
||||
Seq::new(self, len)
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
|
||||
debug!("serialize_tuple => len: {}", len);
|
||||
trace!("Serializer::serialize_tuple(len: {})", len);
|
||||
Ok(Tuple::new(self, len))
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct> {
|
||||
debug!("serialize_tuple_struct => name: {}, len: {}", name, len);
|
||||
trace!("Serializer::serialize_tuple_struct(name: {}, len: {})", name, len);
|
||||
Custom::new(self, name, len)
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeTupleVariant> {
|
||||
debug!("serialize_tuple_variant => name: {}, variant_index: {}, variant: {}, len: {}", name, variant_index, variant, len);
|
||||
Err(Error::Message("tuple variant not supported".to_string()))
|
||||
trace!("Serializer::serialize_tuple_variant(name: {}, variant_index: {}, variant: {}, len: {})", name, variant_index, variant, len);
|
||||
Err(Error::StaticMessage("tuple variant not supported"))
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||
@@ -308,13 +311,12 @@ 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);
|
||||
|
||||
trace!("Serializer::serialize_struct(name: {}, len: {})", name, len);
|
||||
Struct::new(self, name, len)
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeStructVariant> {
|
||||
debug!("serialize_struct_variant => name: {}, variant_index: {}, variant: {}, len: {}", name, variant_index, variant, len);
|
||||
Err(Error::Message("struct variant not supported".to_string()))
|
||||
trace!("Serializer::serialize_struct_variant(name: {}, variant_index: {}, variant: {}, len: {})", name, variant_index, variant, len);
|
||||
Err(Error::StaticMessage("struct variant not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
84
src/ser/seq.rs
Normal file
84
src/ser/seq.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use std::io::{Seek, SeekFrom};
|
||||
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use failure::ResultExt;
|
||||
use serde::ser::{Serialize, SerializeSeq};
|
||||
|
||||
use error::KbinErrorKind;
|
||||
use node_types::StandardType;
|
||||
use ser::{Error, Result, Serializer, TypeHint, WriteMode};
|
||||
|
||||
pub struct Seq<'a> {
|
||||
ser: &'a mut Serializer,
|
||||
|
||||
size_index: u64,
|
||||
node_type: Option<StandardType>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<'a> Seq<'a> {
|
||||
pub fn new(ser: &'a mut Serializer, len: usize) -> Result<Self> {
|
||||
trace!("Tuple::new(len: {})", len);
|
||||
|
||||
ser.write_mode = WriteMode::Array;
|
||||
|
||||
// Estimate u32 for the total size of the tuple
|
||||
let size_index = ser.data_buf.position();
|
||||
ser.data_buf.write_u32::<BigEndian>(len as u32).context(KbinErrorKind::DataWrite("size placeholder"))?;
|
||||
|
||||
Ok(Self {
|
||||
ser,
|
||||
size_index,
|
||||
node_type: None,
|
||||
len,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SerializeSeq for Seq<'a> {
|
||||
type Ok = Option<TypeHint>;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
trace!("<Seq as SerializeSeq>::serialize_element()");
|
||||
|
||||
let hint = value.serialize(&mut *self.ser)?.ok_or(KbinErrorKind::MissingTypeHint)?;
|
||||
debug!("<Seq as SerializeSeq>::serialize_element() => hint: {:?}", hint);
|
||||
|
||||
// Rust tuple types can have different types per element, this is not
|
||||
// permitted by kbin
|
||||
if let Some(node_type) = self.node_type {
|
||||
if node_type != hint.node_type {
|
||||
return Err(KbinErrorKind::TypeMismatch(*node_type, *hint.node_type).into());
|
||||
}
|
||||
} else {
|
||||
self.node_type = Some(hint.node_type);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok> {
|
||||
trace!("<Seq as SerializeSeq>::end()");
|
||||
|
||||
self.ser.write_mode = WriteMode::Single;
|
||||
self.ser.data_buf.realign_writes(None)?;
|
||||
|
||||
let node_type = self.node_type.ok_or(KbinErrorKind::InvalidState)?;
|
||||
let size = (self.len as u32) * (node_type.size as u32);
|
||||
|
||||
// Update the size estimate from the constructor
|
||||
if size as usize != self.len {
|
||||
debug!("<Seq as SerializeSeq>::end() => size correction: {}", size);
|
||||
|
||||
let current_pos = self.ser.data_buf.position();
|
||||
self.ser.data_buf.seek(SeekFrom::Start(self.size_index)).context(KbinErrorKind::Seek)?;
|
||||
self.ser.data_buf.write_u32::<BigEndian>(size).context(KbinErrorKind::DataWrite("node size"))?;
|
||||
self.ser.data_buf.seek(SeekFrom::Start(current_pos)).context(KbinErrorKind::Seek)?;
|
||||
}
|
||||
|
||||
Ok(Some(TypeHint { node_type, is_array: true, count: self.len }))
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,47 @@
|
||||
use std::io::{Seek, SeekFrom};
|
||||
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use failure::ResultExt;
|
||||
use serde::ser::{Serialize, SerializeSeq, SerializeTuple};
|
||||
use serde::ser::{Serialize, SerializeTuple};
|
||||
|
||||
use error::KbinErrorKind;
|
||||
use node_types::StandardType;
|
||||
use ser::{Error, Result, Serializer, TypeHint, WriteMode};
|
||||
use ser::{Error, Result, Serializer, TypeHint};
|
||||
use ser::buffer::BufferSerializer;
|
||||
|
||||
/// Tuple handler for serialization.
|
||||
///
|
||||
/// Kbin tuple types are monotype (all tuple elements have the same type)
|
||||
/// which differs from Rust's tuples that can have different types for each
|
||||
/// element.
|
||||
///
|
||||
/// This key difference is what makes it harder to seralize tuples, which is
|
||||
/// why the `BufferSerializer` is used to serialize tuple elements to an
|
||||
/// intermediate byte array before running the write logic. Kbin's write logic
|
||||
/// depends on the size of the type, which is taken care of by
|
||||
/// `ByteBuffer::write_aligned`.
|
||||
pub struct Tuple<'a> {
|
||||
ser: &'a mut Serializer,
|
||||
buffer: BufferSerializer,
|
||||
|
||||
size_index: u64,
|
||||
node_type: Option<StandardType>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<'a> Tuple<'a> {
|
||||
pub fn new(ser: &'a mut Serializer, len: usize) -> Self {
|
||||
debug!("Tuple::new(len: {})", len);
|
||||
|
||||
ser.write_mode = WriteMode::Array;
|
||||
|
||||
// Estimate u32 for the total size of the tuple
|
||||
let size_index = ser.data_buf.position();
|
||||
ser.data_buf.write_u32::<BigEndian>(len as u32).expect("Unable to write size placeholder");
|
||||
trace!("Tuple::new(len: {})", len);
|
||||
|
||||
Self {
|
||||
ser,
|
||||
size_index,
|
||||
buffer: BufferSerializer::new(),
|
||||
node_type: None,
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_standard_type(&self) -> StandardType {
|
||||
debug!("find_standard_type => len: {}", self.len);
|
||||
self.node_type.unwrap_or(StandardType::String)
|
||||
fn find_standard_type(&self) -> Result<StandardType> {
|
||||
let base = self.node_type.ok_or(KbinErrorKind::MissingBaseType)?;
|
||||
let combined = StandardType::find_type(base, self.len);
|
||||
debug!("find_standard_type => StandardType::find_type(base: {:?}, len: {}) = {:?}", base, self.len, combined);
|
||||
|
||||
Ok(combined)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,58 +52,28 @@ impl<'a> SerializeTuple for Tuple<'a> {
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
debug!("SerializeTuple: serialize_element");
|
||||
let hint = value.serialize(&mut *self.ser)?.ok_or(KbinErrorKind::MissingTypeHint)?;
|
||||
debug!("SerializeTuple: serialize_element, hint: {:?}", hint);
|
||||
let node_type = value.serialize(&mut self.buffer)?;
|
||||
|
||||
// Rust tuple types can have different types per element, this is not
|
||||
// permitted by kbin
|
||||
if let Some(node_type) = self.node_type {
|
||||
if node_type != hint.node_type {
|
||||
return Err(KbinErrorKind::TypeMismatch(*node_type, *hint.node_type).into());
|
||||
if let Some(known) = self.node_type {
|
||||
if known != node_type {
|
||||
return Err(KbinErrorKind::TypeMismatch(*known, *node_type).into());
|
||||
}
|
||||
} else {
|
||||
self.node_type = Some(hint.node_type);
|
||||
self.node_type = Some(node_type);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok> {
|
||||
debug!("SerializeTuple: end");
|
||||
let node_type = self.find_standard_type()?;
|
||||
let buffer = self.buffer.into_inner();
|
||||
debug!("<Tuple as SerializeTuple>::end() => buffer: {:?}, node_type: {:?}", buffer, node_type);
|
||||
|
||||
self.ser.write_mode = WriteMode::Single;
|
||||
self.ser.data_buf.realign_writes(None)?;
|
||||
self.ser.data_buf.write_aligned(*node_type, &buffer)?;
|
||||
|
||||
let node_type = self.find_standard_type();
|
||||
let size = (self.len as u32) * (node_type.size as u32);
|
||||
|
||||
// Update the size estimate from the constructor
|
||||
if size as usize != self.len {
|
||||
debug!("SerializeTuple: end, size correction: {}", size);
|
||||
|
||||
let current_pos = self.ser.data_buf.position();
|
||||
self.ser.data_buf.seek(SeekFrom::Start(self.size_index)).context(KbinErrorKind::Seek)?;
|
||||
self.ser.data_buf.write_u32::<BigEndian>(size).context(KbinErrorKind::DataWrite("node size"))?;
|
||||
self.ser.data_buf.seek(SeekFrom::Start(current_pos)).context(KbinErrorKind::Seek)?;
|
||||
}
|
||||
|
||||
Ok(Some(TypeHint { node_type, is_array: true, count: self.len }))
|
||||
}
|
||||
}
|
||||
|
||||
// kbin only supports sized arrays, coerce sequence types to tuple processing
|
||||
impl<'a> SerializeSeq for Tuple<'a> {
|
||||
type Ok = Option<TypeHint>;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
||||
where T: ?Sized + Serialize
|
||||
{
|
||||
<Self as SerializeTuple>::serialize_element(self, value)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok> {
|
||||
<Self as SerializeTuple>::end(self)
|
||||
Ok(Some(TypeHint::from_type(node_type)))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user