diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index c9b427f2..a918ea97 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -96,8 +96,6 @@ #[cfg(feature = "std")] use std::error; -#[cfg(not(feature = "std"))] -use error; #[cfg(all(not(feature = "std"), feature = "collections"))] use collections::{String, Vec}; @@ -123,131 +121,141 @@ pub use self::ignored_any::IgnoredAny; /////////////////////////////////////////////////////////////////////////////// -/// 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. - /// - /// The message should not be capitalized and should not end with a period. - /// - /// ```rust - /// # use serde::de::{Deserialize, Deserializer, Error}; - /// # use std::str::FromStr; - /// # #[allow(dead_code)] - /// # struct IpAddr; - /// # impl FromStr for IpAddr { - /// # type Err = String; - /// # fn from_str(_: &str) -> Result { unimplemented!() } - /// # } - /// impl<'de> Deserialize<'de> for IpAddr { - /// fn deserialize(deserializer: D) -> Result - /// where D: Deserializer<'de> - /// { - /// let s = try!(String::deserialize(deserializer)); - /// s.parse().map_err(Error::custom) - /// } - /// } - /// ``` - fn custom(msg: T) -> Self; +macro_rules! declare_error_trait { + (Error: Sized $(+ $supertrait:path)*) => { + /// 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 $(+ $supertrait)* { + /// Raised when there is general error when deserializing a type. + /// + /// The message should not be capitalized and should not end with a period. + /// + /// ```rust + /// # use serde::de::{Deserialize, Deserializer, Error}; + /// # use std::str::FromStr; + /// # #[allow(dead_code)] + /// # struct IpAddr; + /// # impl FromStr for IpAddr { + /// # type Err = String; + /// # fn from_str(_: &str) -> Result { unimplemented!() } + /// # } + /// impl<'de> Deserialize<'de> for IpAddr { + /// fn deserialize(deserializer: D) -> Result + /// where D: Deserializer<'de> + /// { + /// let s = try!(String::deserialize(deserializer)); + /// s.parse().map_err(Error::custom) + /// } + /// } + /// ``` + fn custom(msg: T) -> Self; - /// Raised when a `Deserialize` receives a type different from what it was - /// expecting. - /// - /// 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 { - Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) - } + /// Raised when a `Deserialize` receives a type different from what it was + /// expecting. + /// + /// 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 { + Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) + } - /// 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 { - Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp)) - } + /// 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 { + Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp)) + } - /// 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 { - Error::custom(format_args!("invalid length {}, expected {}", len, exp)) - } + /// 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 { + Error::custom(format_args!("invalid length {}, expected {}", len, exp)) + } - /// Raised when a `Deserialize` enum type received a variant with an - /// unrecognized name. - fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { - if expected.is_empty() { - Error::custom(format_args!("unknown variant `{}`, there are no variants", - variant)) - } else { - Error::custom(format_args!("unknown variant `{}`, expected {}", - variant, - OneOf { names: expected })) + /// Raised when a `Deserialize` enum type received a variant with an + /// unrecognized name. + fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { + if expected.is_empty() { + Error::custom(format_args!("unknown variant `{}`, there are no variants", + variant)) + } else { + Error::custom(format_args!("unknown variant `{}`, expected {}", + variant, + OneOf { names: expected })) + } + } + + /// Raised when a `Deserialize` struct type received a field with an + /// unrecognized name. + fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { + if expected.is_empty() { + Error::custom(format_args!("unknown field `{}`, there are no fields", + field)) + } else { + Error::custom(format_args!("unknown field `{}`, expected {}", + field, + OneOf { names: 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_args!("missing field `{}`", field)) + } + + /// Raised when a `Deserialize` struct type received more than one of the + /// same field. + fn duplicate_field(field: &'static str) -> Self { + Error::custom(format_args!("duplicate field `{}`", field)) + } } } - - /// Raised when a `Deserialize` struct type received a field with an - /// unrecognized name. - fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { - if expected.is_empty() { - Error::custom(format_args!("unknown field `{}`, there are no fields", - field)) - } else { - Error::custom(format_args!("unknown field `{}`, expected {}", - field, - OneOf { names: 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_args!("missing field `{}`", field)) - } - - /// Raised when a `Deserialize` struct type received more than one of the - /// same field. - fn duplicate_field(field: &'static str) -> Self { - Error::custom(format_args!("duplicate field `{}`", field)) - } } +#[cfg(feature = "std")] +declare_error_trait!(Error: Sized + error::Error); + +#[cfg(not(feature = "std"))] +declare_error_trait!(Error: Sized); + /// `Unexpected` represents an unexpected invocation of any one of the `Visitor` /// trait methods. /// diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index f4d1eba0..3b157b0c 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -21,8 +21,6 @@ use collections::string::ToString; use core::hash::Hash; #[cfg(feature = "std")] use std::error; -#[cfg(not(feature = "std"))] -use error; use core::fmt::{self, Display}; use core::iter::{self, Iterator}; @@ -67,16 +65,11 @@ impl Display for Error { } } +#[cfg(feature = "std")] impl error::Error for Error { - #[cfg(any(feature = "std", feature = "collections"))] fn description(&self) -> &str { &self.err } - - #[cfg(not(any(feature = "std", feature = "collections")))] - fn description(&self) -> &str { - "Serde deserialization error" - } } /////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/error.rs b/serde/src/error.rs deleted file mode 100644 index fe91c28f..00000000 --- a/serde/src/error.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! A stand-in for `std::error` -use core::fmt::{Debug, Display}; - -/// A stand-in for `std::error::Error`, which requires no allocation. -pub trait Error: Debug + Display { - /// A short description of the error. - /// - /// The description should not contain newlines or sentence-ending - /// punctuation, to facilitate embedding in larger user-facing - /// strings. - fn description(&self) -> &str; - - /// The lower-level cause of this error, if any. - fn cause(&self) -> Option<&Error> { - None - } -} diff --git a/serde/src/lib.rs b/serde/src/lib.rs index eb7aa326..3fe7ec57 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -98,8 +98,6 @@ pub mod de; #[doc(hidden)] pub mod iter; pub mod ser; -#[cfg_attr(feature = "std", doc(hidden))] -pub mod error; mod utils; // Generated code uses these to support no_std. Not public API. diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index fb9ef2dd..475d6836 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -94,8 +94,6 @@ #[cfg(feature = "std")] use std::error; -#[cfg(not(feature = "std"))] -use error; #[cfg(all(feature = "collections", not(feature = "std")))] use collections::string::String; @@ -117,35 +115,47 @@ pub use self::impossible::Impossible; /////////////////////////////////////////////////////////////////////////////// -/// Trait used by `Serialize` implementations to generically construct errors -/// belonging to the `Serializer` against which they are currently running. -pub trait Error: Sized + error::Error { - /// Raised when a `Serialize` implementation encounters a general error - /// while serializing a type. - /// - /// The message should not be capitalized and should not end with a period. - /// - /// For example, a filesystem `Path` may refuse to serialize itself if it - /// contains invalid UTF-8 data. - /// - /// ```rust - /// # use serde::ser::{Serialize, Serializer, Error}; - /// # struct Path; - /// # impl Path { fn to_str(&self) -> Option<&str> { unimplemented!() } } - /// impl Serialize for Path { - /// fn serialize(&self, serializer: S) -> Result - /// where S: Serializer - /// { - /// match self.to_str() { - /// Some(s) => s.serialize(serializer), - /// None => Err(Error::custom("path contains invalid UTF-8 characters")), - /// } - /// } - /// } - /// ``` - fn custom(msg: T) -> Self; +macro_rules! declare_error_trait { + (Error: Sized $(+ $supertrait:path)*) => { + /// Trait used by `Serialize` implementations to generically construct + /// errors belonging to the `Serializer` against which they are + /// currently running. + pub trait Error: Sized $(+ $supertrait)* { + /// Raised when a `Serialize` implementation encounters a general + /// error while serializing a type. + /// + /// The message should not be capitalized and should not end with a + /// period. + /// + /// For example, a filesystem `Path` may refuse to serialize itself + /// if it contains invalid UTF-8 data. + /// + /// ```rust + /// # use serde::ser::{Serialize, Serializer, Error}; + /// # struct Path; + /// # impl Path { fn to_str(&self) -> Option<&str> { unimplemented!() } } + /// impl Serialize for Path { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match self.to_str() { + /// Some(s) => s.serialize(serializer), + /// None => Err(Error::custom("path contains invalid UTF-8 characters")), + /// } + /// } + /// } + /// ``` + fn custom(msg: T) -> Self; + } + } } +#[cfg(feature = "std")] +declare_error_trait!(Error: Sized + error::Error); + +#[cfg(not(feature = "std"))] +declare_error_trait!(Error: Sized); + /////////////////////////////////////////////////////////////////////////////// /// A **data structure** that can be serialized into any data format supported