commit
5dd623d3b1
|
@ -17,11 +17,11 @@ facilitate deserializing and serializing Rust structures.
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustc-serialize = { optional = true, version = "0.3.0" }
|
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]
|
[features]
|
||||||
default = ["rustc-serialize"]
|
default = ["rustc-serialize"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
serde_macros = { git = "https://github.com/alexcrichton/rust-serde", branch = "tweak-some-impls" }
|
serde_macros = "*"
|
||||||
|
|
|
@ -35,6 +35,8 @@ pub enum DecodeErrorKind {
|
||||||
ApplicationError(String),
|
ApplicationError(String),
|
||||||
/// A field was expected, but none was found.
|
/// A field was expected, but none was found.
|
||||||
ExpectedField(/* type */ Option<&'static str>),
|
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.
|
/// A field was found, but it had the wrong type.
|
||||||
ExpectedType(/* expected */ &'static str, /* found */ &'static str),
|
ExpectedType(/* expected */ &'static str, /* found */ &'static str),
|
||||||
/// The nth map key was expected, but none was found.
|
/// 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"),
|
None => write!(f, "expected a value"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UnknownField => write!(f, "unknown field"),
|
||||||
ExpectedType(expected, found) => {
|
ExpectedType(expected, found) => {
|
||||||
fn humanize(s: &str) -> String {
|
fn humanize(s: &str) -> String {
|
||||||
if s == "section" {
|
if s == "section" {
|
||||||
|
@ -194,6 +197,7 @@ impl error::Error for DecodeError {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ApplicationError(ref s) => &**s,
|
ApplicationError(ref s) => &**s,
|
||||||
ExpectedField(..) => "expected a field",
|
ExpectedField(..) => "expected a field",
|
||||||
|
UnknownField => "found an unknown field",
|
||||||
ExpectedType(..) => "expected a type",
|
ExpectedType(..) => "expected a type",
|
||||||
ExpectedMapKey(..) => "expected a map key",
|
ExpectedMapKey(..) => "expected a map key",
|
||||||
ExpectedMapElement(..) => "expected a map element",
|
ExpectedMapElement(..) => "expected a map element",
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use serde::de;
|
use serde::de;
|
||||||
use Value;
|
use Value;
|
||||||
use super::{Decoder, DecodeError, DecodeErrorKind};
|
use super::{Decoder, DecodeError, DecodeErrorKind};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
struct DecodeValue(Value);
|
struct MapVisitor<'a, I>(I, Option<Value>, &'a mut Option<Value>, Option<String>);
|
||||||
struct MapVisitor<I>(I, Option<Value>);
|
|
||||||
struct SubDecoder(Decoder);
|
|
||||||
|
|
||||||
fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
|
fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
|
||||||
match err {
|
match err {
|
||||||
|
@ -15,7 +14,13 @@ fn se2toml(err: de::value::Error, ty: &'static str) -> DecodeError {
|
||||||
field: Some(s.to_string()),
|
field: Some(s.to_string()),
|
||||||
kind: DecodeErrorKind::ExpectedField(Some(ty)),
|
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)) => {
|
Some(Value::Array(a)) => {
|
||||||
let len = a.len();
|
let len = a.len();
|
||||||
let iter = a.into_iter().map(DecodeValue);
|
let iter = a.into_iter();
|
||||||
let e = visitor.visit_seq(de::value::SeqDeserializer::new(iter,
|
visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml))
|
||||||
len));
|
|
||||||
e.map_err(|e| se2toml(e, "array"))
|
|
||||||
}
|
}
|
||||||
Some(Value::Table(t)) => {
|
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()),
|
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 {
|
impl de::Error for DecodeError {
|
||||||
fn syntax_error() -> DecodeError {
|
fn syntax_error() -> DecodeError {
|
||||||
DecodeError { field: None, kind: DecodeErrorKind::SyntaxError }
|
DecodeError { field: None, kind: DecodeErrorKind::SyntaxError }
|
||||||
|
@ -91,33 +169,28 @@ impl de::Error for DecodeError {
|
||||||
kind: DecodeErrorKind::ExpectedField(None),
|
kind: DecodeErrorKind::ExpectedField(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
fn unknown_field_error(name: &str) -> DecodeError {
|
||||||
|
DecodeError {
|
||||||
impl de::Deserializer for SubDecoder {
|
field: Some(name.to_string()),
|
||||||
type Error = de::value::Error;
|
kind: DecodeErrorKind::UnknownField,
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl de::value::ValueDeserializer for DecodeValue {
|
impl<'a, I> MapVisitor<'a, I> {
|
||||||
type Deserializer = SubDecoder;
|
fn remember(&mut self, v: Value) {
|
||||||
|
*self.2 = self.2.take().or(Some(Value::Table(BTreeMap::new())));
|
||||||
fn into_deserializer(self) -> SubDecoder {
|
// remember unknown field
|
||||||
SubDecoder(Decoder::new(self.0))
|
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)>
|
where I: Iterator<Item=(String, Value)>
|
||||||
{
|
{
|
||||||
type Error = DecodeError;
|
type Error = DecodeError;
|
||||||
|
@ -127,9 +200,19 @@ impl<I> de::MapVisitor for MapVisitor<I>
|
||||||
{
|
{
|
||||||
match self.0.next() {
|
match self.0.next() {
|
||||||
Some((k, v)) => {
|
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);
|
self.1 = Some(v);
|
||||||
de::Deserialize::deserialize(&mut Decoder::new(Value::String(k)))
|
Ok(Some(val))
|
||||||
.map(|v| Some(v))
|
},
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
|
@ -140,7 +223,14 @@ impl<I> de::MapVisitor for MapVisitor<I>
|
||||||
where V: de::Deserialize
|
where V: de::Deserialize
|
||||||
{
|
{
|
||||||
match self.1.take() {
|
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())
|
None => Err(de::Error::end_of_stream_error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,4 +239,35 @@ impl<I> de::MapVisitor for MapVisitor<I>
|
||||||
Ok(())
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,14 +214,22 @@ fn hashmap() {
|
||||||
fn tuple_struct() {
|
fn tuple_struct() {
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
struct Foo(isize, String, f64);
|
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!(
|
assert_eq!(
|
||||||
encode!(v),
|
encode!(v),
|
||||||
map! {
|
map! {
|
||||||
_field0, Integer(1),
|
whee, Value::Array(vec![
|
||||||
_field1, Value::String("foo".to_string()),
|
Integer(1),
|
||||||
_field2, Float(4.5)
|
Value::String("foo".to_string()),
|
||||||
|
Float(4.5),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(v, decode!(Table(encode!(v))));
|
assert_eq!(v, decode!(Table(encode!(v))));
|
||||||
|
@ -256,6 +264,7 @@ fn type_errors() {
|
||||||
bar, Float(1.0)
|
bar, Float(1.0)
|
||||||
}));
|
}));
|
||||||
let a: Result<Foo, DecodeError> = Deserialize::deserialize(&mut d);
|
let a: Result<Foo, DecodeError> = Deserialize::deserialize(&mut d);
|
||||||
|
// serde uses FromPrimitive, that's why this works
|
||||||
match a {
|
match a {
|
||||||
Ok(..) => panic!("should not have decoded"),
|
Ok(..) => panic!("should not have decoded"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -278,7 +287,7 @@ fn missing_errors() {
|
||||||
Ok(..) => panic!("should not have decoded"),
|
Ok(..) => panic!("should not have decoded"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
assert_eq!(format!("{}", 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) };
|
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!(
|
assert_eq!(
|
||||||
encode!(v),
|
encode!(v),
|
||||||
map! { a, Integer(10) }
|
map! { a, Integer(10) }
|
||||||
|
|
Loading…
Reference in a new issue