aboutsummaryrefslogtreecommitdiff
path: root/src/decoder
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-21 09:15:19 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-21 09:15:19 -0700
commit5dd623d3b1e47e5e22a430f74aaf7015fccc1380 (patch)
treee15b96d7e1656fddbaf7fb3e4a51fbd83460b98e /src/decoder
parent41563ee01b4eb3481207a88bbb2e3a54d6e96b2b (diff)
parent6e2f2c39e48fb5ec067b144ec39e9e32121615de (diff)
downloadmilf-rs-5dd623d3b1e47e5e22a430f74aaf7015fccc1380.tar.gz
milf-rs-5dd623d3b1e47e5e22a430f74aaf7015fccc1380.zip
Merge pull request #61 from oli-obk/serde
Serde
Diffstat (limited to 'src/decoder')
-rw-r--r--src/decoder/mod.rs4
-rw-r--r--src/decoder/serde.rs189
2 files changed, 159 insertions, 34 deletions
diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
index a3cc29a..62de223 100644
--- a/src/decoder/mod.rs
+++ b/src/decoder/mod.rs
@@ -35,6 +35,8 @@ pub enum DecodeErrorKind {
ApplicationError(String),
/// A field was expected, but none was found.
ExpectedField(/* type */ Option<&'static str>),
+ /// A field was found, but it was not an expected one.
+ UnknownField,
/// A field was found, but it had the wrong type.
ExpectedType(/* expected */ &'static str, /* found */ &'static str),
/// The nth map key was expected, but none was found.
@@ -149,6 +151,7 @@ impl fmt::Display for DecodeError {
None => write!(f, "expected a value"),
}
}
+ UnknownField => write!(f, "unknown field"),
ExpectedType(expected, found) => {
fn humanize(s: &str) -> String {
if s == "section" {
@@ -194,6 +197,7 @@ impl error::Error for DecodeError {
match self.kind {
ApplicationError(ref s) => &**s,
ExpectedField(..) => "expected a field",
+ UnknownField => "found an unknown field",
ExpectedType(..) => "expected a type",
ExpectedMapKey(..) => "expected a map key",
ExpectedMapElement(..) => "expected a map element",
diff --git a/src/decoder/serde.rs b/src/decoder/serde.rs
index 6f60892..048fede 100644
--- a/src/decoder/serde.rs
+++ b/src/decoder/serde.rs
@@ -1,10 +1,9 @@
use serde::de;
use Value;
use super::{Decoder, DecodeError, DecodeErrorKind};
+use std::collections::BTreeMap;
-struct DecodeValue(Value);
-struct MapVisitor<I>(I, Option<Value>);
-struct SubDecoder(Decoder);
+struct MapVisitor<'a, I>(I, Option<Value>, &'a mut Option<Value>, Option<String>);
fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
match err {
@@ -15,7 +14,13 @@ fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
field: Some(s.to_string()),
kind: DecodeErrorKind::ExpectedField(Some(ty)),
}
- }
+ },
+ de::value::Error::UnknownFieldError(s) => {
+ DecodeError {
+ field: Some(s.to_string()),
+ kind: DecodeErrorKind::UnknownField,
+ }
+ },
}
}
@@ -43,13 +48,11 @@ impl de::Deserializer for Decoder {
}
Some(Value::Array(a)) => {
let len = a.len();
- let iter = a.into_iter().map(DecodeValue);
- let e = visitor.visit_seq(de::value::SeqDeserializer::new(iter,
- len));
- e.map_err(|e| se2toml(e, "array"))
+ let iter = a.into_iter();
+ visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml))
}
Some(Value::Table(t)) => {
- visitor.visit_map(MapVisitor(t.into_iter(), None))
+ visitor.visit_map(MapVisitor(t.into_iter(), None, &mut self.toml, None))
}
None => Err(de::Error::end_of_stream_error()),
}
@@ -78,6 +81,81 @@ impl de::Deserializer for Decoder {
}
}
+struct SeqDeserializer<'a, I> {
+ iter: I,
+ len: usize,
+ toml: &'a mut Option<Value>,
+}
+
+impl<'a, I> SeqDeserializer<'a, I>
+ where I: Iterator<Item=Value>,
+{
+ pub fn new(iter: I, len: usize, toml: &'a mut Option<Value>) -> Self {
+ SeqDeserializer {
+ iter: iter,
+ len: len,
+ toml: toml,
+ }
+ }
+ fn remember(&mut self, v: Value) {
+ *self.toml = self.toml.take().or(Some(Value::Array(Vec::new())));
+ // remember unknown field
+ match self.toml.as_mut().unwrap() {
+ &mut Value::Array(ref mut a) => {
+ a.push(v);
+ },
+ _ => unreachable!(),
+ }
+ }
+}
+
+impl<'a, I> de::Deserializer for SeqDeserializer<'a, I>
+ where I: Iterator<Item=Value>,
+{
+ type Error = DecodeError;
+
+ fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
+ where V: de::Visitor,
+ {
+ visitor.visit_seq(self)
+ }
+}
+
+impl<'a, I> de::SeqVisitor for SeqDeserializer<'a, I>
+ where I: Iterator<Item=Value>
+{
+ type Error = DecodeError;
+
+ fn visit<V>(&mut self) -> Result<Option<V>, DecodeError>
+ where V: de::Deserialize
+ {
+ match self.iter.next() {
+ Some(value) => {
+ self.len -= 1;
+ let mut de = Decoder::new(value);
+ let v = try!(de::Deserialize::deserialize(&mut de));
+ if let Some(t) = de.toml {
+ self.remember(t);
+ }
+ Ok(Some(v))
+ }
+ None => Ok(None),
+ }
+ }
+
+ fn end(&mut self) -> Result<(), DecodeError> {
+ if self.len == 0 {
+ Ok(())
+ } else {
+ Err(de::Error::end_of_stream_error())
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len, Some(self.len))
+ }
+}
+
impl de::Error for DecodeError {
fn syntax_error() -> DecodeError {
DecodeError { field: None, kind: DecodeErrorKind::SyntaxError }
@@ -91,33 +169,28 @@ impl de::Error for DecodeError {
kind: DecodeErrorKind::ExpectedField(None),
}
}
-}
-
-impl de::Deserializer for SubDecoder {
- type Error = de::value::Error;
-
- fn visit<V>(&mut self, visitor: V) -> Result<V::Value, de::value::Error>
- where V: de::Visitor
- {
- self.0.visit(visitor).map_err(|e| {
- match e.kind {
- DecodeErrorKind::SyntaxError => de::value::Error::SyntaxError,
- DecodeErrorKind::EndOfStream => de::value::Error::EndOfStreamError,
- _ => de::value::Error::SyntaxError,
- }
- })
+ fn unknown_field_error(name: &str) -> DecodeError {
+ DecodeError {
+ field: Some(name.to_string()),
+ kind: DecodeErrorKind::UnknownField,
+ }
}
}
-impl de::value::ValueDeserializer for DecodeValue {
- type Deserializer = SubDecoder;
-
- fn into_deserializer(self) -> SubDecoder {
- SubDecoder(Decoder::new(self.0))
+impl<'a, I> MapVisitor<'a, I> {
+ fn remember(&mut self, v: Value) {
+ *self.2 = self.2.take().or(Some(Value::Table(BTreeMap::new())));
+ // remember unknown field
+ match self.2.as_mut().unwrap() {
+ &mut Value::Table(ref mut t) => {
+ t.insert(self.3.take().unwrap(), v);
+ },
+ _ => unreachable!(),
+ }
}
}
-impl<I> de::MapVisitor for MapVisitor<I>
+impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
where I: Iterator<Item=(String, Value)>
{
type Error = DecodeError;
@@ -127,9 +200,19 @@ impl<I> de::MapVisitor for MapVisitor<I>
{
match self.0.next() {
Some((k, v)) => {
- self.1 = Some(v);
- de::Deserialize::deserialize(&mut Decoder::new(Value::String(k)))
- .map(|v| Some(v))
+ self.3 = Some(k.clone());
+ let dec = &mut Decoder::new(Value::String(k));
+ match de::Deserialize::deserialize(dec) {
+ Err(DecodeError {kind: DecodeErrorKind::UnknownField, ..}) => {
+ self.remember(v);
+ self.visit_key()
+ }
+ Ok(val) => {
+ self.1 = Some(v);
+ Ok(Some(val))
+ },
+ Err(e) => Err(e),
+ }
}
None => Ok(None),
}
@@ -140,7 +223,14 @@ impl<I> de::MapVisitor for MapVisitor<I>
where V: de::Deserialize
{
match self.1.take() {
- Some(t) => de::Deserialize::deserialize(&mut Decoder::new(t)),
+ Some(t) => {
+ let mut dec = Decoder::new(t);
+ let v = try!(de::Deserialize::deserialize(&mut dec));
+ if let Some(t) = dec.toml {
+ self.remember(t);
+ }
+ Ok(v)
+ },
None => Err(de::Error::end_of_stream_error())
}
}
@@ -149,4 +239,35 @@ impl<I> de::MapVisitor for MapVisitor<I>
Ok(())
}
+ fn missing_field<V>(&mut self, field_name: &'static str) -> Result<V, DecodeError>
+ where V: de::Deserialize,
+ {
+ println!("missing field: {}", field_name);
+ // See if the type can deserialize from a unit.
+ match de::Deserialize::deserialize(&mut UnitDeserializer) {
+ Err(DecodeError {kind: DecodeErrorKind::SyntaxError, field}) => Err(DecodeError {
+ field: field.or(Some(field_name.to_string())),
+ kind: DecodeErrorKind::ExpectedField(None),
+ }),
+ v => v,
+ }
+ }
+}
+
+struct UnitDeserializer;
+
+impl de::Deserializer for UnitDeserializer {
+ type Error = DecodeError;
+
+ fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
+ where V: de::Visitor,
+ {
+ visitor.visit_unit()
+ }
+
+ fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, DecodeError>
+ where V: de::Visitor,
+ {
+ visitor.visit_none()
+ }
}