ser(map): override serialize_entry to handle key and value at the same time

This commit is contained in:
Matt Bilker
2018-08-09 05:24:46 +00:00
parent 6c1c97acda
commit 456ba2bcc9
2 changed files with 52 additions and 47 deletions

View File

@@ -1,11 +1,11 @@
use error::{KbinError, KbinErrorKind};
use std::fmt::{self, Write};
use std::ops::Deref;
use byteorder::WriteBytesExt;
use failure::ResultExt;
use error::{KbinError, KbinErrorKind};
trait KbinWrapperType<T> {
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError>;
fn to_kbin_bytes(output: &mut Vec<u8>, input: &str) -> Result<(), KbinError>;
@@ -100,6 +100,9 @@ impl KbinWrapperType<bool> for bool {
}
struct Ip4;
struct DummyConverter;
struct InvalidConverter;
impl KbinWrapperType<Ip4> for Ip4 {
fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> {
trace!("KbinWrapperType<Ip4> from bytes => input: {:02x?}", input);
@@ -126,13 +129,11 @@ impl KbinWrapperType<Ip4> for Ip4 {
}
}
struct DummyConverter;
impl KbinWrapperType<DummyConverter> for DummyConverter {
fn from_kbin_bytes(_output: &mut String, _input: &[u8]) -> Result<(), KbinError> { Ok(()) }
fn to_kbin_bytes(_output: &mut Vec<u8>, _input: &str) -> Result<(), KbinError> { Ok(()) }
}
struct InvalidConverter;
impl KbinWrapperType<InvalidConverter> for InvalidConverter {
fn from_kbin_bytes(_output: &mut String, input: &[u8]) -> Result<(), KbinError> {
panic!("Invalid kbin type converter called for input: {:02x?}", input);

View File

@@ -1,5 +1,3 @@
use std::io::{Seek, SeekFrom};
use byteorder::WriteBytesExt;
use failure::ResultExt;
use serde::ser::{Serialize, SerializeMap};
@@ -7,27 +5,34 @@ use serde::ser::{Serialize, SerializeMap};
use error::{Error, KbinErrorKind};
use node_types::StandardType;
use ser::{Result, Serializer, TypeHint, WriteMode, ARRAY_MASK};
use sixbit::pack_sixbit;
pub struct Map<'a> {
ser: &'a mut Serializer,
current_node_index: u64,
key_node_type: StandardType,
}
impl<'a> Map<'a> {
pub fn new(ser: &'a mut Serializer) -> Result<Self> {
debug!("Map::new()");
ser.write_node(TypeHint::from_type(StandardType::NodeStart))?;
ser.write_identifier("something")?;
// Restrict bounds of immutable borrow from `hierarchy` Vec
{
// The key name would have been pushed to the stack in
// `<Struct as SerializeStruct>::serialize_field` before calling
// `serialize` on the value
let name = if let Some(key) = ser.hierarchy.last() {
trace!("Map::new() => found key name: {}", key);
key
} else {
return Err(KbinErrorKind::InvalidState.into());
};
Ok(Self {
ser,
current_node_index: 0,
key_node_type: StandardType::NodeStart,
})
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)?;
}
Ok(Self { ser })
}
}
@@ -35,61 +40,60 @@ impl<'a> SerializeMap for Map<'a> {
type Ok = Option<TypeHint>;
type Error = Error;
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<()>
where K: ?Sized + Serialize,
V: ?Sized + Serialize
{
trace!("--> <Map as SerializeMap>::serialize_entry()");
// Serialize methods that return `None` will not be written
if let Some(hint) = value.serialize(&mut *self.ser)? {
let node_type = hint.node_type;
debug!("SerializeMap::serialize_entry() => hint: {:?}", hint);
// Struct handler outputs `NodeStart` event by itself. Avoid repeating it.
if node_type != StandardType::NodeStart {
self.ser.write_node(hint)?;
self.serialize_key(key)?;
if node_type != StandardType::Attribute {
self.ser.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
}
}
}
Ok(())
}
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
where T: ?Sized + Serialize
{
trace!("--> <Map as SerializeMap>::serialize_key()");
self.current_node_index = self.ser.node_buf.position();
self.ser.node_buf.write_u8(0).context(KbinErrorKind::DataWrite("placeholder"))?;
self.ser.write_mode = WriteMode::Identifier;
let hint = key.serialize(&mut *self.ser)?.ok_or(KbinErrorKind::MissingTypeHint)?;
debug!("<Map as SerializeMap>::serialize_key() => hint: {:?}", hint);
self.ser.write_mode = WriteMode::Single;
self.key_node_type = hint.node_type;
match hint.node_type {
StandardType::Attribute |
StandardType::String => Ok(()),
node_type => return Err(KbinErrorKind::TypeMismatch(*StandardType::String, *node_type).into()),
node_type => Err(KbinErrorKind::TypeMismatch(*StandardType::String, *node_type).into()),
}
}
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
fn serialize_value<T>(&mut self, _value: &T) -> Result<()>
where T: ?Sized + Serialize
{
trace!("--> <Map as SerializeMap>::serialize_value()");
let mut hint = value.serialize(&mut *self.ser)?.ok_or(KbinErrorKind::MissingTypeHint)?;
debug!("<Map as SerializeMap>::serialize_value() => hint: {:?}", hint);
// Attributes must have a string body
if self.key_node_type == StandardType::Attribute {
if hint.node_type == StandardType::String {
hint = TypeHint::from_type(StandardType::Attribute);
} else {
return Err(KbinErrorKind::TypeMismatch(*StandardType::Attribute, *hint.node_type).into());
}
}
let new_pos = self.ser.node_buf.position();
self.ser.node_buf.seek(SeekFrom::Start(self.current_node_index)).context(KbinErrorKind::Seek)?;
self.ser.write_node(hint)?;
self.ser.node_buf.seek(SeekFrom::Start(new_pos)).context(KbinErrorKind::Seek)?;
if self.key_node_type != StandardType::Attribute {
self.ser.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
}
Ok(())
unimplemented!();
}
fn end(self) -> Result<Self::Ok> {
trace!("<Map as SerializeMap>::end()");
self.ser.node_buf.write_u8(StandardType::NodeEnd.id | ARRAY_MASK).context(KbinErrorKind::DataWrite("node end"))?;
Ok(None)
Ok(Some(TypeHint::from_type(StandardType::NodeStart)))
}
}