de(map): fix map deserialization

- This allows extra Attribute nodes to end up in a HashMap
This commit is contained in:
Matt Bilker
2018-07-19 03:17:16 +00:00
parent 563518850e
commit 8a8de533d5
2 changed files with 43 additions and 10 deletions

View File

@@ -1,7 +1,7 @@
use serde::de::{DeserializeSeed, MapAccess};
use de::{Deserializer, Result};
use error::Error;
use error::{Error, KbinErrorKind};
use node_types::StandardType;
pub struct Map<'a, 'de: 'a> {
@@ -14,6 +14,7 @@ impl<'de, 'a> Map<'a, 'de> {
}
}
// TODO: FIX THIS, it's pretty broken, but it will deserialize correctly
impl<'de, 'a> MapAccess<'de> for Map<'a, 'de> {
type Error = Error;
@@ -25,18 +26,42 @@ impl<'de, 'a> MapAccess<'de> for Map<'a, 'de> {
let (node_type, _is_array) = self.de.reader.read_node_type()?;
debug!("<Map as MapAccess>::next_key_seed() => node_type: {:?}", node_type);
if node_type == StandardType::NodeEnd {
if node_type == StandardType::NodeEnd ||
node_type == StandardType::FileEnd
{
trace!("<Map as MapAccess>::next_key_seed() => end of map");
return Ok(None);
}
seed.deserialize(&mut *self.de).map(Some)
let key = seed.deserialize(&mut *self.de).map(Some)?;
self.de.node_stack.push(node_type);
Ok(key)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where V: DeserializeSeed<'de>
{
debug!("--> <Map as MapAccess>::next_value_seed()");
seed.deserialize(&mut *self.de)
let value = seed.deserialize(&mut *self.de)?;
let popped = self.de.node_stack.pop();
debug!("<Map as MapAccess>::next_value_seed() => popped: {:?}, node_stack: {:?}", popped, self.de.node_stack);
// Consume the NodeEnd
match popped {
Some(StandardType::Attribute) |
Some(StandardType::NodeStart) => {},
Some(_) => {
let (node_type, _is_array) = self.de.reader.read_node_type()?;
if node_type != StandardType::NodeEnd {
return Err(KbinErrorKind::TypeMismatch(*StandardType::NodeEnd, *node_type).into());
}
},
None => {},
}
Ok(value)
}
}

View File

@@ -286,14 +286,13 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
fn deserialize_struct<V>(self, name: &'static str, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where V: Visitor<'de>
{
trace!("Deserializer::deserialize_struct(name: {:?})", name);
trace!("Deserializer::deserialize_struct() => fields: {:?}", fields);
trace!("Deserializer::deserialize_struct(name: {:?}, fields: {:?})", name, fields);
// The `NodeStart` event is consumed by `deserialize_identifier` when
// reading the parent struct, don't consume the next event.
if self.first_struct {
let (node_type, _, name) = self.read_node_with_name()?;
debug!("Deserializer::deserialize_struct() => node_type: {:?}, name: {:?}", node_type, name);
debug!("Deserializer::deserialize_struct() => node_type: {:?}, name: {:?}, last identifier: {:?}", node_type, name, self.reader.last_identifier());
// Sanity check
if node_type != StandardType::NodeStart {
@@ -317,10 +316,19 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where V: Visitor<'de>
{
trace!("Deserializer::deserialize_identifier()");
let (node_type, _) = self.reader.last_node_type().ok_or(KbinErrorKind::InvalidState)?;
trace!("Deserializer::deserialize_identifier() => last node type: {:?}", node_type);
let name = self.reader.read_node_identifier()?;
debug!("Deserializer::deserialize_identifier() => name: {}", name);
// Prefix Attribute node identifier's with "attr_" to help the serializer
let name = match (node_type, self.reader.read_node_identifier()?) {
(StandardType::Attribute, name) => format!("attr_{}", name),
(StandardType::NodeStart, name) => {
self.first_struct = false;
name
},
(_, name) => name,
};
debug!("Deserializer::deserialize_identifier() => name: '{}'", name);
// Do not use `deserialize_string`! That reads from the data buffer and
// this reads a sixbit string from the node buffer