From 456ba2bcc9eb685aee75f0b20dd0302c2094fc2b Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Thu, 9 Aug 2018 05:24:46 +0000 Subject: [PATCH] ser(map): override serialize_entry to handle key and value at the same time --- src/node_types.rs | 9 ++--- src/ser/map.rs | 90 +++++++++++++++++++++++++---------------------- 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/node_types.rs b/src/node_types.rs index 3eca5b7..3134fbe 100644 --- a/src/node_types.rs +++ b/src/node_types.rs @@ -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 { fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError>; fn to_kbin_bytes(output: &mut Vec, input: &str) -> Result<(), KbinError>; @@ -100,6 +100,9 @@ impl KbinWrapperType for bool { } struct Ip4; +struct DummyConverter; +struct InvalidConverter; + impl KbinWrapperType for Ip4 { fn from_kbin_bytes(output: &mut String, input: &[u8]) -> Result<(), KbinError> { trace!("KbinWrapperType from bytes => input: {:02x?}", input); @@ -126,13 +129,11 @@ impl KbinWrapperType for Ip4 { } } -struct DummyConverter; impl KbinWrapperType for DummyConverter { fn from_kbin_bytes(_output: &mut String, _input: &[u8]) -> Result<(), KbinError> { Ok(()) } fn to_kbin_bytes(_output: &mut Vec, _input: &str) -> Result<(), KbinError> { Ok(()) } } -struct InvalidConverter; impl KbinWrapperType for InvalidConverter { fn from_kbin_bytes(_output: &mut String, input: &[u8]) -> Result<(), KbinError> { panic!("Invalid kbin type converter called for input: {:02x?}", input); diff --git a/src/ser/map.rs b/src/ser/map.rs index aa5fc52..73a5565 100644 --- a/src/ser/map.rs +++ b/src/ser/map.rs @@ -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 { 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 + // `::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; type Error = Error; + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<()> + where K: ?Sized + Serialize, + V: ?Sized + Serialize + { + trace!("--> ::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(&mut self, key: &T) -> Result<()> where T: ?Sized + Serialize { trace!("--> ::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!("::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(&mut self, value: &T) -> Result<()> + fn serialize_value(&mut self, _value: &T) -> Result<()> where T: ?Sized + Serialize { trace!("--> ::serialize_value()"); - - let mut hint = value.serialize(&mut *self.ser)?.ok_or(KbinErrorKind::MissingTypeHint)?; - debug!("::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 { trace!("::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))) } }