diff options
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | src/decoder/mod.rs | 4 | ||||
-rw-r--r-- | src/decoder/serde.rs | 189 | ||||
-rw-r--r-- | tests/serde.rs | 21 |
4 files changed, 177 insertions, 41 deletions
@@ -17,11 +17,11 @@ facilitate deserializing and serializing Rust structures. [dependencies] rustc-serialize = { optional = true, version = "0.3.0" } -serde = { optional = true, git = "https://github.com/alexcrichton/rust-serde", branch = "tweak-some-impls" } +serde = { optional = true } [features] default = ["rustc-serialize"] [dev-dependencies] rustc-serialize = "0.3" -serde_macros = { git = "https://github.com/alexcrichton/rust-serde", branch = "tweak-some-impls" } +serde_macros = "*" 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() + } } diff --git a/tests/serde.rs b/tests/serde.rs index 7e3c325..4c0cc96 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -214,14 +214,22 @@ fn hashmap() { fn tuple_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Foo(isize, String, f64); + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Bar { + whee: Foo, + } - let v = Foo(1, "foo".to_string(), 4.5); + let v = Bar { + whee: Foo(1, "foo".to_string(), 4.5) + }; assert_eq!( encode!(v), map! { - _field0, Integer(1), - _field1, Value::String("foo".to_string()), - _field2, Float(4.5) + whee, Value::Array(vec![ + Integer(1), + Value::String("foo".to_string()), + Float(4.5), + ]) } ); assert_eq!(v, decode!(Table(encode!(v)))); @@ -256,6 +264,7 @@ fn type_errors() { bar, Float(1.0) })); let a: Result<Foo, DecodeError> = Deserialize::deserialize(&mut d); + // serde uses FromPrimitive, that's why this works match a { Ok(..) => panic!("should not have decoded"), Err(e) => { @@ -278,7 +287,7 @@ fn missing_errors() { Ok(..) => panic!("should not have decoded"), Err(e) => { assert_eq!(format!("{}", e), - "expected a value of type `integer` for the key `bar`"); + "expected a value for the key `bar`"); } } } @@ -299,6 +308,8 @@ fn parse_enum() { } let v = Foo { a: E::Bar(10) }; + // technically serde is correct here. a single element tuple still is a tuple and therefor + // a sequence assert_eq!( encode!(v), map! { a, Integer(10) } |