Merge pull request #61 from oli-obk/serde

Serde
This commit is contained in:
Alex Crichton 2015-04-21 09:15:19 -07:00
commit 5dd623d3b1
4 changed files with 177 additions and 41 deletions

View file

@ -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 = "*"

View file

@ -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",

View file

@ -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.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);
de::Deserialize::deserialize(&mut Decoder::new(Value::String(k)))
.map(|v| 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()
}
}

View file

@ -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) }