From 222348fe9630a0c808d353da1c7ae727d679953b Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Thu, 30 Aug 2018 23:16:11 -0400 Subject: [PATCH] node: implement IntoDeserializer --- src/node/de.rs | 147 ++++++++++++++++++++++++++++++++++++++++-------- src/node/mod.rs | 13 ++++- 2 files changed, 136 insertions(+), 24 deletions(-) diff --git a/src/node/de.rs b/src/node/de.rs index b01c3e6..8bc81ee 100644 --- a/src/node/de.rs +++ b/src/node/de.rs @@ -2,7 +2,8 @@ use std::fmt::{self, Write}; use std::marker::PhantomData; use indexmap::IndexMap; -use serde::de::{self, Deserialize, DeserializeSeed, Error, EnumAccess, MapAccess, VariantAccess, Visitor}; +use serde::de::{self, Deserialize, DeserializeSeed, Error, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess, Visitor}; +use serde::de::value::MapDeserializer; use node::Node; use node_types::StandardType; @@ -16,21 +17,23 @@ impl<'de> NodeVisitor { pub(crate) fn map_to_node(node_type: StandardType, key: &str, map: &mut A) -> Result where A: MapAccess<'de> { + trace!("NodeVisitor::map_to_node(node_type: {:?})", node_type); + match node_type { StandardType::Attribute => Err(A::Error::custom("`Attribute` nodes must be handled elsewhere")), StandardType::NodeStart => { let value = try!(map.next_value_seed(NodeValueSeed(key.to_owned()))); - debug!("NodeVisitor::map_to_node() => value: {:?}", value); + debug!("NodeVisitor::map_to_node(node_type: {:?}) => value: {:?}", node_type, value); Ok(value) }, // TODO: roll up `NodeStart` and everything else into a single map handler - _ => { + node_type => { let value = try!(map.next_value()); - debug!("NodeVisitor::map_to_node() => value: {:?}", value); + debug!("NodeVisitor::map_to_node(node_type: {:?}) => value: {:?}", node_type, value); - let node = Node::new(key.to_owned(), Some(value)); - debug!("NodeVisitor::map_to_node() => node_type: {:?}, node: {:?}", node_type, node); + let node = Node::with_value(key.to_owned(), value); + debug!("NodeVisitor::map_to_node(node_type: {:?}) => node: {:?}", node_type, node); Ok(node) }, @@ -42,7 +45,7 @@ impl<'de> Visitor<'de> for NodeVisitor { type Value = Node; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("any valid kbin node") + formatter.write_str("any valid kbin node (for NodeVisitor)") } #[inline] @@ -54,9 +57,8 @@ impl<'de> Visitor<'de> for NodeVisitor { let mut attributes = None; let mut nodes = IndexMap::new(); - while let Some(key) = try!(map.next_key_seed(NodeSeed)) { - debug!("NodeVisitor::visit_map() => key: {:?}", key); - let NodeStart { key, node_type } = key; + while let Some(NodeStart { key, node_type }) = try!(map.next_key()) { + debug!("NodeVisitor::visit_map() => node_type: {:?}, key: {:?}", node_type, key); match node_type { StandardType::Attribute => { @@ -93,15 +95,29 @@ impl<'de> Visitor<'de> for NodeVisitor { } debug!("NodeVisitor::visit_map() => nodes: {:#?}", nodes); - let node = Node { - attributes, + Ok(Node { key: self.key.unwrap_or_else(|| "".to_owned()), + attributes, children: Some(nodes), value: None, - }; + }) + } - //Err(A::Error::custom("still finishing implementation")) - Ok(node) + #[inline] + fn visit_seq(self, mut seq: A) -> Result + where A: SeqAccess<'de> + { + trace!("NodeVisitor::visit_seq()"); + let key = seq.next_element()?.unwrap(); + let attributes = seq.next_element()?.unwrap(); + let children = seq.next_element()?.unwrap(); + let value = seq.next_element()?.unwrap(); + Ok(Node { + key, + attributes, + children, + value, + }) } } @@ -114,6 +130,95 @@ impl<'de> Deserialize<'de> for Node { } } +pub struct NodeDeserializer { + node: Node, + marker: PhantomData, + index: usize, +} + +impl<'de, E: Error> de::Deserializer<'de> for NodeDeserializer { + type Error = E; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result + where V: Visitor<'de> + { + trace!("NodeDeserializer::deserialize_any(key: {:?})", self.node.key); + visitor.visit_seq(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str + string bytes byte_buf option unit unit_struct newtype_struct seq + tuple tuple_struct map struct enum identifier ignored_any + } +} + +impl<'de, E: Error> SeqAccess<'de> for NodeDeserializer { + type Error = E; + + /// "Deserializes" the key, attributes as (key, string), and children as + /// (key, node) + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where T: DeserializeSeed<'de> + { + trace!("--> ::next_element_seed(index: {})", self.index); + let value = match self.index { + 0 => seed.deserialize(self.node.key.as_str().into_deserializer()).map(Some), + 1 => match self.node.attributes.take() { + Some(attributes) => { + let deserializer = MapDeserializer::new(attributes.into_iter()); + seed.deserialize(deserializer).map(Some) + }, + None => seed.deserialize(().into_deserializer()).map(Some), + }, + 2 => match self.node.children.take() { + Some(children) => { + let deserializer = MapDeserializer::new(children.into_iter()); + seed.deserialize(deserializer).map(Some) + }, + None => seed.deserialize(().into_deserializer()).map(Some), + }, + 3 => match self.node.value.take() { + Some(value) => seed.deserialize(value.into_deserializer()).map(Some), + None => seed.deserialize(().into_deserializer()).map(Some), + }, + _ => Ok(None), + }; + self.index += 1; + + value + } +} + +impl<'de, E: Error> IntoDeserializer<'de, E> for Node { + type Deserializer = NodeDeserializer; + + #[inline] + fn into_deserializer(self) -> Self::Deserializer { + NodeDeserializer { + node: self, + marker: PhantomData, + index: 0, + } + } +} + +/// A `DeserializeSeed` holder to deserialize a `Node` from `NodeDeserializer` +pub(crate) struct NodeSeed; + +impl<'de> DeserializeSeed<'de> for NodeSeed { + type Value = Node; + + #[inline] + fn deserialize(self, deserializer: D) -> Result + where D: de::Deserializer<'de> + { + // `key` will be fixed in `deserialize_seq` + deserializer.deserialize_seq(NodeVisitor { key: None }) + } +} + struct NodeValueSeed(String); impl<'de> DeserializeSeed<'de> for NodeValueSeed { @@ -130,28 +235,26 @@ impl<'de> DeserializeSeed<'de> for NodeValueSeed { /// Node classifier that gets the key name and the type of the node before the /// main `Node` object handles getting the value based on the type and the /// attributes. -pub(crate) struct NodeSeed; - #[derive(Debug)] pub(crate) struct NodeStart { pub(crate) key: String, pub(crate) node_type: StandardType, } -impl<'de> DeserializeSeed<'de> for NodeSeed { - type Value = NodeStart; - +impl<'de> Deserialize<'de> for NodeStart { #[inline] - fn deserialize(self, deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de> { + trace!("NodeStart::deserialize()"); + struct NodeVisitor; impl<'de> Visitor<'de> for NodeVisitor { type Value = NodeStart; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("valid node type") + formatter.write_str("valid node type (for NodeSeed)") } #[inline] diff --git a/src/node/mod.rs b/src/node/mod.rs index 4f2f4cf..a8096e9 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -38,12 +38,21 @@ impl fmt::Debug for Node { } impl Node { - pub fn new(key: String, value: Option) -> Self { + pub fn new(key: String) -> Self { Self { key, attributes: None, children: None, - value, + value: None, + } + } + + pub fn with_value(key: String, value: Value) -> Self { + Self { + key, + attributes: None, + children: None, + value: Some(value), } }