diff --git a/serde/Cargo.toml b/serde/Cargo.toml index ea12bf48..a57ff954 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.9.0-rc1" +version = "0.9.0-rc2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" @@ -9,6 +9,7 @@ repository = "https://github.com/serde-rs/serde" documentation = "https://docs.serde.rs/serde/" readme = "../README.md" keywords = ["serde", "serialization"] +categories = ["encoding"] include = ["Cargo.toml", "src/**/*.rs"] [features] diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs index 8402b4bd..10e95eb8 100644 --- a/serde/src/bytes.rs +++ b/serde/src/bytes.rs @@ -181,6 +181,10 @@ mod bytebuf { impl de::Visitor for ByteBufVisitor { type Value = ByteBuf; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("byte array") + } + #[inline] fn visit_unit(self) -> Result where E: de::Error, diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index ea17afd2..5c6045e6 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -32,6 +32,7 @@ use collections::enum_set::{CLike, EnumSet}; #[cfg(all(feature = "unstable", feature = "collections"))] use collections::borrow::ToOwned; +use core::fmt; use core::hash::{Hash, BuildHasher}; use core::marker::PhantomData; #[cfg(feature = "std")] @@ -60,6 +61,7 @@ use std::time::Duration; use core::nonzero::{NonZero, Zeroable}; #[cfg(feature = "unstable")] +#[allow(deprecated)] // required for impl Deserialize for NonZero use core::num::Zero; use de::{ @@ -69,7 +71,7 @@ use de::{ Error, MapVisitor, SeqVisitor, - Type, + Unexpected, VariantVisitor, Visitor, }; @@ -83,6 +85,10 @@ pub struct UnitVisitor; impl Visitor for UnitVisitor { type Value = (); + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("unit") + } + fn visit_unit(self) -> Result<(), E> where E: Error, { @@ -112,6 +118,10 @@ pub struct BoolVisitor; impl Visitor for BoolVisitor { type Value = bool; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a boolean") + } + fn visit_bool(self, v: bool) -> Result where E: Error, { @@ -124,7 +134,7 @@ impl Visitor for BoolVisitor { match s.trim_matches(::utils::Pattern_White_Space) { "true" => Ok(true), "false" => Ok(false), - _ => Err(Error::invalid_type(Type::Bool)), + _ => Err(Error::invalid_type(Unexpected::Str(s), &self)), } } } @@ -140,70 +150,59 @@ impl Deserialize for bool { /////////////////////////////////////////////////////////////////////////////// macro_rules! impl_deserialize_num_method { - ($src_ty:ty, $method:ident, $from_method:ident, $ty:expr) => { + ($ty:ident, $src_ty:ident, $method:ident, $from_method:ident, $group:ident, $group_ty:ident) => { #[inline] - fn $method(self, v: $src_ty) -> Result + fn $method(self, v: $src_ty) -> Result<$ty, E> where E: Error, { match FromPrimitive::$from_method(v) { Some(v) => Ok(v), - None => Err(Error::invalid_type($ty)), + None => Err(Error::invalid_value(Unexpected::$group(v as $group_ty), &self)), } } } } -/// A visitor that produces a primitive type. -struct PrimitiveVisitor { - marker: PhantomData, -} - -impl PrimitiveVisitor { - /// Construct a new `PrimitiveVisitor`. - #[inline] - fn new() -> Self { - PrimitiveVisitor { - marker: PhantomData, - } - } -} - -impl Visitor for PrimitiveVisitor - where T: Deserialize + FromPrimitive + str::FromStr -{ - type Value = T; - - impl_deserialize_num_method!(isize, visit_isize, from_isize, Type::Isize); - impl_deserialize_num_method!(i8, visit_i8, from_i8, Type::I8); - impl_deserialize_num_method!(i16, visit_i16, from_i16, Type::I16); - impl_deserialize_num_method!(i32, visit_i32, from_i32, Type::I32); - impl_deserialize_num_method!(i64, visit_i64, from_i64, Type::I64); - impl_deserialize_num_method!(usize, visit_usize, from_usize, Type::Usize); - impl_deserialize_num_method!(u8, visit_u8, from_u8, Type::U8); - impl_deserialize_num_method!(u16, visit_u16, from_u16, Type::U16); - impl_deserialize_num_method!(u32, visit_u32, from_u32, Type::U32); - impl_deserialize_num_method!(u64, visit_u64, from_u64, Type::U64); - impl_deserialize_num_method!(f32, visit_f32, from_f32, Type::F32); - impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64); - - #[inline] - fn visit_str(self, s: &str) -> Result - where E: Error, - { - str::FromStr::from_str(s.trim_matches(::utils::Pattern_White_Space)).or_else(|_| { - Err(Error::invalid_type(Type::Str)) - }) - } -} - macro_rules! impl_deserialize_num { - ($ty:ty, $method:ident) => { + ($ty:ident, $method:ident) => { impl Deserialize for $ty { #[inline] fn deserialize(deserializer: D) -> Result<$ty, D::Error> where D: Deserializer, { - deserializer.$method(PrimitiveVisitor::new()) + struct PrimitiveVisitor; + + impl Visitor for PrimitiveVisitor { + type Value = $ty; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(stringify!($ty)) + } + + impl_deserialize_num_method!($ty, isize, visit_isize, from_isize, Signed, i64); + impl_deserialize_num_method!($ty, i8, visit_i8, from_i8, Signed, i64); + impl_deserialize_num_method!($ty, i16, visit_i16, from_i16, Signed, i64); + impl_deserialize_num_method!($ty, i32, visit_i32, from_i32, Signed, i64); + impl_deserialize_num_method!($ty, i64, visit_i64, from_i64, Signed, i64); + impl_deserialize_num_method!($ty, usize, visit_usize, from_usize, Unsigned, u64); + impl_deserialize_num_method!($ty, u8, visit_u8, from_u8, Unsigned, u64); + impl_deserialize_num_method!($ty, u16, visit_u16, from_u16, Unsigned, u64); + impl_deserialize_num_method!($ty, u32, visit_u32, from_u32, Unsigned, u64); + impl_deserialize_num_method!($ty, u64, visit_u64, from_u64, Unsigned, u64); + impl_deserialize_num_method!($ty, f32, visit_f32, from_f32, Float, f64); + impl_deserialize_num_method!($ty, f64, visit_f64, from_f64, Float, f64); + + #[inline] + fn visit_str(self, s: &str) -> Result<$ty, E> + where E: Error, + { + str::FromStr::from_str(s.trim_matches(::utils::Pattern_White_Space)).or_else(|_| { + Err(Error::invalid_type(Unexpected::Str(s), &self)) + }) + } + } + + deserializer.$method(PrimitiveVisitor) } } } @@ -229,6 +228,10 @@ struct CharVisitor; impl Visitor for CharVisitor { type Value = char; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a character") + } + #[inline] fn visit_char(self, v: char) -> Result where E: Error, @@ -241,14 +244,9 @@ impl Visitor for CharVisitor { where E: Error, { let mut iter = v.chars(); - if let Some(v) = iter.next() { - if iter.next().is_some() { - Err(Error::invalid_type(Type::Char)) - } else { - Ok(v) - } - } else { - Err(Error::end_of_stream()) + match (iter.next(), iter.next()) { + (Some(c), None) => Ok(c), + _ => Err(Error::invalid_value(Unexpected::Str(v), &self)), } } } @@ -271,6 +269,10 @@ struct StringVisitor; impl Visitor for StringVisitor { type Value = String; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string") + } + fn visit_str(self, v: &str) -> Result where E: Error, { @@ -294,7 +296,7 @@ impl Visitor for StringVisitor { { match str::from_utf8(v) { Ok(s) => Ok(s.to_owned()), - Err(_) => Err(Error::invalid_type(Type::String)), + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), } } @@ -303,7 +305,7 @@ impl Visitor for StringVisitor { { match String::from_utf8(v) { Ok(s) => Ok(s), - Err(_) => Err(Error::invalid_type(Type::String)), + Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)), } } } @@ -328,6 +330,10 @@ impl< > Visitor for OptionVisitor { type Value = Option; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("option") + } + #[inline] fn visit_unit(self) -> Result, E> where E: Error, @@ -368,6 +374,10 @@ pub struct PhantomDataVisitor { impl Visitor for PhantomDataVisitor { type Value = PhantomData; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("unit") + } + #[inline] fn visit_unit(self) -> Result, E> where E: Error, @@ -417,6 +427,10 @@ macro_rules! seq_impl { { type Value = $ty; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence") + } + #[inline] fn visit_unit(self) -> Result<$ty, E> where E: Error, @@ -531,6 +545,10 @@ impl ArrayVisitor { impl Visitor for ArrayVisitor<[T; 0]> where T: Deserialize { type Value = [T; 0]; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an empty array") + } + #[inline] fn visit_unit(self) -> Result<[T; 0], E> where E: Error, @@ -562,6 +580,10 @@ macro_rules! array_impls { impl Visitor for ArrayVisitor<[T; $len]> where T: Deserialize { type Value = [T; $len]; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("an array of length ", $len)) + } + #[inline] fn visit_seq(self, mut visitor: V) -> Result<[T; $len], V::Error> where V: SeqVisitor, @@ -569,7 +591,7 @@ macro_rules! array_impls { $( let $name = match try!(visitor.visit()) { Some(val) => val, - None => return Err(Error::end_of_stream()), + None => return Err(Error::invalid_length(0, &self)), }; )+ @@ -645,6 +667,10 @@ macro_rules! tuple_impls { impl<$($name: Deserialize),+> Visitor for $visitor<$($name,)+> { type Value = ($($name,)+); + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("a tuple of size ", $len)) + } + #[inline] #[allow(non_snake_case)] fn visit_seq(self, mut visitor: V) -> Result<($($name,)+), V::Error> @@ -653,7 +679,7 @@ macro_rules! tuple_impls { $( let $name = match try!(visitor.visit()) { Some(value) => value, - None => return Err(Error::end_of_stream()), + None => return Err(Error::invalid_length(0, &self)), }; )+ @@ -723,6 +749,10 @@ macro_rules! map_impl { { type Value = $ty; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a map") + } + #[inline] fn visit_unit(self) -> Result<$ty, E> where E: Error, @@ -785,7 +815,7 @@ impl Deserialize for net::IpAddr { let s = try!(String::deserialize(deserializer)); match s.parse() { Ok(s) => Ok(s), - Err(err) => Err(D::Error::invalid_value(&err.to_string())), + Err(err) => Err(D::Error::custom(err)), } } } @@ -798,7 +828,7 @@ impl Deserialize for net::Ipv4Addr { let s = try!(String::deserialize(deserializer)); match s.parse() { Ok(s) => Ok(s), - Err(err) => Err(D::Error::invalid_value(&err.to_string())), + Err(err) => Err(D::Error::custom(err)), } } } @@ -811,7 +841,7 @@ impl Deserialize for net::Ipv6Addr { let s = try!(String::deserialize(deserializer)); match s.parse() { Ok(s) => Ok(s), - Err(err) => Err(D::Error::invalid_value(&err.to_string())), + Err(err) => Err(D::Error::custom(err)), } } } @@ -826,7 +856,7 @@ impl Deserialize for net::SocketAddr { let s = try!(String::deserialize(deserializer)); match s.parse() { Ok(s) => Ok(s), - Err(err) => Err(D::Error::invalid_value(&err.to_string())), + Err(err) => Err(D::Error::custom(err)), } } } @@ -839,7 +869,7 @@ impl Deserialize for net::SocketAddrV4 { let s = try!(String::deserialize(deserializer)); match s.parse() { Ok(s) => Ok(s), - Err(err) => Err(D::Error::invalid_value(&err.to_string())), + Err(err) => Err(D::Error::custom(err)), } } } @@ -852,7 +882,7 @@ impl Deserialize for net::SocketAddrV6 { let s = try!(String::deserialize(deserializer)); match s.parse() { Ok(s) => Ok(s), - Err(err) => Err(D::Error::invalid_value(&err.to_string())), + Err(err) => Err(D::Error::custom(err)), } } } @@ -866,6 +896,10 @@ struct PathBufVisitor; impl Visitor for PathBufVisitor { type Value = path::PathBuf; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("path string") + } + fn visit_str(self, v: &str) -> Result where E: Error, { @@ -875,7 +909,7 @@ impl Visitor for PathBufVisitor { fn visit_string(self, v: String) -> Result where E: Error, { - self.visit_str(&v) + Ok(From::from(v)) } } @@ -977,13 +1011,17 @@ impl Deserialize for Duration { impl Visitor for FieldVisitor { type Value = Field; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("`secs` or `nanos`") + } + fn visit_usize(self, value: usize) -> Result where E: Error, { match value { 0usize => Ok(Field::Secs), 1usize => Ok(Field::Nanos), - _ => Err(Error::invalid_value("expected a field")), + _ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)), } } @@ -993,7 +1031,7 @@ impl Deserialize for Duration { match value { "secs" => Ok(Field::Secs), "nanos" => Ok(Field::Nanos), - _ => Err(Error::unknown_field(value)), + _ => Err(Error::unknown_field(value, FIELDS)), } } @@ -1005,7 +1043,7 @@ impl Deserialize for Duration { b"nanos" => Ok(Field::Nanos), _ => { let value = String::from_utf8_lossy(value); - Err(Error::unknown_field(&value)) + Err(Error::unknown_field(&value, FIELDS)) } } } @@ -1020,19 +1058,23 @@ impl Deserialize for Duration { impl Visitor for DurationVisitor { type Value = Duration; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("struct Duration") + } + fn visit_seq(self, mut visitor: V) -> Result where V: SeqVisitor, { let secs: u64 = match try!(visitor.visit()) { Some(value) => value, None => { - return Err(Error::invalid_length(0)); + return Err(Error::invalid_length(0, &self)); } }; let nanos: u32 = match try!(visitor.visit()) { Some(value) => value, None => { - return Err(Error::invalid_length(1)); + return Err(Error::invalid_length(1, &self)); } }; Ok(Duration::new(secs, nanos)) @@ -1061,11 +1103,11 @@ impl Deserialize for Duration { } let secs = match secs { Some(secs) => secs, - None => try!(visitor.missing_field("secs")), + None => return Err(::missing_field("secs")), }; let nanos = match nanos { Some(nanos) => nanos, - None => try!(visitor.missing_field("nanos")), + None => return Err(::missing_field("nanos")), }; Ok(Duration::new(secs, nanos)) } @@ -1079,11 +1121,12 @@ impl Deserialize for Duration { /////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "unstable")] +#[allow(deprecated)] // num::Zero is deprecated but there is no replacement impl Deserialize for NonZero where T: Deserialize + PartialEq + Zeroable + Zero { fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer { let value = try!(Deserialize::deserialize(deserializer)); if value == Zero::zero() { - return Err(Error::invalid_value("expected a non-zero value")) + return Err(Error::custom("expected a non-zero value")) } unsafe { Ok(NonZero::new(value)) @@ -1112,23 +1155,15 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { impl Visitor for FieldVisitor { type Value = Field; - #[cfg(any(feature = "std", feature = "collections"))] - fn visit_usize(self, value: usize) -> Result where E: Error { - #[cfg(feature = "collections")] - use collections::string::ToString; - match value { - 0 => Ok(Field::Ok), - 1 => Ok(Field::Err), - _ => Err(Error::unknown_field(&value.to_string())), - } + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("`Ok` or `Err`") } - #[cfg(all(not(feature = "std"), not(feature = "collections")))] fn visit_usize(self, value: usize) -> Result where E: Error { match value { 0 => Ok(Field::Ok), 1 => Ok(Field::Err), - _ => Err(Error::unknown_field("some number")), + _ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)), } } @@ -1136,7 +1171,7 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { match value { "Ok" => Ok(Field::Ok), "Err" => Ok(Field::Err), - _ => Err(Error::unknown_field(value)), + _ => Err(Error::unknown_variant(value, VARIANTS)), } } @@ -1146,8 +1181,8 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { b"Err" => Ok(Field::Err), _ => { match str::from_utf8(value) { - Ok(value) => Err(Error::unknown_field(value)), - Err(_) => Err(Error::invalid_type(Type::String)), + Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)), } } } @@ -1166,6 +1201,10 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { { type Value = Result; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("enum Result") + } + fn visit_enum(self, visitor: V) -> Result, V::Error> where V: EnumVisitor { @@ -1198,6 +1237,10 @@ impl Deserialize for IgnoredAny { impl Visitor for IgnoredAnyVisitor { type Value = IgnoredAny; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("anything at all") + } + #[inline] fn visit_bool(self, _: bool) -> Result { Ok(IgnoredAny) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index f6307eab..967af350 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -8,7 +8,8 @@ use error; #[cfg(all(not(feature = "std"), feature = "collections"))] use collections::{String, Vec}; -use core::fmt; +use core::fmt::{self, Display}; +use core::marker::PhantomData; /////////////////////////////////////////////////////////////////////////////// @@ -16,208 +17,352 @@ pub mod impls; pub mod value; mod from_primitive; +// Helpers used by generated code. Not public API. +#[doc(hidden)] +pub mod private; + /////////////////////////////////////////////////////////////////////////////// -/// `Error` is a trait that allows a `Deserialize` to generically create a -/// `Deserializer` error. +/// The `Error` trait allows `Deserialize` implementations to create descriptive +/// error messages belonging to the `Deserializer` against which they are +/// currently running. +/// +/// Every `Deserializer` declares an `Error` type that encompasses both +/// general-purpose deserialization errors as well as errors specific to the +/// particular deserialization format. For example the `Error` type of +/// `serde_json` can represent errors like an invalid JSON escape sequence or an +/// unterminated string literal, in addition to the error cases that are part of +/// this trait. +/// +/// Most deserializers should only need to provide the `Error::custom` method +/// and inherit the default behavior for the other methods. pub trait Error: Sized + error::Error { /// Raised when there is general error when deserializing a type. - #[cfg(any(feature = "std", feature = "collections"))] - fn custom>(msg: T) -> Self; + fn custom(msg: T) -> Self; - /// Raised when there is general error when deserializing a type. - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - fn custom>(msg: T) -> Self; - - /// Raised when a `Deserialize` type unexpectedly hit the end of the stream. - fn end_of_stream() -> Self; - - /// Raised when a `Deserialize` was passed an incorrect type. - fn invalid_type(ty: Type) -> Self { - Error::custom(format!("Invalid type. Expected `{:?}`", ty)) - } - - /// Raised when a `Deserialize` was passed an incorrect value. - fn invalid_value(msg: &str) -> Self { - Error::custom(format!("Invalid value: {}", msg)) - } - - /// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments. + /// Raised when a `Deserialize` receives a type different from what it was + /// expecting. /// - /// The parameter `len` is the number of arguments found in the serialization. The sequence - /// may either expect more arguments or less arguments. - fn invalid_length(len: usize) -> Self { - Error::custom(format!("Invalid length: {}", len)) + /// The `unexp` argument provides information about what type was received. + /// This is the type that was present in the input file or other source data + /// of the Deserializer. + /// + /// The `exp` argument provides information about what type was being + /// expected. This is the type that is written in the program. + /// + /// For example if we try to deserialize a String out of a JSON file + /// containing an integer, the unexpected type is the integer and the + /// expected type is the string. + fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self { + struct InvalidType<'a> { + unexp: Unexpected<'a>, + exp: &'a Expected, + } + impl<'a> Display for InvalidType<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "invalid type: {}, expected {}", self.unexp, self.exp) + } + } + Error::custom(InvalidType { unexp: unexp, exp: exp }) } - /// Raised when a `Deserialize` enum type received an unexpected variant. - fn unknown_variant(field: &str) -> Self { - Error::custom(format!("Unknown variant `{}`", field)) + /// Raised when a `Deserialize` receives a value of the right type but that + /// is wrong for some other reason. + /// + /// The `unexp` argument provides information about what value was received. + /// This is the value that was present in the input file or other source + /// data of the Deserializer. + /// + /// The `exp` argument provides information about what value was being + /// expected. This is the type that is written in the program. + /// + /// For example if we try to deserialize a String out of some binary data + /// that is not valid UTF-8, the unexpected value is the bytes and the + /// expected value is a string. + fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self { + struct InvalidValue<'a> { + unexp: Unexpected<'a>, + exp: &'a Expected, + } + impl<'a> Display for InvalidValue<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "invalid value: {}, expected {}", self.unexp, self.exp) + } + } + Error::custom(InvalidValue { unexp: unexp, exp: exp }) } - /// Raised when a `Deserialize` struct type received an unexpected struct field. - fn unknown_field(field: &str) -> Self { - Error::custom(format!("Unknown field `{}`", field)) + /// Raised when deserializing a sequence or map and the input data contains + /// too many or too few elements. + /// + /// The `len` argument is the number of elements encountered. The sequence + /// or map may have expected more arguments or fewer arguments. + /// + /// The `exp` argument provides information about what data was being + /// expected. For example `exp` might say that a tuple of size 6 was + /// expected. + fn invalid_length(len: usize, exp: &Expected) -> Self { + struct InvalidLength<'a> { + len: usize, + exp: &'a Expected, + } + impl<'a> Display for InvalidLength<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "invalid length {}, expected {}", self.len, self.exp) + } + } + Error::custom(InvalidLength { len: len, exp: exp }) } - /// raised when a `deserialize` struct type did not receive a field. + /// Raised when a `Deserialize` enum type received a variant with an + /// unrecognized name. + fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { + struct UnknownVariant<'a> { + variant: &'a str, + expected: &'static [&'static str], + } + impl<'a> Display for UnknownVariant<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.expected.is_empty() { + write!(formatter, + "unknown variant `{}`, there are no variants", + self.variant) + } else { + write!(formatter, + "unknown variant `{}`, expected {}", + self.variant, + OneOf { names: self.expected }) + } + } + } + Error::custom(UnknownVariant { variant: variant, expected: expected }) + } + + /// Raised when a `Deserialize` struct type received a field with an + /// unrecognized name. + fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { + struct UnknownField<'a> { + field: &'a str, + expected: &'static [&'static str], + } + impl<'a> Display for UnknownField<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.expected.is_empty() { + write!(formatter, + "unknown field `{}`, there are no fields", + self.field) + } else { + write!(formatter, + "unknown field `{}`, expected {}", + self.field, + OneOf { names: self.expected }) + } + } + } + Error::custom(UnknownField { field: field, expected: expected }) + } + + /// Raised when a `Deserialize` struct type expected to receive a required + /// field with a particular name but that field was not present in the + /// input. fn missing_field(field: &'static str) -> Self { - Error::custom(format!("Missing field `{}`", field)) + struct MissingField { + field: &'static str, + } + impl Display for MissingField { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "missing field `{}`", self.field) + } + } + Error::custom(MissingField { field: field }) } /// Raised when a `Deserialize` struct type received more than one of the - /// same struct field. + /// same field. fn duplicate_field(field: &'static str) -> Self { - Error::custom(format!("Duplicate field `{}`", field)) + struct DuplicateField { + field: &'static str, + } + impl Display for DuplicateField { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "duplicate field `{}`", self.field) + } + } + Error::custom(DuplicateField { field: field }) } } -/// `Type` represents all the primitive types that can be deserialized. This is used by -/// `Error::invalid_type`. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Type { - /// Represents a `bool` type. - Bool, +/// `Unexpected` represents an unexpected invocation of any one of the `Visitor` +/// trait methods. +/// +/// This is used as an argument to the `invalid_type`, `invalid_value`, and +/// `invalid_length` methods of the `Error` trait to build error messages. +/// +/// ```rust +/// # use serde::de::{Error, Unexpected, Visitor}; +/// # use std::fmt; +/// # struct Example; +/// # impl Visitor for Example { +/// # type Value = (); +/// fn visit_bool(self, v: bool) -> Result +/// where E: Error +/// { +/// Err(Error::invalid_type(Unexpected::Bool(v), &self)) +/// } +/// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// # write!(formatter, "definitely not a boolean") +/// # } +/// # } +/// ``` +#[derive(Clone, PartialEq, Debug)] +pub enum Unexpected<'a> { + /// The input contained a boolean value that was not expected. + Bool(bool), - /// Represents a `usize` type. - Usize, + /// The input contained an unsigned integer `usize`, `u8`, `u16`, `u32` or + /// `u64` that was not expected. + Unsigned(u64), - /// Represents a `u8` type. - U8, + /// The input contained a signed integer `isize`, `i8`, `i16`, `i32` or + /// `i64` that was not expected. + Signed(i64), - /// Represents a `u16` type. - U16, + /// The input contained a floating point `f32` or `f64` that was not + /// expected. + Float(f64), - /// Represents a `u32` type. - U32, + /// The input contained a `char` that was not expected. + Char(char), - /// Represents a `u64` type. - U64, + /// The input contained a `&str` or `String` that was not expected. + Str(&'a str), - /// Represents a `isize` type. - Isize, + /// The input contained a `&[u8]` or `Vec` that was not expected. + Bytes(&'a [u8]), - /// Represents a `i8` type. - I8, - - /// Represents a `i16` type. - I16, - - /// Represents a `i32` type. - I32, - - /// Represents a `i64` type. - I64, - - /// Represents a `f32` type. - F32, - - /// Represents a `f64` type. - F64, - - /// Represents a `char` type. - Char, - - /// Represents a `&str` type. - Str, - - /// Represents a `String` type. - String, - - /// Represents a `()` type. + /// The input contained a unit `()` that was not expected. Unit, - /// Represents an `Option` type. + /// The input contained an `Option` that was not expected. Option, - /// Represents a sequence type. - Seq, - - /// Represents a map type. - Map, - - /// Represents a unit struct type. - UnitStruct, - - /// Represents a newtype type. + /// The input contained a newtype struct that was not expected. NewtypeStruct, - /// Represents a tuple struct type. - TupleStruct, + /// The input contained a sequence that was not expected. + Seq, - /// Represents a struct type. - Struct, + /// The input contained a map that was not expected. + Map, - /// Represents a struct field name. - FieldName, - - /// Represents a tuple type. - Tuple, - - /// Represents an `enum` type. + /// The input contained an enum that was not expected. Enum, - /// Represents an enum variant name. - VariantName, - - /// Represents a struct variant. - StructVariant, - - /// Represents a tuple variant. - TupleVariant, - - /// Represents a unit variant. + /// The input contained a unit variant that was not expected. UnitVariant, - /// Represents a newtype variant. + /// The input contained a newtype variant that was not expected. NewtypeVariant, - /// Represents a `&[u8]` type. - Bytes, + /// The input contained a tuple variant that was not expected. + TupleVariant, - /// Represents a `Vec` type. - ByteBuf, + /// The input contained a struct variant that was not expected. + StructVariant, + + /// A message stating what uncategorized thing the input contained that was + /// not expected. + /// + /// The message should be a noun or noun phrase, not capitalized and without + /// a period. An example message is "unoriginal superhero". + Other(&'a str), } -impl fmt::Display for Type { +impl<'a> fmt::Display for Unexpected<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let display = match *self { - Type::Bool => "bool", - Type::Usize => "usize", - Type::U8 => "u8", - Type::U16 => "u16", - Type::U32 => "u32", - Type::U64 => "u64", - Type::Isize => "isize", - Type::I8 => "i8", - Type::I16 => "i16", - Type::I32 => "i32", - Type::I64 => "i64", - Type::F32 => "f32", - Type::F64 => "f64", - Type::Char => "char", - Type::Str => "str", - Type::String => "string", - Type::Unit => "unit", - Type::Option => "option", - Type::Seq => "seq", - Type::Map => "map", - Type::UnitStruct => "unit struct", - Type::NewtypeStruct => "newtype struct", - Type::TupleStruct => "tuple struct", - Type::Struct => "struct", - Type::FieldName => "field name", - Type::Tuple => "tuple", - Type::Enum => "enum", - Type::VariantName => "variant name", - Type::StructVariant => "struct variant", - Type::TupleVariant => "tuple variant", - Type::UnitVariant => "unit variant", - Type::NewtypeVariant => "newtype variant", - Type::Bytes => "bytes", - Type::ByteBuf => "bytes buf", - }; - display.fmt(formatter) + use self::Unexpected::*; + match *self { + Bool(b) => write!(formatter, "boolean `{}`", b), + Unsigned(i) => write!(formatter, "integer `{}`", i), + Signed(i) => write!(formatter, "integer `{}`", i), + Float(f) => write!(formatter, "floating point `{}`", f), + Char(c) => write!(formatter, "character `{}`", c), + Str(s) => write!(formatter, "string {:?}", s), + Bytes(_) => write!(formatter, "byte array"), + Unit => write!(formatter, "unit value"), + Option => write!(formatter, "Option value"), + NewtypeStruct => write!(formatter, "newtype struct"), + Seq => write!(formatter, "sequence"), + Map => write!(formatter, "map"), + Enum => write!(formatter, "enum"), + UnitVariant => write!(formatter, "unit variant"), + NewtypeVariant => write!(formatter, "newtype variant"), + TupleVariant => write!(formatter, "tuple variant"), + StructVariant => write!(formatter, "struct variant"), + Other(other) => formatter.write_str(other), + } + } +} + +/// `Expected` represents an explanation of what data a `Visitor` was expecting +/// to receive. +/// +/// This is used as an argument to the `invalid_type`, `invalid_value`, and +/// `invalid_length` methods of the `Error` trait to build error messages. The +/// message should complete the sentence "This Visitor expects to receive ...", +/// for example the message could be "an integer between 0 and 64". The message +/// should not be capitalized and should not end with a period. +/// +/// Within the context of a `Visitor` implementation, the `Visitor` itself +/// (`&self`) is an implementation of this trait. +/// +/// ```rust +/// # use serde::de::{Error, Unexpected, Visitor}; +/// # use std::fmt; +/// # struct Example; +/// # impl Visitor for Example { +/// # type Value = (); +/// fn visit_bool(self, v: bool) -> Result +/// where E: Error +/// { +/// Err(Error::invalid_type(Unexpected::Bool(v), &self)) +/// } +/// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// # write!(formatter, "definitely not a boolean") +/// # } +/// # } +/// ``` +/// +/// Outside of a `Visitor`, `&"..."` can be used. +/// +/// ```rust +/// # use serde::de::{Error, Unexpected}; +/// # fn example() -> Result<(), E> { +/// # let v = true; +/// return Err(Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); +/// # } +/// ``` +pub trait Expected { + /// Format an explanation of what data was being expected. Same signature as + /// the `Display` and `Debug` traits. + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result; +} + +impl Expected for T where T: Visitor { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.expecting(formatter) + } +} + +impl<'a> Expected for &'a str { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self) + } +} + +impl<'a> Display for Expected + 'a { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Expected::fmt(self, formatter) } } @@ -230,6 +375,159 @@ pub trait Deserialize: Sized { where D: Deserializer; } +/// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you +/// ever find yourself looking for a way to pass data into a `Deserialize` impl, +/// this trait is the way to do it. +/// +/// As one example of stateful deserialization consider deserializing a JSON +/// array into an existing buffer. Using the `Deserialize` trait we could +/// deserialize a JSON array into a `Vec` but it would be a freshly allocated +/// `Vec`; there is no way for `Deserialize` to reuse a previously allocated +/// buffer. Using `DeserializeSeed` instead makes this possible as in the +/// example code below. +/// +/// The canonical API for stateless deserialization looks like this: +/// +/// ```rust +/// # use serde::Deserialize; +/// # enum Error {} +/// fn func() -> Result +/// # { unimplemented!() } +/// ``` +/// +/// Adjusting an API like this to support stateful deserialization is a matter +/// of accepting a seed as input: +/// +/// ```rust +/// # use serde::de::DeserializeSeed; +/// # enum Error {} +/// fn func_seed(seed: T) -> Result +/// # { unimplemented!() } +/// ``` +/// +/// In practice the majority of deserialization is stateless. An API expecting a +/// seed can be appeased by passing `std::marker::PhantomData` as a seed in the +/// case of stateless deserialization. +/// +/// # Example +/// +/// Suppose we have JSON that looks like `[[1, 2], [3, 4, 5], [6]]` and we need +/// to deserialize it into a flat representation like `vec![1, 2, 3, 4, 5, 6]`. +/// Allocating a brand new `Vec` for each subarray would be slow. Instead we +/// would like to allocate a single `Vec` and then deserialize each subarray +/// into it. This requires stateful deserialization using the DeserializeSeed +/// trait. +/// +/// ```rust +/// # use serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, SeqVisitor}; +/// # use std::fmt; +/// # use std::marker::PhantomData; +/// # +/// // A DeserializeSeed implementation that uses stateful deserialization to +/// // append array elements onto the end of an existing vector. The preexisting +/// // state ("seed") in this case is the Vec. The `deserialize` method of +/// // `ExtendVec` will be traversing the inner arrays of the JSON input and +/// // appending each integer into the existing Vec. +/// struct ExtendVec<'a, T: 'a>(&'a mut Vec); +/// +/// impl<'a, T> DeserializeSeed for ExtendVec<'a, T> +/// where T: Deserialize +/// { +/// // The return type of the `deserialize` method. This implementation +/// // appends onto an existing vector but does not create any new data +/// // structure, so the return type is (). +/// type Value = (); +/// +/// fn deserialize(self, deserializer: D) -> Result +/// where D: Deserializer +/// { +/// // Visitor implementation that will walk an inner array of the JSON +/// // input. +/// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec); +/// +/// impl<'a, T> Visitor for ExtendVecVisitor<'a, T> +/// where T: Deserialize +/// { +/// type Value = (); +/// +/// fn visit_seq(self, mut visitor: V) -> Result<(), V::Error> +/// where V: SeqVisitor +/// { +/// // Visit each element in the inner array and push it onto +/// // the existing vector. +/// while let Some(elem) = visitor.visit()? { +/// self.0.push(elem); +/// } +/// Ok(()) +/// } +/// # +/// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// # write!(formatter, "an array of integers") +/// # } +/// } +/// +/// deserializer.deserialize_seq(ExtendVecVisitor(self.0)) +/// } +/// } +/// +/// // Visitor implementation that will walk the outer array of the JSON input. +/// struct FlattenedVecVisitor(PhantomData); +/// +/// impl Visitor for FlattenedVecVisitor +/// where T: Deserialize +/// { +/// // This Visitor constructs a single Vec to hold the flattened +/// // contents of the inner arrays. +/// type Value = Vec; +/// +/// fn visit_seq(self, mut visitor: V) -> Result, V::Error> +/// where V: SeqVisitor +/// { +/// // Create a single Vec to hold the flattened contents. +/// let mut vec = Vec::new(); +/// +/// // Each iteration through this loop is one inner array. +/// while let Some(()) = visitor.visit_seed(ExtendVec(&mut vec))? { +/// // Nothing to do; inner array has been appended into `vec`. +/// } +/// +/// // Return the finished vec. +/// Ok(vec) +/// } +/// # +/// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// # write!(formatter, "an array of arrays") +/// # } +/// } +/// +/// # fn example(deserializer: D) -> Result<(), D::Error> { +/// let visitor = FlattenedVecVisitor(PhantomData); +/// let flattened: Vec = deserializer.deserialize_seq(visitor)?; +/// # Ok(()) } +/// ``` +pub trait DeserializeSeed: Sized { + /// The type produced by using this seed. + type Value; + + /// Equivalent to the more common `Deserialize::deserialize` method, except + /// with some initial piece of data (the seed) passed in. + fn deserialize(self, deserializer: D) -> Result + where D: Deserializer; +} + +impl DeserializeSeed for PhantomData + where T: Deserialize +{ + type Value = T; + + #[inline] + fn deserialize(self, deserializer: D) -> Result + where D: Deserializer + { + T::deserialize(deserializer) + } +} + /////////////////////////////////////////////////////////////////////////////// /// `Deserializer` is a trait that can deserialize values by threading a `Visitor` trait through a @@ -244,7 +542,7 @@ pub trait Deserialize: Sized { /// with the `deserialize_*` methods how it should parse the next value. One downside though to /// only supporting the `deserialize_*` types is that it does not allow for deserializing into a /// generic `json::Value`-esque type. -pub trait Deserializer { +pub trait Deserializer: Sized { /// The error type that can be returned if some error occurs during deserialization. type Error: Error; @@ -425,16 +723,62 @@ pub trait Deserializer { /////////////////////////////////////////////////////////////////////////////// /// This trait represents a visitor that walks through a deserializer. +/// +/// ```rust +/// # use serde::de::{Error, Unexpected, Visitor}; +/// # use std::fmt; +/// /// A visitor that deserializes a long string - a string containing at least +/// /// some minimum number of bytes. +/// struct LongString { +/// min: usize, +/// } +/// +/// impl Visitor for LongString { +/// type Value = String; +/// +/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// write!(formatter, "a string containing at least {} bytes", self.min) +/// } +/// +/// fn visit_str(self, s: &str) -> Result +/// where E: Error +/// { +/// if s.len() >= self.min { +/// Ok(s.to_owned()) +/// } else { +/// Err(Error::invalid_value(Unexpected::Str(s), &self)) +/// } +/// } +/// } +/// ``` pub trait Visitor: Sized { /// The value produced by this visitor. type Value; + /// Format a message stating what data this Visitor expects to receive. + /// + /// This is used in error messages. The message should complete the sentence + /// "This Visitor expects to receive ...", for example the message could be + /// "an integer between 0 and 64". The message should not be capitalized and + /// should not end with a period. + /// + /// ```rust + /// # use std::fmt; + /// # struct S { max: usize } + /// # impl serde::de::Visitor for S { + /// # type Value = (); + /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// write!(formatter, "an integer between 0 and {}", self.max) + /// } + /// # } + /// ``` + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result; + /// `visit_bool` deserializes a `bool` into a `Value`. fn visit_bool(self, v: bool) -> Result where E: Error, { - let _ = v; - Err(Error::invalid_type(Type::Bool)) + Err(Error::invalid_type(Unexpected::Bool(v), &self)) } /// `visit_isize` deserializes a `isize` into a `Value`. @@ -469,8 +813,7 @@ pub trait Visitor: Sized { fn visit_i64(self, v: i64) -> Result where E: Error, { - let _ = v; - Err(Error::invalid_type(Type::I64)) + Err(Error::invalid_type(Unexpected::Signed(v), &self)) } /// `visit_usize` deserializes a `usize` into a `Value`. @@ -505,8 +848,7 @@ pub trait Visitor: Sized { fn visit_u64(self, v: u64) -> Result where E: Error, { - let _ = v; - Err(Error::invalid_type(Type::U64)) + Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) } /// `visit_f32` deserializes a `f32` into a `Value`. @@ -520,8 +862,7 @@ pub trait Visitor: Sized { fn visit_f64(self, v: f64) -> Result where E: Error, { - let _ = v; - Err(Error::invalid_type(Type::F64)) + Err(Error::invalid_type(Unexpected::Float(v), &self)) } /// `visit_char` deserializes a `char` into a `Value`. @@ -536,8 +877,7 @@ pub trait Visitor: Sized { fn visit_str(self, v: &str) -> Result where E: Error, { - let _ = v; - Err(Error::invalid_type(Type::Str)) + Err(Error::invalid_type(Unexpected::Str(v), &self)) } /// `visit_string` deserializes a `String` into a `Value`. This allows a deserializer to avoid @@ -555,23 +895,14 @@ pub trait Visitor: Sized { fn visit_unit(self) -> Result where E: Error, { - Err(Error::invalid_type(Type::Unit)) - } - - /// `visit_unit_struct` deserializes a unit struct into a `Value`. - #[inline] - fn visit_unit_struct(self, name: &'static str) -> Result - where E: Error, - { - let _ = name; - self.visit_unit() + Err(Error::invalid_type(Unexpected::Unit, &self)) } /// `visit_none` deserializes a none value into a `Value`. fn visit_none(self) -> Result where E: Error, { - Err(Error::invalid_type(Type::Option)) + Err(Error::invalid_type(Unexpected::Option, &self)) } /// `visit_some` deserializes a value into a `Value`. @@ -579,7 +910,7 @@ pub trait Visitor: Sized { where D: Deserializer, { let _ = deserializer; - Err(Error::invalid_type(Type::Option)) + Err(Error::invalid_type(Unexpected::Option, &self)) } /// `visit_newtype_struct` deserializes a value into a `Value`. @@ -587,7 +918,7 @@ pub trait Visitor: Sized { where D: Deserializer, { let _ = deserializer; - Err(Error::invalid_type(Type::NewtypeStruct)) + Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) } /// `visit_seq` deserializes a `SeqVisitor` into a `Value`. @@ -595,7 +926,7 @@ pub trait Visitor: Sized { where V: SeqVisitor, { let _ = visitor; - Err(Error::invalid_type(Type::Seq)) + Err(Error::invalid_type(Unexpected::Seq, &self)) } /// `visit_map` deserializes a `MapVisitor` into a `Value`. @@ -603,7 +934,7 @@ pub trait Visitor: Sized { where V: MapVisitor, { let _ = visitor; - Err(Error::invalid_type(Type::Map)) + Err(Error::invalid_type(Unexpected::Map, &self)) } /// `visit_enum` deserializes a `EnumVisitor` into a `Value`. @@ -611,7 +942,7 @@ pub trait Visitor: Sized { where V: EnumVisitor, { let _ = visitor; - Err(Error::invalid_type(Type::Enum)) + Err(Error::invalid_type(Unexpected::Enum, &self)) } /// `visit_bytes` deserializes a `&[u8]` into a `Value`. @@ -619,7 +950,7 @@ pub trait Visitor: Sized { where E: Error, { let _ = v; - Err(Error::invalid_type(Type::Bytes)) + Err(Error::invalid_type(Unexpected::Bytes(v), &self)) } /// `visit_byte_buf` deserializes a `Vec` into a `Value`. @@ -641,10 +972,26 @@ pub trait SeqVisitor { /// The error type that can be returned if some error occurs during deserialization. type Error: Error; - /// This returns a `Ok(Some(value))` for the next value in the sequence, or `Ok(None)` if there - /// are no more remaining items. + /// This returns `Ok(Some(value))` for the next value in the sequence, or + /// `Ok(None)` if there are no more remaining items. + /// + /// `Deserialize` implementations should typically use `SeqVisitor::visit` + /// instead. + fn visit_seed(&mut self, seed: T) -> Result, Self::Error> + where T: DeserializeSeed; + + /// This returns `Ok(Some(value))` for the next value in the sequence, or + /// `Ok(None)` if there are no more remaining items. + /// + /// This method exists as a convenience for `Deserialize` implementations. + /// `SeqVisitor` implementations should not need to override the default + /// behavior. + #[inline] fn visit(&mut self) -> Result, Self::Error> - where T: Deserialize; + where T: Deserialize + { + self.visit_seed(PhantomData) + } /// Return the lower and upper bound of items remaining in the sequence. #[inline] @@ -656,6 +1003,13 @@ pub trait SeqVisitor { impl<'a, V> SeqVisitor for &'a mut V where V: SeqVisitor { type Error = V::Error; + #[inline] + fn visit_seed(&mut self, seed: T) -> Result, V::Error> + where T: DeserializeSeed + { + (**self).visit_seed(seed) + } + #[inline] fn visit(&mut self) -> Result, V::Error> where T: Deserialize @@ -678,48 +1032,114 @@ pub trait MapVisitor { /// The error type that can be returned if some error occurs during deserialization. type Error: Error; - /// This returns a `Ok(Some((key, value)))` for the next (key-value) pair in the map, or - /// `Ok(None)` if there are no more remaining items. + /// This returns `Ok(Some(key))` for the next key in the map, or `Ok(None)` + /// if there are no more remaining entries. + /// + /// `Deserialize` implementations should typically use + /// `MapVisitor::visit_key` or `MapVisitor::visit` instead. + fn visit_key_seed(&mut self, seed: K) -> Result, Self::Error> + where K: DeserializeSeed; + + /// This returns a `Ok(value)` for the next value in the map. + /// + /// `Deserialize` implementations should typically use + /// `MapVisitor::visit_value` instead. + fn visit_value_seed(&mut self, seed: V) -> Result + where V: DeserializeSeed; + + /// This returns `Ok(Some((key, value)))` for the next (key-value) pair in + /// the map, or `Ok(None)` if there are no more remaining items. + /// + /// `MapVisitor` implementations should override the default behavior if a + /// more efficient implementation is possible. + /// + /// `Deserialize` implementations should typically use `MapVisitor::visit` + /// instead. #[inline] - fn visit(&mut self) -> Result, Self::Error> - where K: Deserialize, - V: Deserialize, + fn visit_seed(&mut self, kseed: K, vseed: V) -> Result, Self::Error> + where K: DeserializeSeed, + V: DeserializeSeed { - match try!(self.visit_key()) { + match try!(self.visit_key_seed(kseed)) { Some(key) => { - let value = try!(self.visit_value()); + let value = try!(self.visit_value_seed(vseed)); Ok(Some((key, value))) } None => Ok(None) } } - /// This returns a `Ok(Some(key))` for the next key in the map, or `Ok(None)` if there are no - /// more remaining items. + /// This returns `Ok(Some(key))` for the next key in the map, or `Ok(None)` + /// if there are no more remaining entries. + /// + /// This method exists as a convenience for `Deserialize` implementations. + /// `MapVisitor` implementations should not need to override the default + /// behavior. + #[inline] fn visit_key(&mut self) -> Result, Self::Error> - where K: Deserialize; + where K: Deserialize + { + self.visit_key_seed(PhantomData) + } /// This returns a `Ok(value)` for the next value in the map. + /// + /// This method exists as a convenience for `Deserialize` implementations. + /// `MapVisitor` implementations should not need to override the default + /// behavior. + #[inline] fn visit_value(&mut self) -> Result - where V: Deserialize; + where V: Deserialize + { + self.visit_value_seed(PhantomData) + } + + /// This returns `Ok(Some((key, value)))` for the next (key-value) pair in + /// the map, or `Ok(None)` if there are no more remaining items. + /// + /// This method exists as a convenience for `Deserialize` implementations. + /// `MapVisitor` implementations should not need to override the default + /// behavior. + #[inline] + fn visit(&mut self) -> Result, Self::Error> + where K: Deserialize, + V: Deserialize, + { + self.visit_seed(PhantomData, PhantomData) + } /// Return the lower and upper bound of items remaining in the sequence. #[inline] fn size_hint(&self) -> (usize, Option) { (0, None) } - - /// Report that the struct has a field that wasn't deserialized - fn missing_field(&mut self, field: &'static str) -> Result - where V: Deserialize, - { - Err(Error::missing_field(field)) - } } impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { type Error = V_::Error; + #[inline] + fn visit_key_seed(&mut self, seed: K) -> Result, Self::Error> + where K: DeserializeSeed + { + (**self).visit_key_seed(seed) + } + + #[inline] + fn visit_value_seed(&mut self, seed: V) -> Result + where V: DeserializeSeed + { + (**self).visit_value_seed(seed) + } + + #[inline] + fn visit_seed(&mut self, kseed: K, vseed: V) -> Result, Self::Error> + where K: DeserializeSeed, + V: DeserializeSeed + { + (**self).visit_seed(kseed, vseed) + } + #[inline] fn visit(&mut self) -> Result, V_::Error> where K: Deserialize, @@ -746,13 +1166,6 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } - - #[inline] - fn missing_field(&mut self, field: &'static str) -> Result - where V: Deserialize - { - (**self).missing_field(field) - } } /////////////////////////////////////////////////////////////////////////////// @@ -760,7 +1173,7 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { /// `EnumVisitor` is a visitor that is created by the `Deserializer` and passed /// to the `Deserialize` in order to identify which variant of an enum to /// deserialize. -pub trait EnumVisitor { +pub trait EnumVisitor: Sized { /// The error type that can be returned if some error occurs during deserialization. type Error: Error; /// The `Visitor` that will be used to deserialize the content of the enum @@ -768,14 +1181,29 @@ pub trait EnumVisitor { type Variant: VariantVisitor; /// `visit_variant` is called to identify which variant to deserialize. + /// + /// `Deserialize` implementations should typically use + /// `EnumVisitor::visit_variant` instead. + fn visit_variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where V: DeserializeSeed; + + /// `visit_variant` is called to identify which variant to deserialize. + /// + /// This method exists as a convenience for `Deserialize` implementations. + /// `EnumVisitor` implementations should not need to override the default + /// behavior. + #[inline] fn visit_variant(self) -> Result<(V, Self::Variant), Self::Error> - where V: Deserialize; + where V: Deserialize + { + self.visit_variant_seed(PhantomData) + } } /// `VariantVisitor` is a visitor that is created by the `Deserializer` and /// passed to the `Deserialize` to deserialize the content of a particular enum /// variant. -pub trait VariantVisitor { +pub trait VariantVisitor: Sized { /// The error type that can be returned if some error occurs during deserialization. type Error: Error; @@ -784,8 +1212,24 @@ pub trait VariantVisitor { /// `visit_newtype` is called when deserializing a variant with a single value. /// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`. + /// + /// `Deserialize` implementations should typically use + /// `VariantVisitor::visit_newtype` instead. + fn visit_newtype_seed(self, seed: T) -> Result + where T: DeserializeSeed; + + /// `visit_newtype` is called when deserializing a variant with a single value. + /// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`. + /// + /// This method exists as a convenience for `Deserialize` implementations. + /// `VariantVisitor` implementations should not need to override the default + /// behavior. + #[inline] fn visit_newtype(self) -> Result - where T: Deserialize; + where T: Deserialize + { + self.visit_newtype_seed(PhantomData) + } /// `visit_tuple` is called when deserializing a tuple-like variant. /// If no tuple variants are expected, yield a @@ -803,3 +1247,34 @@ pub trait VariantVisitor { visitor: V) -> Result where V: Visitor; } + +/////////////////////////////////////////////////////////////////////////////// + +/// Used in error messages. +/// +/// - expected `a` +/// - expected `a` or `b` +/// - expected one of `a`, `b`, `c` +struct OneOf { + names: &'static [&'static str], +} + +impl Display for OneOf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.names.len() { + 0 => panic!(), // special case elsewhere + 1 => write!(formatter, "`{}`", self.names[0]), + 2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]), + _ => { + try!(write!(formatter, "one of ")); + for (i, alt) in self.names.iter().enumerate() { + if i > 0 { + try!(write!(formatter, ", ")); + } + try!(write!(formatter, "`{}`", alt)); + } + Ok(()) + } + } + } +} diff --git a/serde/src/de/private.rs b/serde/src/de/private.rs new file mode 100644 index 00000000..92e71cf8 --- /dev/null +++ b/serde/src/de/private.rs @@ -0,0 +1,40 @@ +use core::marker::PhantomData; + +use de::{Deserialize, Deserializer, Error, Visitor}; + +/// If the missing field is of type `Option` then treat is as `None`, +/// otherwise it is an error. +pub fn missing_field(field: &'static str) -> Result + where V: Deserialize, + E: Error +{ + struct MissingFieldDeserializer(&'static str, PhantomData); + + impl Deserializer for MissingFieldDeserializer + where E: Error + { + type Error = E; + + fn deserialize(self, _visitor: V) -> Result + where V: Visitor + { + Err(Error::missing_field(self.0)) + } + + fn deserialize_option(self, visitor: V) -> Result + where V: Visitor + { + visitor.visit_none() + } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit seq seq_fixed_size bytes byte_buf map unit_struct + newtype_struct tuple_struct struct struct_field tuple enum + ignored_any + } + } + + let deserializer = MissingFieldDeserializer(field, PhantomData); + Deserialize::deserialize(deserializer) +} diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index c6472474..f34fb087 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -28,6 +28,10 @@ use collections::{ }; #[cfg(all(feature = "collections", not(feature = "std")))] use collections::borrow::Cow; +#[cfg(all(feature = "collections", not(feature = "std")))] +use collections::boxed::Box; +#[cfg(all(feature = "collections", not(feature = "std")))] +use collections::string::ToString; #[cfg(all(feature = "unstable", feature = "collections"))] use collections::borrow::ToOwned; @@ -38,112 +42,57 @@ use std::error; #[cfg(not(feature = "std"))] use error; -use core::fmt; +use core::fmt::{self, Display}; +use core::iter::{self, Iterator}; use core::marker::PhantomData; -use de::{self, SeqVisitor}; +use de::{self, Expected, SeqVisitor}; use bytes; /////////////////////////////////////////////////////////////////////////////// /// This represents all the possible errors that can occur using the `ValueDeserializer`. #[derive(Clone, Debug, PartialEq)] -pub enum Error { - /// The value had some custom error. - #[cfg(any(feature = "std", feature = "collections"))] - Custom(String), - /// The value had some custom error. - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - Custom(&'static str), +pub struct Error(ErrorImpl); - /// The value had an incorrect type. - InvalidType(de::Type), - - /// The value had an invalid length. - InvalidLength(usize), - - /// The value is invalid and cannot be deserialized. - #[cfg(any(feature = "std", feature = "collections"))] - InvalidValue(String), - /// The value is invalid and cannot be deserialized. - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - InvalidValue(&'static str), - - /// EOF while deserializing a value. - EndOfStream, - - /// Unknown variant in enum. - #[cfg(any(feature = "std", feature = "collections"))] - UnknownVariant(String), - /// Unknown variant in enum. - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - UnknownVariant(&'static str), - - /// Unknown field in struct. - #[cfg(any(feature = "std", feature = "collections"))] - UnknownField(String), - /// Unknown field in struct. - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - UnknownField(&'static str), - - /// Struct is missing a field. - MissingField(&'static str), -} +#[cfg(any(feature = "std", feature = "collections"))] +type ErrorImpl = Box; +#[cfg(not(any(feature = "std", feature = "collections")))] +type ErrorImpl = (); impl de::Error for Error { #[cfg(any(feature = "std", feature = "collections"))] - fn custom>(msg: T) -> Self { Error::Custom(msg.into()) } + fn custom(msg: T) -> Self { + Error(msg.to_string().into_boxed_str()) + } - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - fn custom>(msg: T) -> Self { Error::Custom(msg.into()) } - - fn end_of_stream() -> Self { Error::EndOfStream } - fn invalid_type(ty: de::Type) -> Self { Error::InvalidType(ty) } - - #[cfg(any(feature = "std", feature = "collections"))] - fn invalid_value(msg: &str) -> Self { Error::InvalidValue(msg.to_owned()) } - - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - fn invalid_value(msg: &str) -> Self { Error::InvalidValue("invalid value") } - - fn invalid_length(len: usize) -> Self { Error::InvalidLength(len) } - - #[cfg(any(feature = "std", feature = "collections"))] - fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant(String::from(variant)) } - #[cfg(any(feature = "std", feature = "collections"))] - fn unknown_field(field: &str) -> Self { Error::UnknownField(String::from(field)) } - - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant("unknown variant") } - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - fn unknown_field(field: &str) -> Self { Error::UnknownField("unknown field") } - fn missing_field(field: &'static str) -> Self { Error::MissingField(field) } + #[cfg(not(any(feature = "std", feature = "collections")))] + fn custom(msg: T) -> Self { + Error(()) + } } -impl fmt::Display for Error { +impl Display for Error { + #[cfg(any(feature = "std", feature = "collections"))] fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Error::Custom(ref s) => write!(formatter, "{}", s), - Error::EndOfStream => formatter.write_str("End of stream"), - Error::InvalidType(ty) => write!(formatter, "Invalid type, expected `{:?}`", ty), - Error::InvalidValue(ref value) => write!(formatter, "Invalid value: {}", value), - Error::InvalidLength(len) => write!(formatter, "Invalid length: {}", len), - Error::UnknownVariant(ref variant) => { - write!(formatter, "Unknown variant: {}", variant) - } - Error::UnknownField(ref field) => write!(formatter, "Unknown field: {}", field), - Error::MissingField(field) => write!(formatter, "Missing field: {}", field), - } + formatter.write_str(&self.0) + } + + #[cfg(not(any(feature = "std", feature = "collections")))] + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Serde deserialization error") } } impl error::Error for Error { + #[cfg(any(feature = "std", feature = "collections"))] fn description(&self) -> &str { - "Serde Deserialization Error" + &self.0 } - fn cause(&self) -> Option<&error::Error> { - None + #[cfg(not(any(feature = "std", feature = "collections")))] + fn description(&self) -> &str { + "Serde deserialization error" } } @@ -298,10 +247,10 @@ impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E> type Error = E; type Variant = private::UnitOnly; - fn visit_variant(self) -> Result<(T, Self::Variant), Self::Error> - where T: de::Deserialize, + fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where T: de::DeserializeSeed, { - de::Deserialize::deserialize(self).map(private::unit_only) + seed.deserialize(self).map(private::unit_only) } } @@ -357,10 +306,10 @@ impl<'a, E> de::EnumVisitor for StringDeserializer type Error = E; type Variant = private::UnitOnly; - fn visit_variant(self) -> Result<(T, Self::Variant), Self::Error> - where T: de::Deserialize, + fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where T: de::DeserializeSeed, { - de::Deserialize::deserialize(self).map(private::unit_only) + seed.deserialize(self).map(private::unit_only) } } @@ -419,10 +368,10 @@ impl<'a, E> de::EnumVisitor for CowStrDeserializer<'a, E> type Error = E; type Variant = private::UnitOnly; - fn visit_variant(self) -> Result<(T, Self::Variant), Self::Error> - where T: de::Deserialize, + fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where T: de::DeserializeSeed, { - de::Deserialize::deserialize(self).map(private::unit_only) + seed.deserialize(self).map(private::unit_only) } } @@ -430,22 +379,37 @@ impl<'a, E> de::EnumVisitor for CowStrDeserializer<'a, E> /// A helper deserializer that deserializes a sequence. pub struct SeqDeserializer { - iter: I, - len: usize, + iter: iter::Fuse, + count: usize, marker: PhantomData, } impl SeqDeserializer - where E: de::Error, + where I: Iterator, + E: de::Error, { /// Construct a new `SeqDeserializer`. - pub fn new(iter: I, len: usize) -> Self { + pub fn new(iter: I) -> Self { SeqDeserializer { - iter: iter, - len: len, + iter: iter.fuse(), + count: 0, marker: PhantomData, } } + + fn end(&mut self) -> Result<(), E> { + let mut remaining = 0; + while self.iter.next().is_some() { + remaining += 1; + } + if remaining == 0 { + Ok(()) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(self.count + remaining, &ExpectedInSeq(self.count))) + } + } } impl de::Deserializer for SeqDeserializer @@ -459,11 +423,8 @@ impl de::Deserializer for SeqDeserializer where V: de::Visitor, { let v = try!(visitor.visit_seq(&mut self)); - if self.len == 0 { - Ok(v) - } else { - Err(de::Error::invalid_length(self.len)) - } + try!(self.end()); + Ok(v) } forward_to_deserialize! { @@ -480,20 +441,32 @@ impl de::SeqVisitor for SeqDeserializer { type Error = E; - fn visit(&mut self) -> Result, Self::Error> - where V: de::Deserialize + fn visit_seed(&mut self, seed: V) -> Result, Self::Error> + where V: de::DeserializeSeed { match self.iter.next() { Some(value) => { - self.len -= 1; - de::Deserialize::deserialize(value.into_deserializer()).map(Some) + self.count += 1; + seed.deserialize(value.into_deserializer()).map(Some) } None => Ok(None), } } fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) + self.iter.size_hint() + } +} + +struct ExpectedInSeq(usize); + +impl Expected for ExpectedInSeq { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.0 == 1 { + write!(formatter, "1 element in sequence") + } else { + write!(formatter, "{} elements in sequence", self.0) + } } } @@ -507,8 +480,7 @@ impl ValueDeserializer for Vec type Deserializer = SeqDeserializer, E>; fn into_deserializer(self) -> Self::Deserializer { - let len = self.len(); - SeqDeserializer::new(self.into_iter(), len) + SeqDeserializer::new(self.into_iter()) } } @@ -520,8 +492,7 @@ impl ValueDeserializer for BTreeSet type Deserializer = SeqDeserializer, E>; fn into_deserializer(self) -> Self::Deserializer { - let len = self.len(); - SeqDeserializer::new(self.into_iter(), len) + SeqDeserializer::new(self.into_iter()) } } @@ -533,8 +504,7 @@ impl ValueDeserializer for HashSet type Deserializer = SeqDeserializer, E>; fn into_deserializer(self) -> Self::Deserializer { - let len = self.len(); - SeqDeserializer::new(self.into_iter(), len) + SeqDeserializer::new(self.into_iter()) } } @@ -579,66 +549,66 @@ impl de::Deserializer for SeqVisitorDeserializer /////////////////////////////////////////////////////////////////////////////// /// A helper deserializer that deserializes a map. -pub struct MapDeserializer - where I: Iterator, - K: ValueDeserializer, - V: ValueDeserializer, +pub struct MapDeserializer + where I: Iterator, + I::Item: private::Pair, + ::First: ValueDeserializer, + ::Second: ValueDeserializer, E: de::Error, { - iter: I, - value: Option, - len: Option, + iter: iter::Fuse, + value: Option<::Second>, + count: usize, marker: PhantomData, } -impl MapDeserializer - where I: Iterator, - K: ValueDeserializer, - V: ValueDeserializer, +impl MapDeserializer + where I: Iterator, + I::Item: private::Pair, + ::First: ValueDeserializer, + ::Second: ValueDeserializer, E: de::Error, { - /// Construct a new `MapDeserializer` with a specific length. - pub fn new(iter: I, len: usize) -> Self { + /// Construct a new `MapDeserializer`. + pub fn new(iter: I) -> Self { MapDeserializer { - iter: iter, + iter: iter.fuse(), value: None, - len: Some(len), + count: 0, marker: PhantomData, } } - /// Construct a new `MapDeserializer` that is not bounded - /// by a specific length and that delegates to `iter` for its size hint. - pub fn unbounded(iter: I) -> Self { - MapDeserializer { - iter: iter, - value: None, - len: None, - marker: PhantomData, - } - } - - fn next(&mut self) -> Option<(K, V)> { - self.iter.next().map(|(k, v)| { - if let Some(len) = self.len.as_mut() { - *len -= 1; + fn next(&mut self) -> Option<(::First, ::Second)> { + match self.iter.next() { + Some(kv) => { + self.count += 1; + Some(private::Pair::split(kv)) } - (k, v) - }) + None => None, + } } fn end(&mut self) -> Result<(), E> { - match self.len { - Some(len) if len > 0 => Err(de::Error::invalid_length(len)), - _ => Ok(()) + let mut remaining = 0; + while self.iter.next().is_some() { + remaining += 1; + } + if remaining == 0 { + Ok(()) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count))) } } } -impl de::Deserializer for MapDeserializer - where I: Iterator, - K: ValueDeserializer, - V: ValueDeserializer, +impl de::Deserializer for MapDeserializer + where I: Iterator, + I::Item: private::Pair, + ::First: ValueDeserializer, + ::Second: ValueDeserializer, E: de::Error, { type Error = E; @@ -659,17 +629,10 @@ impl de::Deserializer for MapDeserializer Ok(value) } - fn deserialize_seq_fixed_size(mut self, len: usize, visitor: V_) -> Result + fn deserialize_seq_fixed_size(self, _len: usize, visitor: V_) -> Result where V_: de::Visitor, { - match self.len { - Some(map_len) if map_len != len => Err(de::Error::invalid_length(len)), - _ => { - let value = try!(visitor.visit_seq(&mut self)); - try!(self.end()); - Ok(value) - } - } + self.deserialize_seq(visitor) } forward_to_deserialize! { @@ -679,47 +642,45 @@ impl de::Deserializer for MapDeserializer } } -impl de::MapVisitor for MapDeserializer - where I: Iterator, - K: ValueDeserializer, - V: ValueDeserializer, +impl de::MapVisitor for MapDeserializer + where I: Iterator, + I::Item: private::Pair, + ::First: ValueDeserializer, + ::Second: ValueDeserializer, E: de::Error, { type Error = E; - fn visit_key(&mut self) -> Result, Self::Error> - where T: de::Deserialize, + fn visit_key_seed(&mut self, seed: T) -> Result, Self::Error> + where T: de::DeserializeSeed, { match self.next() { Some((key, value)) => { self.value = Some(value); - de::Deserialize::deserialize(key.into_deserializer()).map(Some) + seed.deserialize(key.into_deserializer()).map(Some) } None => Ok(None), } } - fn visit_value(&mut self) -> Result - where T: de::Deserialize, + fn visit_value_seed(&mut self, seed: T) -> Result + where T: de::DeserializeSeed, { - match self.value.take() { - Some(value) => { - de::Deserialize::deserialize(value.into_deserializer()) - } - None => { - Err(de::Error::end_of_stream()) - } - } + let value = self.value.take(); + // Panic because this indicates a bug in the program rather than an + // expected failure. + let value = value.expect("MapVisitor::visit_value called before visit_key"); + seed.deserialize(value.into_deserializer()) } - fn visit(&mut self) -> Result, Self::Error> - where TK: de::Deserialize, - TV: de::Deserialize + fn visit_seed(&mut self, kseed: TK, vseed: TV) -> Result, Self::Error> + where TK: de::DeserializeSeed, + TV: de::DeserializeSeed { match self.next() { Some((key, value)) => { - let key = try!(de::Deserialize::deserialize(key.into_deserializer())); - let value = try!(de::Deserialize::deserialize(value.into_deserializer())); + let key = try!(kseed.deserialize(key.into_deserializer())); + let value = try!(vseed.deserialize(value.into_deserializer())); Ok(Some((key, value))) } None => Ok(None) @@ -727,34 +688,33 @@ impl de::MapVisitor for MapDeserializer } fn size_hint(&self) -> (usize, Option) { - self.len.map_or_else( - || self.iter.size_hint(), - |len| (len, Some(len))) + self.iter.size_hint() } } -impl de::SeqVisitor for MapDeserializer - where I: Iterator, - K: ValueDeserializer, - V: ValueDeserializer, +impl de::SeqVisitor for MapDeserializer + where I: Iterator, + I::Item: private::Pair, + ::First: ValueDeserializer, + ::Second: ValueDeserializer, E: de::Error, { type Error = E; - fn visit(&mut self) -> Result, Self::Error> - where T: de::Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Self::Error> + where T: de::DeserializeSeed, { match self.next() { Some((k, v)) => { let de = PairDeserializer(k, v, PhantomData); - de::Deserialize::deserialize(de).map(Some) + seed.deserialize(de).map(Some) } None => Ok(None), } } fn size_hint(&self) -> (usize, Option) { - de::MapVisitor::size_hint(self) + self.iter.size_hint() } } @@ -789,7 +749,10 @@ impl de::Deserializer for PairDeserializer if pair_visitor.1.is_none() { Ok(pair) } else { - Err(de::Error::invalid_length(pair_visitor.size_hint().0)) + let remaining = pair_visitor.size_hint().0; + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) } } @@ -799,7 +762,9 @@ impl de::Deserializer for PairDeserializer if len == 2 { self.deserialize_seq(visitor) } else { - Err(de::Error::invalid_length(len)) + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(2, &ExpectedInSeq(len))) } } } @@ -813,13 +778,13 @@ impl de::SeqVisitor for PairVisitor { type Error = E; - fn visit(&mut self) -> Result, Self::Error> - where T: de::Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Self::Error> + where T: de::DeserializeSeed, { if let Some(k) = self.0.take() { - de::Deserialize::deserialize(k.into_deserializer()).map(Some) + seed.deserialize(k.into_deserializer()).map(Some) } else if let Some(v) = self.1.take() { - de::Deserialize::deserialize(v.into_deserializer()).map(Some) + seed.deserialize(v.into_deserializer()).map(Some) } else { Ok(None) } @@ -837,6 +802,18 @@ impl de::SeqVisitor for PairVisitor } } +struct ExpectedInMap(usize); + +impl Expected for ExpectedInMap { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.0 == 1 { + write!(formatter, "1 element in map") + } else { + write!(formatter, "{} elements in map", self.0) + } + } +} + /////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "collections"))] @@ -845,11 +822,10 @@ impl ValueDeserializer for BTreeMap V: ValueDeserializer, E: de::Error, { - type Deserializer = MapDeserializer, K, V, E>; + type Deserializer = MapDeserializer, E>; fn into_deserializer(self) -> Self::Deserializer { - let len = self.len(); - MapDeserializer::new(self.into_iter(), len) + MapDeserializer::new(self.into_iter()) } } @@ -859,11 +835,10 @@ impl ValueDeserializer for HashMap V: ValueDeserializer, E: de::Error, { - type Deserializer = MapDeserializer, K, V, E>; + type Deserializer = MapDeserializer, E>; fn into_deserializer(self) -> Self::Deserializer { - let len = self.len(); - MapDeserializer::new(self.into_iter(), len) + MapDeserializer::new(self.into_iter()) } } @@ -977,7 +952,7 @@ impl de::Deserializer for ByteBufDeserializer /////////////////////////////////////////////////////////////////////////////// mod private { - use de; + use de::{self, Unexpected}; use core::marker::PhantomData; pub struct UnitOnly(PhantomData); @@ -995,10 +970,10 @@ mod private { Ok(()) } - fn visit_newtype(self) -> Result - where T: de::Deserialize, + fn visit_newtype_seed(self, _seed: T) -> Result + where T: de::DeserializeSeed, { - Err(de::Error::invalid_type(de::Type::NewtypeVariant)) + Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant")) } fn visit_tuple(self, @@ -1006,7 +981,7 @@ mod private { _visitor: V) -> Result where V: de::Visitor { - Err(de::Error::invalid_type(de::Type::TupleVariant)) + Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant")) } fn visit_struct(self, @@ -1014,7 +989,21 @@ mod private { _visitor: V) -> Result where V: de::Visitor { - Err(de::Error::invalid_type(de::Type::StructVariant)) + Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant")) } } + + /// Avoid having to restate the generic types on MapDeserializer. The + /// Iterator::Item contains enough information to figure out K and V. + pub trait Pair { + type First; + type Second; + fn split(self) -> (Self::First, Self::Second); + } + + impl Pair for (A, B) { + type First = A; + type Second = B; + fn split(self) -> (A, B) { self } + } } diff --git a/serde/src/error.rs b/serde/src/error.rs index f6b704c7..6c411f84 100644 --- a/serde/src/error.rs +++ b/serde/src/error.rs @@ -1,5 +1,4 @@ //! A stand-in for `std::error` -use core::any::TypeId; use core::fmt::{Debug, Display}; /// A stand-in for `std::error::Error`, which requires no allocation. @@ -13,10 +12,4 @@ pub trait Error: Debug + Display { /// The lower-level cause of this error, if any. fn cause(&self) -> Option<&Error> { None } - - /// Get the `TypeId` of `self` - #[doc(hidden)] - fn type_id(&self) -> TypeId where Self: 'static { - TypeId::of::() - } } diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 2046872b..24f2a677 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -40,11 +40,6 @@ mod core { pub use ser::{Serialize, Serializer}; pub use de::{Deserialize, Deserializer}; -#[cfg(not(feature = "std"))] -macro_rules! format { - ($s:expr, $($rest:tt)*) => ($s) -} - #[macro_use] mod macros; diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index f09b2871..e89f0cd3 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -772,7 +772,7 @@ impl Serialize for path::Path { { match self.to_str() { Some(s) => s.serialize(serializer), - None => Err(Error::invalid_value("Path contains invalid UTF-8 characters")), + None => Err(Error::custom("Path contains invalid UTF-8 characters")), } } } diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 3b2e3d34..10b14fda 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -23,6 +23,8 @@ use core::marker::PhantomData; #[cfg(feature = "unstable")] use core::cell::RefCell; +use core::fmt::Display; + pub mod impls; /////////////////////////////////////////////////////////////////////////////// @@ -31,17 +33,7 @@ pub mod impls; /// `Serializer` error. pub trait Error: Sized + error::Error { /// Raised when there is a general error when serializing a type. - #[cfg(any(feature = "std", feature = "collections"))] - fn custom>(msg: T) -> Self; - - /// Raised when there is a general error when serializing a type. - #[cfg(all(not(feature = "std"), not(feature = "collections")))] - fn custom>(msg: T) -> Self; - - /// Raised when a `Serialize` was passed an incorrect value. - fn invalid_value(msg: &str) -> Self { - Error::custom(format!("invalid value: {}", msg)) - } + fn custom(msg: T) -> Self; } /////////////////////////////////////////////////////////////////////////////// diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 757e838f..6161e373 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.9.0-rc1" +version = "0.9.0-rc2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 21ae9aa1..eda81859 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -200,12 +200,18 @@ fn deserialize_unit_struct( ) -> Tokens { let type_name = item_attrs.name().deserialize_name(); + let expecting = format!("unit struct {}", type_ident); + quote!({ struct __Visitor; impl _serde::de::Visitor for __Visitor { type Value = #type_ident; + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str(#expecting) + } + #[inline] fn visit_unit<__E>(self) -> ::std::result::Result<#type_ident, __E> where __E: _serde::de::Error, @@ -242,6 +248,10 @@ fn deserialize_tuple( Some(variant_ident) => quote!(#type_ident::#variant_ident), None => quote!(#type_ident), }; + let expecting = match variant_ident { + Some(variant_ident) => format!("tuple variant {}::{}", type_ident, variant_ident), + None => format!("tuple struct {}", type_ident), + }; let nfields = fields.len(); @@ -287,6 +297,10 @@ fn deserialize_tuple( impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { type Value = #ty; + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str(#expecting) + } + #visit_newtype_struct #[inline] @@ -310,6 +324,11 @@ fn deserialize_seq( ) -> Tokens { let vars = (0..fields.len()).map(field_i as fn(_) -> _); + let deserialized_count = fields.iter() + .filter(|field| !field.attrs.skip_deserializing()) + .count(); + let expecting = format!("tuple of {} elements", deserialized_count); + let mut index_in_seq = 0usize; let let_values = vars.clone().zip(fields) .map(|(var, field)| { @@ -338,7 +357,7 @@ fn deserialize_seq( let #var = match #visit { Some(value) => { value }, None => { - return Err(_serde::de::Error::invalid_length(#index_in_seq)); + return Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting)); } }; }; @@ -413,6 +432,10 @@ fn deserialize_struct( Some(variant_ident) => quote!(#type_ident::#variant_ident), None => quote!(#type_ident), }; + let expecting = match variant_ident { + Some(variant_ident) => format!("struct variant {}::{}", type_ident, variant_ident), + None => format!("struct {}", type_ident), + }; let visit_seq = deserialize_seq( type_ident, @@ -457,6 +480,10 @@ fn deserialize_struct( impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { type Value = #ty; + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str(#expecting) + } + #[inline] fn visit_seq<__V>(self, #visitor_var: __V) -> ::std::result::Result<#ty, __V::Error> where __V: _serde::de::SeqVisitor @@ -489,24 +516,27 @@ fn deserialize_item_enum( let type_name = item_attrs.name().deserialize_name(); - let variant_names_idents = variants.iter() + let expecting = format!("enum {}", type_ident); + + let variant_names_idents: Vec<_> = variants.iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i))) .collect(); + let variants_stmt = { + let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name); + quote! { + const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; + } + }; + let variant_visitor = deserialize_field_visitor( variant_names_idents, item_attrs, true, ); - let variant_names = variants.iter().map(|variant| variant.attrs.name().deserialize_name()); - - let variants_stmt = quote! { - const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; - }; - // Match arms to extract a variant from a string let variant_arms = variants.iter() .enumerate() @@ -555,6 +585,10 @@ fn deserialize_item_enum( impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { type Value = #ty; + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str(#expecting) + } + fn visit_enum<__V>(self, visitor: __V) -> ::std::result::Result<#ty, __V::Error> where __V: _serde::de::EnumVisitor, { @@ -660,7 +694,7 @@ fn deserialize_field_visitor( let visit_usize = if is_variant { let variant_indices = 0usize..; - let fallthrough_msg = format!("expected variant index 0 <= i < {}", fields.len()); + let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len()); Some(quote! { fn visit_usize<__E>(self, value: usize) -> ::std::result::Result<__Field, __E> where __E: _serde::de::Error @@ -669,7 +703,9 @@ fn deserialize_field_visitor( #( #variant_indices => Ok(__Field::#field_idents), )* - _ => Err(_serde::de::Error::invalid_value(#fallthrough_msg)) + _ => Err(_serde::de::Error::invalid_value( + _serde::de::Unexpected::Unsigned(value as u64), + &#fallthrough_msg)) } } }) @@ -679,11 +715,11 @@ fn deserialize_field_visitor( let fallthrough_arm = if is_variant { quote! { - Err(_serde::de::Error::unknown_variant(value)) + Err(_serde::de::Error::unknown_variant(value, VARIANTS)) } } else if item_attrs.deny_unknown_fields() { quote! { - Err(_serde::de::Error::unknown_field(value)) + Err(_serde::de::Error::unknown_field(value, FIELDS)) } } else { quote! { @@ -718,6 +754,10 @@ fn deserialize_field_visitor( impl _serde::de::Visitor for __FieldVisitor { type Value = __Field; + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("field name") + } + #visit_usize fn visit_str<__E>(self, value: &str) -> ::std::result::Result<__Field, __E> @@ -759,12 +799,19 @@ fn deserialize_struct_visitor( fields: &[Field], item_attrs: &attr::Item, ) -> (Tokens, Tokens, Tokens) { - let field_names_idents = fields.iter() + let field_names_idents: Vec<_> = fields.iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i))) .collect(); + let fields_stmt = { + let field_names = field_names_idents.iter().map(|&(ref name, _)| name); + quote! { + const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; + } + }; + let field_visitor = deserialize_field_visitor( field_names_idents, item_attrs, @@ -779,11 +826,6 @@ fn deserialize_struct_visitor( item_attrs, ); - let field_names = fields.iter().map(|field| field.attrs.name().deserialize_name()); - let fields_stmt = quote! { - const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; - }; - (field_visitor, fields_stmt, visit_map) } @@ -974,7 +1016,7 @@ fn expr_is_missing(attrs: &attr::Field) -> Tokens { match attrs.deserialize_with() { None => { quote! { - try!(visitor.missing_field(#name)) + try!(_serde::de::private::missing_field(#name)) } } Some(_) => { diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index acd9973c..3374d5ac 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -257,10 +257,10 @@ fn serialize_variant( let variant_name = variant.attrs.name().serialize_name(); if variant.attrs.skip_serializing() { - let skipped_msg = format!("The enum variant {}::{} cannot be serialized", + let skipped_msg = format!("the enum variant {}::{} cannot be serialized", type_ident, variant_ident); let skipped_err = quote! { - Err(_serde::ser::Error::invalid_value(#skipped_msg)) + Err(_serde::ser::Error::custom(#skipped_msg)) }; let fields_pat = match variant.style { Style::Unit => quote!(), diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 18337045..ddc3f62f 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.9.0-rc1" +version = "0.9.0-rc2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.9.0-rc1" +version = "=0.9.0-rc2" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.9.0-rc1", path = "../serde" } -serde_test = { version = "0.9.0-rc1", path = "../serde_test" } +serde = { version = "0.9.0-rc2", path = "../serde" } +serde_test = { version = "0.9.0-rc2", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index de037b79..b4ea1c74 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.9.0-rc1" +version = "0.9.0-rc2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.9.0-rc1", path = "../serde" } +serde = { version = "0.9.0-rc2", path = "../serde" } diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index 849bdf27..fc29ccd9 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -3,6 +3,7 @@ use std::iter; use serde::de::{ self, Deserialize, + DeserializeSeed, EnumVisitor, MapVisitor, SeqVisitor, @@ -42,7 +43,7 @@ impl Deserializer Err(Error::UnexpectedToken(token)) } } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -258,7 +259,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer Some(Token::Option(false)) => visitor.visit_none(), Some(Token::Option(true)) => visitor.visit_some(self), Some(Token::Unit) => visitor.visit_unit(), - Some(Token::UnitStruct(name)) => visitor.visit_unit_struct(name), + Some(Token::UnitStruct(_name)) => visitor.visit_unit(), Some(Token::SeqStart(len)) => { self.visit_seq(len, visitor) } @@ -272,7 +273,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer self.visit_map(Some(len), visitor) } Some(token) => Err(Error::UnexpectedToken(token)), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -295,7 +296,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer visitor.visit_none() } Some(_) => visitor.visit_some(self), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -325,7 +326,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer let token = self.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => { return Err(Error::EndOfStream); } + None => { return Err(Error::EndOfTokens); } } } @@ -342,7 +343,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer } } Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -361,7 +362,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer } } Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -376,7 +377,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer self.visit_array(len, visitor) } Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -411,7 +412,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer self.visit_tuple_struct(len, visitor) } Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -455,7 +456,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer } } Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -479,7 +480,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer self.visit_map(Some(fields.len()), visitor) } Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } } @@ -496,21 +497,21 @@ impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I> { type Error = Error; - fn visit(&mut self) -> Result, Error> - where T: Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Error> + where T: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::SeqSep) => { self.de.tokens.next(); self.len = self.len.map(|len| len - 1); - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::SeqEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -532,21 +533,21 @@ impl<'a, I> SeqVisitor for DeserializerArrayVisitor<'a, I> { type Error = Error; - fn visit(&mut self) -> Result, Error> - where T: Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Error> + where T: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::SeqSep) => { self.de.tokens.next(); self.len -= 1; - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::SeqEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -567,21 +568,21 @@ impl<'a, I> SeqVisitor for DeserializerTupleVisitor<'a, I> { type Error = Error; - fn visit(&mut self) -> Result, Error> - where T: Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Error> + where T: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::TupleSep) => { self.de.tokens.next(); self.len -= 1; - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::TupleEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -602,21 +603,21 @@ impl<'a, I> SeqVisitor for DeserializerTupleStructVisitor<'a, I> { type Error = Error; - fn visit(&mut self) -> Result, Error> - where T: Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Error> + where T: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::TupleStructSep) => { self.de.tokens.next(); self.len -= 1; - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::TupleStructEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -637,21 +638,21 @@ impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I> { type Error = Error; - fn visit(&mut self) -> Result, Error> - where T: Deserialize, + fn visit_seed(&mut self, seed: T) -> Result, Error> + where T: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::EnumSeqSep) => { self.de.tokens.next(); self.len = self.len.map(|len| len - 1); - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::EnumSeqEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -673,28 +674,28 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I> { type Error = Error; - fn visit_key(&mut self) -> Result, Error> - where K: Deserialize, + fn visit_key_seed(&mut self, seed: K) -> Result, Error> + where K: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::MapSep) => { self.de.tokens.next(); self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 }); - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::MapEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } - fn visit_value(&mut self) -> Result - where V: Deserialize, + fn visit_value_seed(&mut self, seed: V) -> Result + where V: DeserializeSeed, { - Deserialize::deserialize(&mut *self.de) + seed.deserialize(&mut *self.de) } fn size_hint(&self) -> (usize, Option) { @@ -715,28 +716,28 @@ impl<'a, I> MapVisitor for DeserializerStructVisitor<'a, I> { type Error = Error; - fn visit_key(&mut self) -> Result, Error> - where K: Deserialize, + fn visit_key_seed(&mut self, seed: K) -> Result, Error> + where K: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::StructSep) => { self.de.tokens.next(); self.len = self.len.saturating_sub(1); - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::StructEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } - fn visit_value(&mut self) -> Result - where V: Deserialize, + fn visit_value_seed(&mut self, seed: V) -> Result + where V: DeserializeSeed, { - Deserialize::deserialize(&mut *self.de) + seed.deserialize(&mut *self.de) } fn size_hint(&self) -> (usize, Option) { @@ -756,8 +757,8 @@ impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I> type Error = Error; type Variant = Self; - fn visit_variant(self) -> Result<(V, Self), Error> - where V: Deserialize, + fn visit_variant_seed(self, seed: V) -> Result<(V::Value, Self), Error> + where V: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::EnumUnit(_, v)) @@ -765,14 +766,14 @@ impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I> | Some(&Token::EnumSeqStart(_, v, _)) | Some(&Token::EnumMapStart(_, v, _)) => { let de = v.into_deserializer(); - let value = try!(Deserialize::deserialize(de)); + let value = try!(seed.deserialize(de)); Ok((value, self)) } Some(_) => { - let value = try!(Deserialize::deserialize(&mut *self.de)); + let value = try!(seed.deserialize(&mut *self.de)); Ok((value, self)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } } @@ -791,22 +792,22 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> Some(_) => { Deserialize::deserialize(self.de) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } - fn visit_newtype(self) -> Result - where T: Deserialize, + fn visit_newtype_seed(self, seed: T) -> Result + where T: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::EnumNewType(_, _)) => { self.de.tokens.next(); - Deserialize::deserialize(self.de) + seed.deserialize(self.de) } Some(_) => { - Deserialize::deserialize(self.de) + seed.deserialize(self.de) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -837,7 +838,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> Some(_) => { de::Deserializer::deserialize(self.de, visitor) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } @@ -868,7 +869,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> Some(_) => { de::Deserializer::deserialize(self.de, visitor) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } } @@ -885,28 +886,28 @@ impl<'a, I> MapVisitor for DeserializerVariantMapVisitor<'a, I> { type Error = Error; - fn visit_key(&mut self) -> Result, Error> - where K: Deserialize, + fn visit_key_seed(&mut self, seed: K) -> Result, Error> + where K: DeserializeSeed, { match self.de.tokens.peek() { Some(&Token::EnumMapSep) => { self.de.tokens.next(); self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 }); - Deserialize::deserialize(&mut *self.de).map(Some) + seed.deserialize(&mut *self.de).map(Some) } Some(&Token::EnumMapEnd) => Ok(None), Some(_) => { let token = self.de.tokens.next().unwrap(); Err(Error::UnexpectedToken(token)) } - None => Err(Error::EndOfStream), + None => Err(Error::EndOfTokens), } } - fn visit_value(&mut self) -> Result - where V: Deserialize, + fn visit_value_seed(&mut self, seed: V) -> Result + where V: DeserializeSeed, { - Deserialize::deserialize(&mut *self.de) + seed.deserialize(&mut *self.de) } fn size_hint(&self) -> (usize, Option) { diff --git a/serde_test/src/error.rs b/serde_test/src/error.rs index d5c4c6e7..a09252ab 100644 --- a/serde_test/src/error.rs +++ b/serde_test/src/error.rs @@ -1,4 +1,5 @@ -use std::{error, fmt}; +use std::error; +use std::fmt::{self, Display}; use serde::{ser, de}; @@ -6,82 +7,42 @@ use token::Token; #[derive(Clone, PartialEq, Debug)] pub enum Error { - // Shared - Custom(String), - InvalidValue(String), - - // De - EndOfStream, - InvalidType(de::Type), - InvalidLength(usize), - UnknownVariant(String), - UnknownField(String), - MissingField(&'static str), - DuplicateField(&'static str), + Message(String), InvalidName(&'static str), UnexpectedToken(Token<'static>), + EndOfTokens, } impl ser::Error for Error { - fn custom>(msg: T) -> Error { - Error::Custom(msg.into()) - } - - fn invalid_value(msg: &str) -> Error { - Error::InvalidValue(msg.to_owned()) + fn custom(msg: T) -> Error { + Error::Message(msg.to_string()) } } impl de::Error for Error { - fn custom>(msg: T) -> Error { - Error::Custom(msg.into()) - } - - fn end_of_stream() -> Error { - Error::EndOfStream - } - - fn invalid_type(ty: de::Type) -> Error { - Error::InvalidType(ty) - } - - fn invalid_value(msg: &str) -> Error { - Error::InvalidValue(msg.to_owned()) - } - - fn invalid_length(len: usize) -> Error { - Error::InvalidLength(len) - } - - fn unknown_variant(variant: &str) -> Error { - Error::UnknownVariant(variant.to_owned()) - } - - fn unknown_field(field: &str) -> Error { - Error::UnknownField(field.to_owned()) - } - - fn missing_field(field: &'static str) -> Error { - Error::MissingField(field) - } - - fn duplicate_field(field: &'static str) -> Error { - Error::DuplicateField(field) + fn custom(msg: T) -> Error { + Error::Message(msg.to_string()) } } impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str(format!("{:?}", self).as_ref()) + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::Message(ref msg) => formatter.write_str(msg), + Error::InvalidName(name) => write!(formatter, "invalid name `{}`", name), + Error::UnexpectedToken(_) => formatter.write_str("unexpected token"), + Error::EndOfTokens => formatter.write_str("end of tokens"), + } } } impl error::Error for Error { fn description(&self) -> &str { - "Serde Error" - } - - fn cause(&self) -> Option<&error::Error> { - None + match *self { + Error::Message(ref msg) => msg, + Error::InvalidName(_) => "invalid name", + Error::UnexpectedToken(_) => "unexpected token", + Error::EndOfTokens => "end of tokens", + } } } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 7a31c31e..b592a214 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.9.0-rc1" +version = "0.9.0-rc2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/testing/tests/test_annotations.rs b/testing/tests/test_annotations.rs index 0649a8e7..7df8bb1c 100644 --- a/testing/tests/test_annotations.rs +++ b/testing/tests/test_annotations.rs @@ -145,7 +145,7 @@ fn test_default_enum() { assert_de_tokens( &DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, &[ - Token::EnumMapStart("DefaultEnum", "Struct", 5), + Token::EnumMapStart("DefaultEnum", "Struct", 3), Token::EnumMapSep, Token::Str("a1"), @@ -174,7 +174,7 @@ fn test_default_enum() { assert_de_tokens( &DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 }, &[ - Token::EnumMapStart("DefaultEnum", "Struct", 5), + Token::EnumMapStart("DefaultEnum", "Struct", 3), Token::EnumMapSep, Token::Str("a1"), @@ -343,7 +343,7 @@ fn test_ignore_unknown() { Token::StructSep, Token::Str("whoops"), ], - Error::UnknownField("whoops".to_owned()) + Error::Message("unknown field `whoops`, expected `a1`".to_owned()) ); } @@ -905,7 +905,7 @@ fn test_missing_renamed_field_struct() { Token::StructEnd, ], - Error::MissingField("a3"), + Error::Message("missing field `a3`".to_owned()), ); assert_de_tokens_error::( @@ -918,7 +918,7 @@ fn test_missing_renamed_field_struct() { Token::StructEnd, ], - Error::MissingField("a5"), + Error::Message("missing field `a5`".to_owned()), ); } @@ -930,7 +930,7 @@ fn test_missing_renamed_field_enum() { Token::EnumMapEnd, ], - Error::MissingField("b"), + Error::Message("missing field `b`".to_owned()), ); assert_de_tokens_error::>( @@ -943,7 +943,7 @@ fn test_missing_renamed_field_enum() { Token::EnumMapEnd, ], - Error::MissingField("d"), + Error::Message("missing field `d`".to_owned()), ); } @@ -962,7 +962,7 @@ fn test_invalid_length_enum() { Token::I32(1), Token::EnumSeqEnd, ], - Error::InvalidLength(1), + Error::Message("invalid length 1, expected tuple of 3 elements".to_owned()), ); assert_de_tokens_error::( &[ @@ -971,6 +971,6 @@ fn test_invalid_length_enum() { Token::I32(1), Token::EnumSeqEnd, ], - Error::InvalidLength(1), + Error::Message("invalid length 1, expected tuple of 2 elements".to_owned()), ); } diff --git a/testing/tests/test_de.rs b/testing/tests/test_de.rs index cfe6506f..83c3eabf 100644 --- a/testing/tests/test_de.rs +++ b/testing/tests/test_de.rs @@ -3,7 +3,7 @@ use std::net; use std::path::PathBuf; use std::time::Duration; -use serde::de::Deserialize; +use serde::Deserialize; extern crate fnv; use self::fnv::FnvHasher; @@ -863,7 +863,7 @@ declare_error_tests! { Token::StructSep, Token::Str("d"), ], - Error::UnknownField("d".to_owned()), + Error::Message("unknown field `d`, expected `a`".to_owned()), } test_skipped_field_is_unknown { &[ @@ -871,7 +871,7 @@ declare_error_tests! { Token::StructSep, Token::Str("b"), ], - Error::UnknownField("b".to_owned()), + Error::Message("unknown field `b`, expected `a`".to_owned()), } test_skip_all_deny_unknown { &[ @@ -879,25 +879,25 @@ declare_error_tests! { Token::StructSep, Token::Str("a"), ], - Error::UnknownField("a".to_owned()), + Error::Message("unknown field `a`, there are no fields".to_owned()), } test_unknown_variant { &[ Token::EnumUnit("Enum", "Foo"), ], - Error::UnknownVariant("Foo".to_owned()), + Error::Message("unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`".to_owned()), } test_enum_skipped_variant { &[ Token::EnumUnit("Enum", "Skipped"), ], - Error::UnknownVariant("Skipped".to_owned()), + Error::Message("unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`".to_owned()), } test_enum_skip_all { &[ Token::EnumUnit("EnumSkipAll", "Skipped"), ], - Error::UnknownVariant("Skipped".to_owned()), + Error::Message("unknown variant `Skipped`, there are no variants".to_owned()), } test_struct_seq_too_long { &[ @@ -918,7 +918,7 @@ declare_error_tests! { Token::MapSep, Token::Str("a"), ], - Error::DuplicateField("a"), + Error::Message("duplicate field `a`".to_owned()), } test_duplicate_field_enum { &[ @@ -930,7 +930,7 @@ declare_error_tests! { Token::EnumMapSep, Token::Str("a"), ], - Error::DuplicateField("a"), + Error::Message("duplicate field `a`".to_owned()), } test_enum_out_of_range { &[ @@ -938,6 +938,6 @@ declare_error_tests! { Token::Usize(4), Token::Unit, ], - Error::InvalidValue("expected variant index 0 <= i < 4".to_owned()), + Error::Message("invalid value: integer `4`, expected variant index 0 <= i < 4".into()), } } diff --git a/testing/tests/test_ser.rs b/testing/tests/test_ser.rs index 5d54b432..25df26d1 100644 --- a/testing/tests/test_ser.rs +++ b/testing/tests/test_ser.rs @@ -432,7 +432,7 @@ fn test_cannot_serialize_paths() { assert_ser_tokens_error( &Path::new(path), &[], - Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned())); + Error::Message("Path contains invalid UTF-8 characters".to_owned())); let mut path_buf = PathBuf::new(); path_buf.push(path); @@ -440,7 +440,7 @@ fn test_cannot_serialize_paths() { assert_ser_tokens_error( &path_buf, &[], - Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned())); + Error::Message("Path contains invalid UTF-8 characters".to_owned())); } #[test] @@ -448,17 +448,17 @@ fn test_enum_skipped() { assert_ser_tokens_error( &Enum::SkippedUnit, &[], - Error::InvalidValue("The enum variant Enum::SkippedUnit cannot be serialized".to_owned())); + Error::Message("the enum variant Enum::SkippedUnit cannot be serialized".to_owned())); assert_ser_tokens_error( &Enum::SkippedOne(42), &[], - Error::InvalidValue("The enum variant Enum::SkippedOne cannot be serialized".to_owned())); + Error::Message("the enum variant Enum::SkippedOne cannot be serialized".to_owned())); assert_ser_tokens_error( &Enum::SkippedSeq(1, 2), &[], - Error::InvalidValue("The enum variant Enum::SkippedSeq cannot be serialized".to_owned())); + Error::Message("the enum variant Enum::SkippedSeq cannot be serialized".to_owned())); assert_ser_tokens_error( &Enum::SkippedMap { _a: 1, _b: 2 }, &[], - Error::InvalidValue("The enum variant Enum::SkippedMap cannot be serialized".to_owned())); + Error::Message("the enum variant Enum::SkippedMap cannot be serialized".to_owned())); }