diff --git a/serde_macros/src/lib.rs b/serde_macros/src/lib.rs index 0d111aba..e74a8c52 100644 --- a/serde_macros/src/lib.rs +++ b/serde_macros/src/lib.rs @@ -320,7 +320,7 @@ fn deserialize_struct( match $token { ::serde::de::StructStart(_, _) => $struct_block, ::serde::de::MapStart(_) => $map_block, - _ => $deserializer.syntax_error(), + token => $deserializer.syntax_error(token), } ) } @@ -383,6 +383,7 @@ fn deserialize_struct_from_map( $name = Some( try!(::serde::de::Deserializable::deserialize($deserializer)) ); + false }) }) .collect(); @@ -414,6 +415,25 @@ fn deserialize_struct_from_map( .collect() ); + let error_arms: Vec = fields.iter() + .map(|&(name, span)| { + let pats = fields.iter() + .map(|&(n, _)| { + if n == name { + quote_pat!(cx, None) + } else { + quote_pat!(cx, _) + } + }) + .collect(); + + let pat = cx.pat_tuple(span, pats); + let s = cx.expr_str(span, token::get_ident(name)); + + quote_arm!(cx, $pat => { return $deserializer.missing_field_error($s); }) + }) + .collect(); + quote_expr!(cx, { $let_fields @@ -423,21 +443,27 @@ fn deserialize_struct_from_map( token => token, }; - let key = match token { - ::serde::de::Str(s) => s, - ::serde::de::String(ref s) => s.as_slice(), - _ => { return $deserializer.syntax_error(); } + let error = { + let key = match token { + ::serde::de::Str(s) => s, + ::serde::de::String(ref s) => s.as_slice(), + token => { return $deserializer.syntax_error(token); } + }; + + match key { + $key_arms + _ => true + } }; - match key { - $key_arms - _ => { return $deserializer.syntax_error(); } + if error { + return $deserializer.syntax_error(token); } } let result = match $fields_tuple { $fields_pat => $result, - _ => { return $deserializer.syntax_error(); } + $error_arms }; Ok(result) diff --git a/src/bench_bytes.rs b/src/bench_bytes.rs index 277d722e..ae31defb 100644 --- a/src/bench_bytes.rs +++ b/src/bench_bytes.rs @@ -126,8 +126,7 @@ mod deserializer { use super::{Error, EndOfStream, SyntaxError}; - use de::Deserializer; - use de::{Token, Int, SeqStart, Sep, End}; + use de; #[deriving(Eq, Show)] enum State { @@ -153,22 +152,22 @@ mod deserializer { } } - impl Iterator> for BytesDeserializer { + impl Iterator> for BytesDeserializer { #[inline] fn next(&mut self) -> Option> { match self.state { StartState => { self.state = SepOrEndState; - Some(Ok(SeqStart(self.len))) + Some(Ok(de::SeqStart(self.len))) } SepOrEndState => { match self.iter.next() { Some(value) => { - Some(Ok(Int(value))) + Some(Ok(de::Int(value))) } None => { self.state = EndState; - Some(Ok(End)) + Some(Ok(de::End)) } } } @@ -179,14 +178,19 @@ mod deserializer { } } - impl Deserializer for BytesDeserializer { + impl de::Deserializer for BytesDeserializer { #[inline] fn end_of_stream_error(&self) -> Result { Err(EndOfStream) } #[inline] - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { + Err(SyntaxError) + } + + #[inline] + fn missing_field_error(&mut self, _field: &'static str) -> Error { Err(SyntaxError) } } diff --git a/src/bench_enum.rs b/src/bench_enum.rs index d6cc149c..e2cf41c1 100644 --- a/src/bench_enum.rs +++ b/src/bench_enum.rs @@ -178,8 +178,7 @@ mod decoder { mod deserializer { use super::{Animal, Dog, Frog, Error, EndOfStream, SyntaxError}; - use de::Deserializer; - use de::{Token, Int, String, EnumStart, End}; + use de; enum State { AnimalState(Animal), @@ -202,42 +201,47 @@ mod deserializer { } } - impl Iterator> for AnimalDeserializer { + impl Iterator> for AnimalDeserializer { #[inline] - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { match self.stack.pop() { Some(AnimalState(Dog)) => { self.stack.push(EndState); - Some(Ok(EnumStart("Animal", "Dog", 0))) + Some(Ok(de::EnumStart("Animal", "Dog", 0))) } Some(AnimalState(Frog(x0, x1))) => { self.stack.push(EndState); self.stack.push(IntState(x1)); self.stack.push(StringState(x0)); - Some(Ok(EnumStart("Animal", "Frog", 2))) + Some(Ok(de::EnumStart("Animal", "Frog", 2))) } Some(IntState(x)) => { - Some(Ok(Int(x))) + Some(Ok(de::Int(x))) } Some(StringState(x)) => { - Some(Ok(String(x))) + Some(Ok(de::String(x))) } Some(EndState) => { - Some(Ok(End)) + Some(Ok(de::End)) } None => None, } } } - impl Deserializer for AnimalDeserializer { + impl de::Deserializer for AnimalDeserializer { #[inline] fn end_of_stream_error(&self) -> Result { Err(EndOfStream) } #[inline] - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { + Err(SyntaxError) + } + + #[inline] + fn missing_field_error(&self, _field: &'static str) -> Result { Err(SyntaxError) } } diff --git a/src/bench_map.rs b/src/bench_map.rs index d191930c..30439219 100644 --- a/src/bench_map.rs +++ b/src/bench_map.rs @@ -232,7 +232,12 @@ mod deserializer { } #[inline] - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { + Err(SyntaxError) + } + + #[inline] + fn missing_field_error(&self, _field: &'static str) -> Result { Err(SyntaxError) } } diff --git a/src/bench_struct.rs b/src/bench_struct.rs index 9b5bdab8..54c8aaea 100644 --- a/src/bench_struct.rs +++ b/src/bench_struct.rs @@ -256,8 +256,7 @@ mod decoder { mod deserializer { use std::collections::HashMap; use super::{Outer, Inner, Error, EndOfStream, SyntaxError}; - use de::Deserializer; - use de::{Token, Uint, Char, String, Null, TupleStart, StructStart, Str, SeqStart, MapStart, End, Option}; + use de; enum State { OuterState(Outer), @@ -288,15 +287,15 @@ mod deserializer { } } - impl Iterator> for OuterDeserializer { + impl Iterator> for OuterDeserializer { #[inline] - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { match self.stack.pop() { Some(OuterState(Outer { inner })) => { self.stack.push(EndState); self.stack.push(VecState(inner)); self.stack.push(FieldState("inner")); - Some(Ok(StructStart("Outer", 1))) + Some(Ok(de::StructStart("Outer", 1))) } Some(InnerState(Inner { a: (), b, c })) => { self.stack.push(EndState); @@ -308,16 +307,16 @@ mod deserializer { self.stack.push(NullState); self.stack.push(FieldState("a")); - Some(Ok(StructStart("Inner", 3))) + Some(Ok(de::StructStart("Inner", 3))) } - Some(FieldState(name)) => Some(Ok(Str(name))), + Some(FieldState(name)) => Some(Ok(de::Str(name))), Some(VecState(value)) => { self.stack.push(EndState); let len = value.len(); for inner in value.move_iter().rev() { self.stack.push(InnerState(inner)); } - Some(Ok(SeqStart(len))) + Some(Ok(de::SeqStart(len))) } Some(MapState(value)) => { self.stack.push(EndState); @@ -334,30 +333,35 @@ mod deserializer { } self.stack.push(StringState(key)); } - Some(Ok(MapStart(len))) + Some(Ok(de::MapStart(len))) } - Some(TupleState(len)) => Some(Ok(TupleStart(len))), - Some(NullState) => Some(Ok(Null)), - Some(UintState(x)) => Some(Ok(Uint(x))), - Some(CharState(x)) => Some(Ok(Char(x))), - Some(StringState(x)) => Some(Ok(String(x))), - Some(OptionState(x)) => Some(Ok(Option(x))), + Some(TupleState(len)) => Some(Ok(de::TupleStart(len))), + Some(NullState) => Some(Ok(de::Null)), + Some(UintState(x)) => Some(Ok(de::Uint(x))), + Some(CharState(x)) => Some(Ok(de::Char(x))), + Some(StringState(x)) => Some(Ok(de::String(x))), + Some(OptionState(x)) => Some(Ok(de::Option(x))), Some(EndState) => { - Some(Ok(End)) + Some(Ok(de::End)) } None => None, } } } - impl Deserializer for OuterDeserializer { + impl de::Deserializer for OuterDeserializer { #[inline] fn end_of_stream_error(&self) -> Result { Err(EndOfStream) } #[inline] - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { + Err(SyntaxError) + } + + #[inline] + fn missing_field_error(&self, _field: &'static str) -> Result { Err(SyntaxError) } } diff --git a/src/bench_vec.rs b/src/bench_vec.rs index 39f2a795..f175e909 100644 --- a/src/bench_vec.rs +++ b/src/bench_vec.rs @@ -300,7 +300,12 @@ mod deserializer { } #[inline] - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { + Err(SyntaxError) + } + + #[inline] + fn missing_field_error(&self, _field: &'static str) -> Result { Err(SyntaxError) } } @@ -355,7 +360,12 @@ mod deserializer { } #[inline] - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { + Err(SyntaxError) + } + + #[inline] + fn missing_field_error(&self, _field: &'static str) -> Result { Err(SyntaxError) } } diff --git a/src/de.rs b/src/de.rs index e7ce7538..a2607c36 100644 --- a/src/de.rs +++ b/src/de.rs @@ -54,7 +54,9 @@ macro_rules! to_result { pub trait Deserializer: Iterator> { fn end_of_stream_error(&self) -> Result; - fn syntax_error(&self) -> Result; + fn syntax_error(&self, token: Token) -> Result; + + fn missing_field_error(&self, field: &'static str) -> Result; #[inline] fn expect_token(&mut self) -> Result { @@ -72,10 +74,10 @@ pub trait Deserializer: Iterator> { TupleStart(_) => { match try!(self.expect_token()) { End => Ok(()), - _ => self.syntax_error(), + token => self.syntax_error(token), } } - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -83,42 +85,45 @@ pub trait Deserializer: Iterator> { fn expect_bool(&mut self, token: Token) -> Result { match token { Bool(value) => Ok(value), - _ => self.syntax_error(), + token => self.syntax_error(token), } } #[inline] fn expect_num(&mut self, token: Token) -> Result { match token { - Int(x) => to_result!(num::cast(x), self.syntax_error()), - I8(x) => to_result!(num::cast(x), self.syntax_error()), - I16(x) => to_result!(num::cast(x), self.syntax_error()), - I32(x) => to_result!(num::cast(x), self.syntax_error()), - I64(x) => to_result!(num::cast(x), self.syntax_error()), - Uint(x) => to_result!(num::cast(x), self.syntax_error()), - U8(x) => to_result!(num::cast(x), self.syntax_error()), - U16(x) => to_result!(num::cast(x), self.syntax_error()), - U32(x) => to_result!(num::cast(x), self.syntax_error()), - U64(x) => to_result!(num::cast(x), self.syntax_error()), - F32(x) => to_result!(num::cast(x), self.syntax_error()), - F64(x) => to_result!(num::cast(x), self.syntax_error()), + Int(x) => to_result!(num::cast(x), self.syntax_error(Int(x))), + I8(x) => to_result!(num::cast(x), self.syntax_error(I8(x))), + I16(x) => to_result!(num::cast(x), self.syntax_error(I16(x))), + I32(x) => to_result!(num::cast(x), self.syntax_error(I32(x))), + I64(x) => to_result!(num::cast(x), self.syntax_error(I64(x))), + Uint(x) => to_result!(num::cast(x), self.syntax_error(Uint(x))), + U8(x) => to_result!(num::cast(x), self.syntax_error(U8(x))), + U16(x) => to_result!(num::cast(x), self.syntax_error(U16(x))), + U32(x) => to_result!(num::cast(x), self.syntax_error(U32(x))), + U64(x) => to_result!(num::cast(x), self.syntax_error(U64(x))), + F32(x) => to_result!(num::cast(x), self.syntax_error(F32(x))), + F64(x) => to_result!(num::cast(x), self.syntax_error(F64(x))), + token => self.syntax_error(token), + } + } #[inline] fn expect_from_primitive(&mut self, token: Token) -> Result { match token { - Int(x) => to_result!(num::from_int(x), self.syntax_error()), - I8(x) => to_result!(num::from_i8(x), self.syntax_error()), - I16(x) => to_result!(num::from_i16(x), self.syntax_error()), - I32(x) => to_result!(num::from_i32(x), self.syntax_error()), - I64(x) => to_result!(num::from_i64(x), self.syntax_error()), - Uint(x) => to_result!(num::from_uint(x), self.syntax_error()), - U8(x) => to_result!(num::from_u8(x), self.syntax_error()), - U16(x) => to_result!(num::from_u16(x), self.syntax_error()), - U32(x) => to_result!(num::from_u32(x), self.syntax_error()), - U64(x) => to_result!(num::from_u64(x), self.syntax_error()), - F32(x) => to_result!(num::from_f32(x), self.syntax_error()), - F64(x) => to_result!(num::from_f64(x), self.syntax_error()), - _ => self.syntax_error(), + Int(x) => to_result!(num::from_int(x), self.syntax_error(Int(x))), + I8(x) => to_result!(num::from_i8(x), self.syntax_error(I8(x))), + I16(x) => to_result!(num::from_i16(x), self.syntax_error(I16(x))), + I32(x) => to_result!(num::from_i32(x), self.syntax_error(I32(x))), + I64(x) => to_result!(num::from_i64(x), self.syntax_error(I64(x))), + Uint(x) => to_result!(num::from_uint(x), self.syntax_error(Uint(x))), + U8(x) => to_result!(num::from_u8(x), self.syntax_error(U8(x))), + U16(x) => to_result!(num::from_u16(x), self.syntax_error(U16(x))), + U32(x) => to_result!(num::from_u32(x), self.syntax_error(U32(x))), + U64(x) => to_result!(num::from_u64(x), self.syntax_error(U64(x))), + F32(x) => to_result!(num::from_f32(x), self.syntax_error(F32(x))), + F64(x) => to_result!(num::from_f64(x), self.syntax_error(F64(x))), + token => self.syntax_error(token), } } @@ -126,7 +131,7 @@ pub trait Deserializer: Iterator> { fn expect_char(&mut self, token: Token) -> Result { match token { Char(value) => Ok(value), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -134,7 +139,7 @@ pub trait Deserializer: Iterator> { fn expect_str(&mut self, token: Token) -> Result<&'static str, E> { match token { Str(value) => Ok(value), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -143,7 +148,7 @@ pub trait Deserializer: Iterator> { match token { Str(value) => Ok(value.to_string()), String(value) => Ok(value), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -157,7 +162,7 @@ pub trait Deserializer: Iterator> { let value: T = try!(Deserializable::deserialize(self)); Ok(Some(value)) } - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -165,12 +170,12 @@ pub trait Deserializer: Iterator> { fn expect_tuple_start(&mut self, token: Token) -> Result { match token { TupleStart(len) => Ok(len), - _ => self.syntax_error(), + token => self.syntax_error(token), } } #[inline] - fn expect_tuple_sep< + fn expect_tuple_elt< T: Deserializable >(&mut self) -> Result { Deserializable::deserialize(self) @@ -180,7 +185,7 @@ pub trait Deserializer: Iterator> { fn expect_tuple_end(&mut self) -> Result<(), E> { match try!(self.expect_token()) { End => Ok(()), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -191,10 +196,10 @@ pub trait Deserializer: Iterator> { if name == n { Ok(()) } else { - self.syntax_error() + self.syntax_error(token) } } - _ => self.syntax_error(), + _ => self.syntax_error(token), } } @@ -205,15 +210,15 @@ pub trait Deserializer: Iterator> { match try!(self.expect_token()) { Str(n) => { if name != n { - return self.syntax_error(); + return self.syntax_error(Str(n)); } } String(n) => { if name != n.as_slice() { - return self.syntax_error(); + return self.syntax_error(String(n)); } } - _ => { return self.syntax_error(); } + token => { return self.syntax_error(token); } } Deserializable::deserialize(self) @@ -223,7 +228,7 @@ pub trait Deserializer: Iterator> { fn expect_struct_end(&mut self) -> Result<(), E> { match try!(self.expect_token()) { End => Ok(()), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -234,13 +239,13 @@ pub trait Deserializer: Iterator> { if name == n { match variants.iter().position(|variant| *variant == v) { Some(position) => Ok(position), - None => self.syntax_error(), + None => self.syntax_error(token), } } else { - self.syntax_error() + self.syntax_error(token) } } - _ => self.syntax_error(), + _ => self.syntax_error(token), } } @@ -255,7 +260,7 @@ pub trait Deserializer: Iterator> { fn expect_enum_end(&mut self) -> Result<(), E> { match try!(self.expect_token()) { End => Ok(()), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -264,7 +269,7 @@ pub trait Deserializer: Iterator> { match token { TupleStart(len) => Ok(len), SeqStart(len) => Ok(len), - _ => self.syntax_error(), + token => self.syntax_error(token), } } @@ -307,7 +312,7 @@ pub trait Deserializer: Iterator> { fn expect_map_start(&mut self, token: Token) -> Result { match token { MapStart(len) => Ok(len), - _ => self.syntax_error(), + _ => self.syntax_error(token), } } @@ -567,7 +572,7 @@ macro_rules! impl_deserialize_tuple { try!(d.expect_tuple_start(token)); let result = ($({ - let $name = try!(Deserializable::deserialize(d)); + let $name = try!(d.expect_tuple_elt()); $name },)*); @@ -617,7 +622,7 @@ impl Deserializable for IgnoreTokens { Str(_) | String(_) => { let _: IgnoreTokens = try!(Deserializable::deserialize(d)); } - _token => { return d.syntax_error(); } + _token => { return d.syntax_error(token); } } } } @@ -656,7 +661,7 @@ impl Deserializable for IgnoreTokens { } } - End => d.syntax_error(), + End => d.syntax_error(token), _ => Ok(IgnoreTokens), } @@ -716,7 +721,7 @@ impl GatherTokens { self.gather_map(d) } End => { - d.syntax_error() + d.syntax_error(token) } token => { self.tokens.push(token); @@ -752,7 +757,7 @@ impl GatherTokens { self.tokens.push(token); try!(self.gather(d)) } - _token => { return d.syntax_error(); } + token => { return d.syntax_error(token); } } } } @@ -908,6 +913,7 @@ mod tests { enum Error { EndOfStream, SyntaxError, + IncompleteValue, } ////////////////////////////////////////////////////////////////////////////// @@ -940,9 +946,13 @@ mod tests { Err(EndOfStream) } - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: Token) -> Result { Err(SyntaxError) } + + fn missing_field_error(&self, _field: &'static str) -> Result { + Err(IncompleteValue) + } } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/json/mod.rs b/src/json/mod.rs index 02546970..600a62c8 100644 --- a/src/json/mod.rs +++ b/src/json/mod.rs @@ -526,7 +526,7 @@ impl de::Deserializable for Json { object.insert(name.to_string(), List(fields)); Ok(Object(object)) } - de::End => d.syntax_error(), + de::End => d.syntax_error(de::End), } } } @@ -615,10 +615,14 @@ impl de::Deserializer for JsonDeserializer { Err(SyntaxError(EOFWhileParsingValue, 0, 0)) } - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { Err(SyntaxError(InvalidSyntax, 0, 0)) } + fn missing_field_error(&self, field: &'static str) -> Result { + Err(SyntaxError(MissingField(field), 0, 0)) + } + // Special case treating options as a nullable value. #[inline] fn expect_option< @@ -702,7 +706,7 @@ pub enum ErrorCode { InvalidUnicodeCodePoint, KeyMustBeAString, LoneLeadingSurrogateInHexEscape, - MissingField, + MissingField(&'static str), NotFourDigit, NotUtf8, TrailingCharacters, @@ -734,33 +738,28 @@ pub enum DecoderError { } */ -/// Returns a readable error string for a given error code. -pub fn error_str(error: ErrorCode) -> &'static str { - return match error { - EOFWhileParsingList => "EOF While parsing list", - EOFWhileParsingObject => "EOF While parsing object", - EOFWhileParsingString => "EOF While parsing string", - EOFWhileParsingValue => "EOF While parsing value", - ExpectedColon => "expected `:`", - InvalidEscape => "invalid escape", - InvalidNumber => "invalid number", - InvalidSyntax => "invalid syntax", - InvalidUnicodeCodePoint => "invalid unicode code point", - KeyMustBeAString => "key must be a string", - LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape", - MissingField => "missing variant", - NotFourDigit => "invalid \\u escape (not four digits)", - NotUtf8 => "contents not utf-8", - TrailingCharacters => "trailing characters", - UnexpectedEndOfHexEscape => "unexpected end of hex escape", - UnknownVariant => "unknown variant", - UnrecognizedHex => "invalid \\u escape (unrecognized hex)", - } -} - impl fmt::Show for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - error_str(*self).fmt(f) + match *self { + EOFWhileParsingList => "EOF While parsing list".fmt(f), + EOFWhileParsingObject => "EOF While parsing object".fmt(f), + EOFWhileParsingString => "EOF While parsing string".fmt(f), + EOFWhileParsingValue => "EOF While parsing value".fmt(f), + ExpectedColon => "expected `:`".fmt(f), + InvalidEscape => "invalid escape".fmt(f), + InvalidNumber => "invalid number".fmt(f), + InvalidSyntax => "invalid syntax".fmt(f), + InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f), + KeyMustBeAString => "key must be a string".fmt(f), + LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f), + MissingField(field) => write!(f, "missing field \"{}\"", field), + NotFourDigit => "invalid \\u escape (not four digits)".fmt(f), + NotUtf8 => "contents not utf-8".fmt(f), + TrailingCharacters => "trailing characters".fmt(f), + UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f), + UnknownVariant => "unknown variant".fmt(f), + UnrecognizedHex => "invalid \\u escape (unrecognized hex)".fmt(f), + } } } @@ -1982,10 +1981,14 @@ impl> de::Deserializer for Parser { Err(SyntaxError(EOFWhileParsingValue, self.line, self.col)) } - fn syntax_error(&self) -> Result { + fn syntax_error(&self, _token: de::Token) -> Result { Err(SyntaxError(InvalidSyntax, self.line, self.col)) } + fn missing_field_error(&self, field: &'static str) -> Result { + Err(SyntaxError(MissingField(field), self.line, self.col)) + } + // Special case treating options as a nullable value. #[inline] fn expect_option<