diff --git a/Cargo.toml b/Cargo.toml index 601a709e..29db37d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [workspace] members = [ "serde", - "serde_codegen_internals", "serde_derive", + "serde_derive_internals", "serde_test", "test_suite", "test_suite/no_std", diff --git a/README.md b/README.md index 358f9b22..c2f35e9c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) +# Serde   [![Build Status]][travis] [![Latest Version]][crates.io] + +[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master +[travis]: https://travis-ci.org/serde-rs/serde +[Latest Version]: https://img.shields.io/crates/v/serde.svg +[crates.io]: https://crates.io/crates/serde **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..914d19d6 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,5 @@ +fn_args_layout = "Block" +array_layout = "Block" +where_style = "Rfc" +generics_indent = "Block" +fn_call_style = "Block" diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 1c7e1c41..c1b4709f 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.9.14" +version = "0.9.14" # remember to update html_root_url authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" @@ -9,27 +9,68 @@ repository = "https://github.com/serde-rs/serde" documentation = "https://docs.serde.rs/serde/" keywords = ["serde", "serialization", "no_std"] categories = ["encoding"] -readme = "../README.md" +readme = "README.md" include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] +publish = false # this branch contains breaking changes [badges] travis-ci = { repository = "serde-rs/serde" } - -[features] -default = ["std"] -derive = ["serde_derive"] - -std = [] -unstable = [] -alloc = ["unstable"] -collections = ["alloc"] -unstable-testing = ["unstable", "std"] - -# to get serde_derive picked up by play.integer32.com -playground = ["serde_derive"] +appveyor = { repository = "serde-rs/serde" } [dependencies] serde_derive = { version = "0.9", optional = true, path = "../serde_derive" } [dev-dependencies] serde_derive = { version = "0.9", path = "../serde_derive" } + + +### FEATURES ################################################################# + +[features] +default = ["std"] + +# Re-export the derive(Serialize, Deserialize) macros. This is specifically +# intended for library crates that provide optional Serde impls behind a Cargo +# cfg of their own. All other crates should depend on serde_derive directly. +# +# Please refer to the long comment above the line `pub use serde_derive::*` in +# src/lib.rs before enabling this feature. If you think you need this feature +# and your use case does not precisely match the one described in the comment, +# please open an issue to let us know about your use case. +derive = ["serde_derive"] + +# Provide impls for common standard library types like Vec and HashMap. +# Requires a dependency on the Rust standard library. +std = [] + +# Provide impls for types that require unstable functionality. For tracking and +# discussion of unstable functionality please refer to this issue: +# +# https://github.com/serde-rs/serde/issues/812 +unstable = [] + +# Provide impls for types that require memory allocation like Box and Rc. +# This is a subset of std but may be enabled without depending on all of std. +# +# Requires a dependency on the unstable core allocation library: +# +# https://doc.rust-lang.org/alloc/ +alloc = ["unstable"] + +# Provide impls for collection types like String and Cow. This is a subset of +# std but may be enabled without depending on all of std. +# +# Requires a dependency on the unstable collections library: +# +# https://doc.rust-lang.org/collections/ +collections = ["alloc"] + +# Opt into impls for Rc and Arc. Serializing and deserializing these types +# does not preserve identity and may result in multiple copies of the same data. +# Be sure that this is what you want before enabling this feature. +rc = [] + +# Get serde_derive picked up by the Integer 32 playground. Not public API. +# +# http://play.integer32.com/ +playground = ["serde_derive"] diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs deleted file mode 100644 index d1ea0189..00000000 --- a/serde/src/bytes.rs +++ /dev/null @@ -1,315 +0,0 @@ -//! Wrapper types to enable optimized handling of `&[u8]` and `Vec`. -//! -//! Without specialization, Rust forces us to treat `&[u8]` just like any other -//! slice and `Vec` just like any other vector. In reality this particular -//! slice and vector can often be serialized and deserialized in a more -//! efficient, compact representation in many formats. -//! -//! When working with such a format, you can opt into specialized handling of -//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec` by wrapping it in -//! `bytes::ByteBuf`. -//! -//! Rust support for specialization is being tracked in -//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler -//! we will be deprecating these wrapper types in favor of optimizing `&[u8]` -//! and `Vec` out of the box. -//! -//! [specialization]: https://github.com/rust-lang/rust/issues/31844 - -use core::{ops, fmt, char, iter, slice}; -use core::fmt::Write; - -use ser; - -#[cfg(any(feature = "std", feature = "collections"))] -pub use self::bytebuf::ByteBuf; - -#[cfg(any(feature = "std", feature = "collections"))] -#[doc(hidden)] // does anybody need this? -pub use self::bytebuf::ByteBufVisitor; - -#[cfg(feature = "collections")] -use collections::Vec; - -/////////////////////////////////////////////////////////////////////////////// - -/// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support -/// deserialization. -/// -/// ```rust -/// # #[macro_use] extern crate serde_derive; -/// # extern crate serde; -/// # use std::net::IpAddr; -/// # -/// use serde::bytes::Bytes; -/// -/// # #[allow(dead_code)] -/// #[derive(Serialize)] -/// struct Packet<'a> { -/// destination: IpAddr, -/// payload: Bytes<'a>, -/// } -/// # -/// # fn main() {} -/// ``` -#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)] -pub struct Bytes<'a> { - bytes: &'a [u8], -} - -impl<'a> Bytes<'a> { - /// Wrap an existing `&[u8]`. - pub fn new(bytes: &'a [u8]) -> Self { - Bytes { bytes: bytes } - } -} - -impl<'a> fmt::Debug for Bytes<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(f.write_str("b\"")); - for c in escape_bytestring(self.bytes) { - try!(f.write_char(c)); - } - f.write_char('"') - } -} - -impl<'a> From<&'a [u8]> for Bytes<'a> { - fn from(bytes: &'a [u8]) -> Self { - Bytes::new(bytes) - } -} - -#[cfg(any(feature = "std", feature = "collections"))] -impl<'a> From<&'a Vec> for Bytes<'a> { - fn from(bytes: &'a Vec) -> Self { - Bytes::new(bytes) - } -} - -impl<'a> Into<&'a [u8]> for Bytes<'a> { - fn into(self) -> &'a [u8] { - self.bytes - } -} - -impl<'a> ops::Deref for Bytes<'a> { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - self.bytes - } -} - -impl<'a> ser::Serialize for Bytes<'a> { - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: ser::Serializer - { - serializer.serialize_bytes(self.bytes) - } -} - -/////////////////////////////////////////////////////////////////////////////// - -#[cfg(any(feature = "std", feature = "collections"))] -mod bytebuf { - use core::cmp; - use core::ops; - use core::fmt; - use core::fmt::Write; - - use ser; - use de; - - #[cfg(feature = "collections")] - use collections::{String, Vec}; - - /// Wraps a `Vec` in order to serialize and deserialize in an efficient - /// way. - /// - /// ```rust - /// # #[macro_use] extern crate serde_derive; - /// # extern crate serde; - /// # use std::net::IpAddr; - /// # - /// use serde::bytes::ByteBuf; - /// - /// # #[allow(dead_code)] - /// #[derive(Serialize, Deserialize)] - /// struct Packet { - /// destination: IpAddr, - /// payload: ByteBuf, - /// } - /// # - /// # fn main() {} - /// ``` - #[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] - pub struct ByteBuf { - bytes: Vec, - } - - impl ByteBuf { - /// Construct a new, empty `ByteBuf`. - pub fn new() -> Self { - ByteBuf::from(Vec::new()) - } - - /// Construct a new, empty `ByteBuf` with the specified capacity. - pub fn with_capacity(cap: usize) -> Self { - ByteBuf::from(Vec::with_capacity(cap)) - } - - /// Wrap existing bytes in a `ByteBuf`. - pub fn from>>(bytes: T) -> Self { - ByteBuf { bytes: bytes.into() } - } - } - - impl fmt::Debug for ByteBuf { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(f.write_str("b\"")); - for c in super::escape_bytestring(self.bytes.as_ref()) { - try!(f.write_char(c)); - } - f.write_char('"') - } - } - - impl Into> for ByteBuf { - fn into(self) -> Vec { - self.bytes - } - } - - impl From> for ByteBuf { - fn from(bytes: Vec) -> Self { - ByteBuf::from(bytes) - } - } - - impl AsRef> for ByteBuf { - fn as_ref(&self) -> &Vec { - &self.bytes - } - } - - impl AsRef<[u8]> for ByteBuf { - fn as_ref(&self) -> &[u8] { - &self.bytes - } - } - - impl AsMut> for ByteBuf { - fn as_mut(&mut self) -> &mut Vec { - &mut self.bytes - } - } - - impl AsMut<[u8]> for ByteBuf { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.bytes - } - } - - impl ops::Deref for ByteBuf { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - &self.bytes[..] - } - } - - impl ops::DerefMut for ByteBuf { - fn deref_mut(&mut self) -> &mut [u8] { - &mut self.bytes[..] - } - } - - impl ser::Serialize for ByteBuf { - fn serialize(&self, serializer: S) -> Result - where S: ser::Serializer - { - serializer.serialize_bytes(self) - } - } - - /// This type implements the `serde::de::Visitor` trait for a `ByteBuf`. - pub struct ByteBufVisitor; - - 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 - { - Ok(ByteBuf::new()) - } - - #[inline] - fn visit_seq(self, mut visitor: V) -> Result - where V: de::SeqVisitor - { - let len = cmp::min(visitor.size_hint().0, 4096); - let mut values = Vec::with_capacity(len); - - while let Some(value) = try!(visitor.visit()) { - values.push(value); - } - - Ok(ByteBuf::from(values)) - } - - #[inline] - fn visit_bytes(self, v: &[u8]) -> Result - where E: de::Error - { - Ok(ByteBuf::from(v)) - } - - #[inline] - fn visit_byte_buf(self, v: Vec) -> Result - where E: de::Error - { - Ok(ByteBuf::from(v)) - } - - fn visit_str(self, v: &str) -> Result - where E: de::Error - { - Ok(ByteBuf::from(v)) - } - - fn visit_string(self, v: String) -> Result - where E: de::Error - { - Ok(ByteBuf::from(v)) - } - } - - impl de::Deserialize for ByteBuf { - #[inline] - fn deserialize(deserializer: D) -> Result - where D: de::Deserializer - { - deserializer.deserialize_byte_buf(ByteBufVisitor) - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -#[inline] -fn escape_bytestring<'a> - (bytes: &'a [u8]) - -> iter::FlatMap, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> { - fn f(b: &u8) -> char::EscapeDefault { - char::from_u32(*b as u32).unwrap().escape_default() - } - bytes.iter().flat_map(f as fn(&u8) -> char::EscapeDefault) -} diff --git a/serde/src/de/content.rs b/serde/src/de/content.rs deleted file mode 100644 index e784b4ec..00000000 --- a/serde/src/de/content.rs +++ /dev/null @@ -1,1338 +0,0 @@ -// This module is doc(hidden) and nothing here should be used outside of -// generated code. -// -// We will iterate on the implementation for a few releases and only have to -// worry about backward compatibility for the `untagged` and `tag` attributes -// rather than for this entire mechanism. -// -// This issue is tracking making some of this stuff public: -// https://github.com/serde-rs/serde/issues/741 - -#![doc(hidden)] - -use core::cmp; -use core::fmt; -use core::marker::PhantomData; - -#[cfg(all(not(feature = "std"), feature = "collections"))] -use collections::{String, Vec}; - -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::boxed::Box; - -use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqVisitor, MapVisitor, - EnumVisitor, Unexpected}; - -/// Used from generated code to buffer the contents of the Deserializer when -/// deserializing untagged enums and internally tagged enums. -/// -/// Not public API. Use serde-value instead. -#[derive(Debug)] -pub enum Content { - Bool(bool), - - U8(u8), - U16(u16), - U32(u32), - U64(u64), - - I8(i8), - I16(i16), - I32(i32), - I64(i64), - - F32(f32), - F64(f64), - - Char(char), - String(String), - Bytes(Vec), - - None, - Some(Box), - - Unit, - Newtype(Box), - Seq(Vec), - Map(Vec<(Content, Content)>), -} - -impl Content { - fn unexpected(&self) -> Unexpected { - match *self { - Content::Bool(b) => Unexpected::Bool(b), - Content::U8(n) => Unexpected::Unsigned(n as u64), - Content::U16(n) => Unexpected::Unsigned(n as u64), - Content::U32(n) => Unexpected::Unsigned(n as u64), - Content::U64(n) => Unexpected::Unsigned(n), - Content::I8(n) => Unexpected::Signed(n as i64), - Content::I16(n) => Unexpected::Signed(n as i64), - Content::I32(n) => Unexpected::Signed(n as i64), - Content::I64(n) => Unexpected::Signed(n), - Content::F32(f) => Unexpected::Float(f as f64), - Content::F64(f) => Unexpected::Float(f), - Content::Char(c) => Unexpected::Char(c), - Content::String(ref s) => Unexpected::Str(s), - Content::Bytes(ref b) => Unexpected::Bytes(b), - Content::None | Content::Some(_) => Unexpected::Option, - Content::Unit => Unexpected::Unit, - Content::Newtype(_) => Unexpected::NewtypeStruct, - Content::Seq(_) => Unexpected::Seq, - Content::Map(_) => Unexpected::Map, - } - } -} - -impl Deserialize for Content { - fn deserialize(deserializer: D) -> Result { - // Untagged and internally tagged enums are only supported in - // self-describing formats. - deserializer.deserialize(ContentVisitor) - } -} - -struct ContentVisitor; - -impl Visitor for ContentVisitor { - type Value = Content; - - fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str("any value") - } - - fn visit_bool(self, value: bool) -> Result - where F: de::Error - { - Ok(Content::Bool(value)) - } - - fn visit_i8(self, value: i8) -> Result - where F: de::Error - { - Ok(Content::I8(value)) - } - - fn visit_i16(self, value: i16) -> Result - where F: de::Error - { - Ok(Content::I16(value)) - } - - fn visit_i32(self, value: i32) -> Result - where F: de::Error - { - Ok(Content::I32(value)) - } - - fn visit_i64(self, value: i64) -> Result - where F: de::Error - { - Ok(Content::I64(value)) - } - - fn visit_u8(self, value: u8) -> Result - where F: de::Error - { - Ok(Content::U8(value)) - } - - fn visit_u16(self, value: u16) -> Result - where F: de::Error - { - Ok(Content::U16(value)) - } - - fn visit_u32(self, value: u32) -> Result - where F: de::Error - { - Ok(Content::U32(value)) - } - - fn visit_u64(self, value: u64) -> Result - where F: de::Error - { - Ok(Content::U64(value)) - } - - fn visit_f32(self, value: f32) -> Result - where F: de::Error - { - Ok(Content::F32(value)) - } - - fn visit_f64(self, value: f64) -> Result - where F: de::Error - { - Ok(Content::F64(value)) - } - - fn visit_char(self, value: char) -> Result - where F: de::Error - { - Ok(Content::Char(value)) - } - - fn visit_str(self, value: &str) -> Result - where F: de::Error - { - Ok(Content::String(value.into())) - } - - fn visit_string(self, value: String) -> Result - where F: de::Error - { - Ok(Content::String(value)) - } - - fn visit_bytes(self, value: &[u8]) -> Result - where F: de::Error - { - Ok(Content::Bytes(value.into())) - } - - fn visit_byte_buf(self, value: Vec) -> Result - where F: de::Error - { - Ok(Content::Bytes(value)) - } - - fn visit_unit(self) -> Result - where F: de::Error - { - Ok(Content::Unit) - } - - fn visit_none(self) -> Result - where F: de::Error - { - Ok(Content::None) - } - - fn visit_some(self, deserializer: D) -> Result - where D: Deserializer - { - Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v))) - } - - fn visit_newtype_struct(self, deserializer: D) -> Result - where D: Deserializer - { - Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v))) - } - - fn visit_seq(self, mut visitor: V) -> Result - where V: SeqVisitor - { - let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)); - while let Some(e) = try!(visitor.visit()) { - vec.push(e); - } - Ok(Content::Seq(vec)) - } - - fn visit_map(self, mut visitor: V) -> Result - where V: MapVisitor - { - let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)); - while let Some(kv) = try!(visitor.visit()) { - vec.push(kv); - } - Ok(Content::Map(vec)) - } - - fn visit_enum(self, _visitor: V) -> Result - where V: EnumVisitor - { - Err(de::Error::custom("untagged and internally tagged enums do not support enum input")) - } -} - -/// This is the type of the map keys in an internally tagged enum. -/// -/// Not public API. -pub enum TagOrContent { - Tag, - Content(Content), -} - -struct TagOrContentVisitor { - name: &'static str, -} - -impl TagOrContentVisitor { - fn new(name: &'static str) -> Self { - TagOrContentVisitor { name: name } - } -} - -impl DeserializeSeed for TagOrContentVisitor { - type Value = TagOrContent; - - fn deserialize(self, deserializer: D) -> Result - where D: Deserializer - { - // Internally tagged enums are only supported in self-describing - // formats. - deserializer.deserialize(self) - } -} - -impl Visitor for TagOrContentVisitor { - type Value = TagOrContent; - - fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "a type tag `{}` or any other value", self.name) - } - - fn visit_bool(self, value: bool) -> Result - where F: de::Error - { - ContentVisitor.visit_bool(value).map(TagOrContent::Content) - } - - fn visit_i8(self, value: i8) -> Result - where F: de::Error - { - ContentVisitor.visit_i8(value).map(TagOrContent::Content) - } - - fn visit_i16(self, value: i16) -> Result - where F: de::Error - { - ContentVisitor.visit_i16(value).map(TagOrContent::Content) - } - - fn visit_i32(self, value: i32) -> Result - where F: de::Error - { - ContentVisitor.visit_i32(value).map(TagOrContent::Content) - } - - fn visit_i64(self, value: i64) -> Result - where F: de::Error - { - ContentVisitor.visit_i64(value).map(TagOrContent::Content) - } - - fn visit_u8(self, value: u8) -> Result - where F: de::Error - { - ContentVisitor.visit_u8(value).map(TagOrContent::Content) - } - - fn visit_u16(self, value: u16) -> Result - where F: de::Error - { - ContentVisitor.visit_u16(value).map(TagOrContent::Content) - } - - fn visit_u32(self, value: u32) -> Result - where F: de::Error - { - ContentVisitor.visit_u32(value).map(TagOrContent::Content) - } - - fn visit_u64(self, value: u64) -> Result - where F: de::Error - { - ContentVisitor.visit_u64(value).map(TagOrContent::Content) - } - - fn visit_f32(self, value: f32) -> Result - where F: de::Error - { - ContentVisitor.visit_f32(value).map(TagOrContent::Content) - } - - fn visit_f64(self, value: f64) -> Result - where F: de::Error - { - ContentVisitor.visit_f64(value).map(TagOrContent::Content) - } - - fn visit_char(self, value: char) -> Result - where F: de::Error - { - ContentVisitor.visit_char(value).map(TagOrContent::Content) - } - - fn visit_str(self, value: &str) -> Result - where F: de::Error - { - if value == self.name { - Ok(TagOrContent::Tag) - } else { - ContentVisitor.visit_str(value).map(TagOrContent::Content) - } - } - - fn visit_string(self, value: String) -> Result - where F: de::Error - { - if value == self.name { - Ok(TagOrContent::Tag) - } else { - ContentVisitor.visit_string(value).map(TagOrContent::Content) - } - } - - fn visit_bytes(self, value: &[u8]) -> Result - where F: de::Error - { - if value == self.name.as_bytes() { - Ok(TagOrContent::Tag) - } else { - ContentVisitor.visit_bytes(value).map(TagOrContent::Content) - } - } - - fn visit_byte_buf(self, value: Vec) -> Result - where F: de::Error - { - if value == self.name.as_bytes() { - Ok(TagOrContent::Tag) - } else { - ContentVisitor.visit_byte_buf(value).map(TagOrContent::Content) - } - } - - fn visit_unit(self) -> Result - where F: de::Error - { - ContentVisitor.visit_unit().map(TagOrContent::Content) - } - - fn visit_none(self) -> Result - where F: de::Error - { - ContentVisitor.visit_none().map(TagOrContent::Content) - } - - fn visit_some(self, deserializer: D) -> Result - where D: Deserializer - { - ContentVisitor.visit_some(deserializer).map(TagOrContent::Content) - } - - fn visit_newtype_struct(self, deserializer: D) -> Result - where D: Deserializer - { - ContentVisitor.visit_newtype_struct(deserializer).map(TagOrContent::Content) - } - - fn visit_seq(self, visitor: V) -> Result - where V: SeqVisitor - { - ContentVisitor.visit_seq(visitor).map(TagOrContent::Content) - } - - fn visit_map(self, visitor: V) -> Result - where V: MapVisitor - { - ContentVisitor.visit_map(visitor).map(TagOrContent::Content) - } - - fn visit_enum(self, visitor: V) -> Result - where V: EnumVisitor - { - ContentVisitor.visit_enum(visitor).map(TagOrContent::Content) - } -} - -/// Used by generated code to deserialize an internally tagged enum. -/// -/// Not public API. -pub struct TaggedContent { - pub tag: T, - pub content: Content, -} - -/// Not public API. -pub struct TaggedContentVisitor { - tag_name: &'static str, - tag: PhantomData, -} - -impl TaggedContentVisitor { - /// Visitor for the content of an internally tagged enum with the given tag - /// name. - pub fn new(name: &'static str) -> Self { - TaggedContentVisitor { - tag_name: name, - tag: PhantomData, - } - } -} - -impl DeserializeSeed for TaggedContentVisitor - where T: Deserialize -{ - type Value = TaggedContent; - - fn deserialize(self, deserializer: D) -> Result - where D: Deserializer - { - // Internally tagged enums are only supported in self-describing - // formats. - deserializer.deserialize(self) - } -} - -impl Visitor for TaggedContentVisitor - where T: Deserialize -{ - type Value = TaggedContent; - - fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str("any value") - } - - fn visit_map(self, mut visitor: V) -> Result - where V: MapVisitor - { - let mut tag = None; - let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)); - while let Some(k) = try!(visitor.visit_key_seed(TagOrContentVisitor::new(self.tag_name))) { - match k { - TagOrContent::Tag => { - if tag.is_some() { - return Err(de::Error::duplicate_field(self.tag_name)); - } - tag = Some(try!(visitor.visit_value())); - } - TagOrContent::Content(k) => { - let v = try!(visitor.visit_value()); - vec.push((k, v)); - } - } - } - match tag { - None => Err(de::Error::missing_field(self.tag_name)), - Some(tag) => { - Ok(TaggedContent { - tag: tag, - content: Content::Map(vec), - }) - } - } - } -} - -/// Used by generated code to deserialize an adjacently tagged enum. -/// -/// Not public API. -pub enum TagOrContentField { - Tag, - Content, -} - -/// Not public API. -pub struct TagOrContentFieldVisitor { - pub tag: &'static str, - pub content: &'static str, -} - -impl DeserializeSeed for TagOrContentFieldVisitor { - type Value = TagOrContentField; - - fn deserialize(self, deserializer: D) -> Result - where D: Deserializer - { - deserializer.deserialize_str(self) - } -} - -impl Visitor for TagOrContentFieldVisitor { - type Value = TagOrContentField; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "{:?} or {:?}", self.tag, self.content) - } - - fn visit_str(self, field: &str) -> Result - where E: de::Error - { - if field == self.tag { - Ok(TagOrContentField::Tag) - } else if field == self.content { - Ok(TagOrContentField::Content) - } else { - Err(de::Error::invalid_value(Unexpected::Str(field), &self)) - } - } -} - -/// Not public API -pub struct ContentDeserializer { - content: Content, - err: PhantomData, -} - -/// Used when deserializing an internally tagged enum because the content will -/// be used exactly once. -impl Deserializer for ContentDeserializer - where E: de::Error -{ - type Error = E; - - fn deserialize(self, visitor: V) -> Result - where V: Visitor - { - match self.content { - Content::Bool(v) => visitor.visit_bool(v), - Content::U8(v) => visitor.visit_u8(v), - Content::U16(v) => visitor.visit_u16(v), - Content::U32(v) => visitor.visit_u32(v), - Content::U64(v) => visitor.visit_u64(v), - Content::I8(v) => visitor.visit_i8(v), - Content::I16(v) => visitor.visit_i16(v), - Content::I32(v) => visitor.visit_i32(v), - Content::I64(v) => visitor.visit_i64(v), - Content::F32(v) => visitor.visit_f32(v), - Content::F64(v) => visitor.visit_f64(v), - Content::Char(v) => visitor.visit_char(v), - Content::String(v) => visitor.visit_string(v), - Content::Unit => visitor.visit_unit(), - Content::None => visitor.visit_none(), - Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), - Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)), - Content::Seq(v) => { - let seq = v.into_iter().map(ContentDeserializer::new); - let mut seq_visitor = de::value::SeqDeserializer::new(seq); - let value = try!(visitor.visit_seq(&mut seq_visitor)); - try!(seq_visitor.end()); - Ok(value) - } - Content::Map(v) => { - let map = v.into_iter().map(|(k, v)| { - (ContentDeserializer::new(k), - ContentDeserializer::new(v)) - }); - let mut map_visitor = de::value::MapDeserializer::new(map); - let value = try!(visitor.visit_map(&mut map_visitor)); - try!(map_visitor.end()); - Ok(value) - } - Content::Bytes(v) => visitor.visit_byte_buf(v), - } - } - - fn deserialize_option(self, visitor: V) -> Result - where V: Visitor - { - match self.content { - Content::None => visitor.visit_none(), - Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), - Content::Unit => visitor.visit_unit(), - _ => visitor.visit_some(self), - } - } - - fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result - where V: Visitor - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_enum(self, - _name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor - { - let (variant, value) = match self.content { - Content::Map(value) => { - let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(de::Error::invalid_value(de::Unexpected::Map, - &"map with a single key")); - } - }; - // enums are encoded in json as maps with a single key:value pair - if iter.next().is_some() { - return Err(de::Error::invalid_value(de::Unexpected::Map, - &"map with a single key")); - } - (variant, Some(value)) - } - Content::String(variant) => (Content::String(variant), None), - other => { - return Err(de::Error::invalid_type(other.unexpected(), &"string or map")); - } - }; - - visitor.visit_enum(EnumDeserializer { - variant: variant, - value: value, - err: PhantomData, - }) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq - seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct - struct_field tuple ignored_any - } -} - -impl ContentDeserializer { - /// private API, don't use - pub fn new(content: Content) -> Self { - ContentDeserializer { - content: content, - err: PhantomData, - } - } -} - -struct EnumDeserializer - where E: de::Error -{ - variant: Content, - value: Option, - err: PhantomData, -} - -impl de::EnumVisitor for EnumDeserializer - where E: de::Error -{ - type Error = E; - type Variant = VariantDeserializer; - - fn visit_variant_seed(self, - seed: V) - -> Result<(V::Value, VariantDeserializer), Self::Error> - where V: de::DeserializeSeed - { - let visitor = VariantDeserializer { - value: self.value, - err: PhantomData, - }; - seed.deserialize(ContentDeserializer::new(self.variant)).map(|v| (v, visitor)) - } -} - -struct VariantDeserializer - where E: de::Error -{ - value: Option, - err: PhantomData, -} - -impl de::VariantVisitor for VariantDeserializer - where E: de::Error -{ - type Error = E; - - fn visit_unit(self) -> Result<(), E> { - match self.value { - Some(value) => de::Deserialize::deserialize(ContentDeserializer::new(value)), - None => Ok(()), - } - } - - fn visit_newtype_seed(self, seed: T) -> Result - where T: de::DeserializeSeed - { - match self.value { - Some(value) => seed.deserialize(ContentDeserializer::new(value)), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant")), - } - } - - fn visit_tuple(self, _len: usize, visitor: V) -> Result - where V: de::Visitor - { - match self.value { - Some(Content::Seq(v)) => { - de::Deserializer::deserialize(SeqDeserializer::new(v), visitor) - } - Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant")), - } - } - - fn visit_struct(self, - _fields: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor - { - match self.value { - Some(Content::Map(v)) => { - de::Deserializer::deserialize(MapDeserializer::new(v), visitor) - } - Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")), - _ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant")), - } - } -} - -struct SeqDeserializer - where E: de::Error -{ - iter: as IntoIterator>::IntoIter, - err: PhantomData, -} - -impl SeqDeserializer - where E: de::Error -{ - fn new(vec: Vec) -> Self { - SeqDeserializer { - iter: vec.into_iter(), - err: PhantomData, - } - } -} - -impl de::Deserializer for SeqDeserializer - where E: de::Error -{ - type Error = E; - - #[inline] - fn deserialize(mut self, visitor: V) -> Result - where V: de::Visitor - { - let len = self.iter.len(); - if len == 0 { - visitor.visit_unit() - } else { - let ret = try!(visitor.visit_seq(&mut self)); - let remaining = self.iter.len(); - if remaining == 0 { - Ok(ret) - } else { - Err(de::Error::invalid_length(len, &"fewer elements in array")) - } - } - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct - tuple_struct struct struct_field tuple enum ignored_any - } -} - -impl de::SeqVisitor for SeqDeserializer - where E: de::Error -{ - type Error = E; - - fn visit_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed - { - match self.iter.next() { - Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some), - None => Ok(None), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -struct MapDeserializer - where E: de::Error -{ - iter: as IntoIterator>::IntoIter, - value: Option, - err: PhantomData, -} - -impl MapDeserializer - where E: de::Error -{ - fn new(map: Vec<(Content, Content)>) -> Self { - MapDeserializer { - iter: map.into_iter(), - value: None, - err: PhantomData, - } - } -} - -impl de::MapVisitor for MapDeserializer - where E: de::Error -{ - type Error = E; - - fn visit_key_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed - { - match self.iter.next() { - Some((key, value)) => { - self.value = Some(value); - seed.deserialize(ContentDeserializer::new(key)).map(Some) - } - None => Ok(None), - } - } - - fn visit_value_seed(&mut self, seed: T) -> Result - where T: de::DeserializeSeed - { - match self.value.take() { - Some(value) => seed.deserialize(ContentDeserializer::new(value)), - None => Err(de::Error::custom("value is missing")), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl de::Deserializer for MapDeserializer - where E: de::Error -{ - type Error = E; - - #[inline] - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor - { - visitor.visit_map(self) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct - tuple_struct struct struct_field tuple enum ignored_any - } -} - - -/// Not public API. -pub struct ContentRefDeserializer<'a, E> { - content: &'a Content, - err: PhantomData, -} - -/// Used when deserializing an untagged enum because the content may need to be -/// used more than once. -impl<'a, E> Deserializer for ContentRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - fn deserialize(self, visitor: V) -> Result - where V: Visitor - { - match *self.content { - Content::Bool(v) => visitor.visit_bool(v), - Content::U8(v) => visitor.visit_u8(v), - Content::U16(v) => visitor.visit_u16(v), - Content::U32(v) => visitor.visit_u32(v), - Content::U64(v) => visitor.visit_u64(v), - Content::I8(v) => visitor.visit_i8(v), - Content::I16(v) => visitor.visit_i16(v), - Content::I32(v) => visitor.visit_i32(v), - Content::I64(v) => visitor.visit_i64(v), - Content::F32(v) => visitor.visit_f32(v), - Content::F64(v) => visitor.visit_f64(v), - Content::Char(v) => visitor.visit_char(v), - Content::String(ref v) => visitor.visit_str(v), - Content::Unit => visitor.visit_unit(), - Content::None => visitor.visit_none(), - Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), - Content::Newtype(ref v) => visitor.visit_newtype_struct(ContentRefDeserializer::new(v)), - Content::Seq(ref v) => { - let seq = v.into_iter().map(ContentRefDeserializer::new); - let mut seq_visitor = de::value::SeqDeserializer::new(seq); - let value = try!(visitor.visit_seq(&mut seq_visitor)); - try!(seq_visitor.end()); - Ok(value) - } - Content::Map(ref v) => { - let map = v.into_iter().map(|&(ref k, ref v)| { - (ContentRefDeserializer::new(k), - ContentRefDeserializer::new(v)) - }); - let mut map_visitor = de::value::MapDeserializer::new(map); - let value = try!(visitor.visit_map(&mut map_visitor)); - try!(map_visitor.end()); - Ok(value) - } - Content::Bytes(ref v) => visitor.visit_bytes(v), - } - } - - fn deserialize_option(self, visitor: V) -> Result - where V: Visitor - { - match *self.content { - Content::None => visitor.visit_none(), - Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), - Content::Unit => visitor.visit_unit(), - _ => visitor.visit_some(self), - } - } - - fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result - where V: Visitor - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_enum(self, - _name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor - { - let (variant, value) = match *self.content { - Content::Map(ref value) => { - let mut iter = value.into_iter(); - let &(ref variant, ref value) = match iter.next() { - Some(v) => v, - None => { - return Err(de::Error::invalid_value(de::Unexpected::Map, - &"map with a single key")); - } - }; - // enums are encoded in json as maps with a single key:value pair - if iter.next().is_some() { - return Err(de::Error::invalid_value(de::Unexpected::Map, - &"map with a single key")); - } - (variant, Some(value)) - } - ref s @ Content::String(_) => (s, None), - ref other => { - return Err(de::Error::invalid_type(other.unexpected(), &"string or map")); - } - }; - - visitor.visit_enum(EnumRefDeserializer { - variant: variant, - value: value, - err: PhantomData, - }) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq - seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct - struct_field tuple ignored_any - } -} - -impl<'a, E> ContentRefDeserializer<'a, E> { - /// private API, don't use - pub fn new(content: &'a Content) -> Self { - ContentRefDeserializer { - content: content, - err: PhantomData, - } - } -} - -struct EnumRefDeserializer<'a, E> - where E: de::Error -{ - variant: &'a Content, - value: Option<&'a Content>, - err: PhantomData, -} - -impl<'a, E> de::EnumVisitor for EnumRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - type Variant = VariantRefDeserializer<'a, Self::Error>; - - fn visit_variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> - where V: de::DeserializeSeed - { - let visitor = VariantRefDeserializer { - value: self.value, - err: PhantomData, - }; - seed.deserialize(ContentRefDeserializer::new(self.variant)).map(|v| (v, visitor)) - } -} - -struct VariantRefDeserializer<'a, E> - where E: de::Error -{ - value: Option<&'a Content>, - err: PhantomData, -} - -impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - fn visit_unit(self) -> Result<(), E> { - match self.value { - Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)), - None => Ok(()), - } - } - - fn visit_newtype_seed(self, seed: T) -> Result - where T: de::DeserializeSeed - { - match self.value { - Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant")), - } - } - - fn visit_tuple(self, _len: usize, visitor: V) -> Result - where V: de::Visitor - { - match self.value { - Some(&Content::Seq(ref v)) => { - de::Deserializer::deserialize(SeqRefDeserializer::new(v), visitor) - } - Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant")), - } - } - - fn visit_struct(self, - _fields: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor - { - match self.value { - Some(&Content::Map(ref v)) => { - de::Deserializer::deserialize(MapRefDeserializer::new(v), visitor) - } - Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")), - _ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant")), - } - } -} - -struct SeqRefDeserializer<'a, E> - where E: de::Error -{ - iter: <&'a [Content] as IntoIterator>::IntoIter, - err: PhantomData, -} - -impl<'a, E> SeqRefDeserializer<'a, E> - where E: de::Error -{ - fn new(vec: &'a [Content]) -> Self { - SeqRefDeserializer { - iter: vec.into_iter(), - err: PhantomData, - } - } -} - -impl<'a, E> de::Deserializer for SeqRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - #[inline] - fn deserialize(mut self, visitor: V) -> Result - where V: de::Visitor - { - let len = self.iter.len(); - if len == 0 { - visitor.visit_unit() - } else { - let ret = try!(visitor.visit_seq(&mut self)); - let remaining = self.iter.len(); - if remaining == 0 { - Ok(ret) - } else { - Err(de::Error::invalid_length(len, &"fewer elements in array")) - } - } - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct - tuple_struct struct struct_field tuple enum ignored_any - } -} - -impl<'a, E> de::SeqVisitor for SeqRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - fn visit_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed - { - match self.iter.next() { - Some(value) => seed.deserialize(ContentRefDeserializer::new(value)).map(Some), - None => Ok(None), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -struct MapRefDeserializer<'a, E> - where E: de::Error -{ - iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter, - value: Option<&'a Content>, - err: PhantomData, -} - -impl<'a, E> MapRefDeserializer<'a, E> - where E: de::Error -{ - fn new(map: &'a [(Content, Content)]) -> Self { - MapRefDeserializer { - iter: map.into_iter(), - value: None, - err: PhantomData, - } - } -} - -impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - fn visit_key_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed - { - match self.iter.next() { - Some(&(ref key, ref value)) => { - self.value = Some(value); - seed.deserialize(ContentRefDeserializer::new(key)).map(Some) - } - None => Ok(None), - } - } - - fn visit_value_seed(&mut self, seed: T) -> Result - where T: de::DeserializeSeed - { - match self.value.take() { - Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), - None => Err(de::Error::custom("value is missing")), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl<'a, E> de::Deserializer for MapRefDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - #[inline] - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor - { - visitor.visit_map(self) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct - tuple_struct struct struct_field tuple enum ignored_any - } -} - -impl de::value::ValueDeserializer for ContentDeserializer - where E: de::Error -{ - type Deserializer = Self; - - fn into_deserializer(self) -> Self { - self - } -} - -impl<'a, E> de::value::ValueDeserializer for ContentRefDeserializer<'a, E> - where E: de::Error -{ - type Deserializer = Self; - - fn into_deserializer(self) -> Self { - self - } -} - -/// Visitor for deserializing an internally tagged unit variant. -/// -/// Not public API. -pub struct InternallyTaggedUnitVisitor<'a> { - type_name: &'a str, - variant_name: &'a str, -} - -impl<'a> InternallyTaggedUnitVisitor<'a> { - /// Not public API. - pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { - InternallyTaggedUnitVisitor { - type_name: type_name, - variant_name: variant_name, - } - } -} - -impl<'a> Visitor for InternallyTaggedUnitVisitor<'a> { - type Value = (); - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name) - } - - fn visit_map(self, _: V) -> Result<(), V::Error> - where V: MapVisitor - { - Ok(()) - } -} - -/// Visitor for deserializing an untagged unit variant. -/// -/// Not public API. -pub struct UntaggedUnitVisitor<'a> { - type_name: &'a str, - variant_name: &'a str, -} - -impl<'a> UntaggedUnitVisitor<'a> { - /// Not public API. - pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { - UntaggedUnitVisitor { - type_name: type_name, - variant_name: variant_name, - } - } -} - -impl<'a> Visitor for UntaggedUnitVisitor<'a> { - type Value = (); - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name) - } - - fn visit_unit(self) -> Result<(), E> - where E: de::Error - { - Ok(()) - } -} diff --git a/serde/src/de/from_primitive.rs b/serde/src/de/from_primitive.rs index 14e51860..ae293952 100644 --- a/serde/src/de/from_primitive.rs +++ b/serde/src/de/from_primitive.rs @@ -1,6 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. +// Copyright 2017 Serde Developers // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -8,402 +6,111 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Extracted from https://github.com/rust-num/num. +use lib::*; -// Rust 1.5 is unhappy that this private module is undocumented. -#![allow(missing_docs)] - -use core::{usize, u8, u16, u32, u64}; -use core::{isize, i8, i16, i32, i64}; -use core::{f32, f64}; -use core::mem::size_of; - -/// Numbers which have upper and lower bounds -pub trait Bounded { - // FIXME (#5527): These should be associated constants - /// returns the smallest finite number this type can represent - fn min_value() -> Self; - /// returns the largest finite number this type can represent - fn max_value() -> Self; -} - -macro_rules! bounded_impl { - ($t:ty, $min:expr, $max:expr) => { - impl Bounded for $t { - #[inline] - fn min_value() -> $t { $min } - - #[inline] - fn max_value() -> $t { $max } - } - } -} - -bounded_impl!(usize, usize::MIN, usize::MAX); -bounded_impl!(u8, u8::MIN, u8::MAX); -bounded_impl!(u16, u16::MIN, u16::MAX); -bounded_impl!(u32, u32::MIN, u32::MAX); -bounded_impl!(u64, u64::MIN, u64::MAX); - -bounded_impl!(isize, isize::MIN, isize::MAX); -bounded_impl!(i8, i8::MIN, i8::MAX); -bounded_impl!(i16, i16::MIN, i16::MAX); -bounded_impl!(i32, i32::MIN, i32::MAX); -bounded_impl!(i64, i64::MIN, i64::MAX); - -bounded_impl!(f32, f32::MIN, f32::MAX); -bounded_impl!(f64, f64::MIN, f64::MAX); - -/// A generic trait for converting a value to a number. -pub trait ToPrimitive { - /// Converts the value of `self` to an `isize`. - #[inline] - fn to_isize(&self) -> Option { - self.to_i64().and_then(|x| x.to_isize()) - } - - /// Converts the value of `self` to an `i8`. - #[inline] - fn to_i8(&self) -> Option { - self.to_i64().and_then(|x| x.to_i8()) - } - - /// Converts the value of `self` to an `i16`. - #[inline] - fn to_i16(&self) -> Option { - self.to_i64().and_then(|x| x.to_i16()) - } - - /// Converts the value of `self` to an `i32`. - #[inline] - fn to_i32(&self) -> Option { - self.to_i64().and_then(|x| x.to_i32()) - } - - /// Converts the value of `self` to an `i64`. - fn to_i64(&self) -> Option; - - /// Converts the value of `self` to a `usize`. - #[inline] - fn to_usize(&self) -> Option { - self.to_u64().and_then(|x| x.to_usize()) - } - - /// Converts the value of `self` to an `u8`. - #[inline] - fn to_u8(&self) -> Option { - self.to_u64().and_then(|x| x.to_u8()) - } - - /// Converts the value of `self` to an `u16`. - #[inline] - fn to_u16(&self) -> Option { - self.to_u64().and_then(|x| x.to_u16()) - } - - /// Converts the value of `self` to an `u32`. - #[inline] - fn to_u32(&self) -> Option { - self.to_u64().and_then(|x| x.to_u32()) - } - - /// Converts the value of `self` to an `u64`. - #[inline] - fn to_u64(&self) -> Option; - - /// Converts the value of `self` to an `f32`. - #[inline] - fn to_f32(&self) -> Option { - self.to_f64().and_then(|x| x.to_f32()) - } - - /// Converts the value of `self` to an `f64`. - #[inline] - fn to_f64(&self) -> Option { - self.to_i64().and_then(|x| x.to_f64()) - } -} - -macro_rules! impl_to_primitive_int_to_int { - ($SrcT:ty, $DstT:ty, $slf:expr) => ( - { - if size_of::<$SrcT>() <= size_of::<$DstT>() { - Some($slf as $DstT) - } else { - let n = $slf as i64; - let min_value: $DstT = Bounded::min_value(); - let max_value: $DstT = Bounded::max_value(); - if min_value as i64 <= n && n <= max_value as i64 { - Some($slf as $DstT) - } else { - None - } - } - } - ) -} - -macro_rules! impl_to_primitive_int_to_uint { - ($SrcT:ty, $DstT:ty, $slf:expr) => ( - { - let zero: $SrcT = 0; - let max_value: $DstT = Bounded::max_value(); - if zero <= $slf && $slf as u64 <= max_value as u64 { - Some($slf as $DstT) - } else { - None - } - } - ) -} - -macro_rules! impl_to_primitive_int { - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_isize(&self) -> Option { impl_to_primitive_int_to_int!($T, isize, *self) } - #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8, *self) } - #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_int_to_int!($T, i16, *self) } - #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_int_to_int!($T, i32, *self) } - #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64, *self) } - - #[inline] - fn to_usize(&self) -> Option { impl_to_primitive_int_to_uint!($T, usize, *self) } - #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8, *self) } - #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_int_to_uint!($T, u16, *self) } - #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_int_to_uint!($T, u32, *self) } - #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_int_to_uint!($T, u64, *self) } - - #[inline] - fn to_f32(&self) -> Option { Some(*self as f32) } - #[inline] - fn to_f64(&self) -> Option { Some(*self as f64) } - } - ) -} - -impl_to_primitive_int! { isize } -impl_to_primitive_int! { i8 } -impl_to_primitive_int! { i16 } -impl_to_primitive_int! { i32 } -impl_to_primitive_int! { i64 } - -macro_rules! impl_to_primitive_uint_to_int { - ($DstT:ty, $slf:expr) => ( - { - let max_value: $DstT = Bounded::max_value(); - if $slf as u64 <= max_value as u64 { - Some($slf as $DstT) - } else { - None - } - } - ) -} - -macro_rules! impl_to_primitive_uint_to_uint { - ($SrcT:ty, $DstT:ty, $slf:expr) => ( - { - if size_of::<$SrcT>() <= size_of::<$DstT>() { - Some($slf as $DstT) - } else { - let zero: $SrcT = 0; - let max_value: $DstT = Bounded::max_value(); - if zero <= $slf && $slf as u64 <= max_value as u64 { - Some($slf as $DstT) - } else { - None - } - } - } - ) -} - -macro_rules! impl_to_primitive_uint { - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_isize(&self) -> Option { impl_to_primitive_uint_to_int!(isize, *self) } - #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8, *self) } - #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_uint_to_int!(i16, *self) } - #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_uint_to_int!(i32, *self) } - #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64, *self) } - - #[inline] - fn to_usize(&self) -> Option { - impl_to_primitive_uint_to_uint!($T, usize, *self) - } - #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8, *self) } - #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u16, *self) } - #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u32, *self) } - #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u64, *self) } - - #[inline] - fn to_f32(&self) -> Option { Some(*self as f32) } - #[inline] - fn to_f64(&self) -> Option { Some(*self as f64) } - } - ) -} - -impl_to_primitive_uint! { usize } -impl_to_primitive_uint! { u8 } -impl_to_primitive_uint! { u16 } -impl_to_primitive_uint! { u32 } -impl_to_primitive_uint! { u64 } - -macro_rules! impl_to_primitive_float_to_float { - ($SrcT:ident, $DstT:ident, $slf:expr) => ( - if size_of::<$SrcT>() <= size_of::<$DstT>() { - Some($slf as $DstT) +macro_rules! int_to_int { + ($dst:ident, $n:ident) => ( + if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 { + Some($n as $dst) } else { - let n = $slf as f64; - let max_value: $SrcT = ::core::$SrcT::MAX; - if -max_value as f64 <= n && n <= max_value as f64 { - Some($slf as $DstT) - } else { - None - } + None } ) } -macro_rules! impl_to_primitive_float { - ($T:ident) => ( - impl ToPrimitive for $T { - #[inline] - fn to_isize(&self) -> Option { Some(*self as isize) } - #[inline] - fn to_i8(&self) -> Option { Some(*self as i8) } - #[inline] - fn to_i16(&self) -> Option { Some(*self as i16) } - #[inline] - fn to_i32(&self) -> Option { Some(*self as i32) } - #[inline] - fn to_i64(&self) -> Option { Some(*self as i64) } - - #[inline] - fn to_usize(&self) -> Option { Some(*self as usize) } - #[inline] - fn to_u8(&self) -> Option { Some(*self as u8) } - #[inline] - fn to_u16(&self) -> Option { Some(*self as u16) } - #[inline] - fn to_u32(&self) -> Option { Some(*self as u32) } - #[inline] - fn to_u64(&self) -> Option { Some(*self as u64) } - - #[inline] - fn to_f32(&self) -> Option { impl_to_primitive_float_to_float!($T, f32, *self) } - #[inline] - fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64, *self) } +macro_rules! int_to_uint { + ($dst:ident, $n:ident) => ( + if 0 <= $n && $n as u64 <= $dst::MAX as u64 { + Some($n as $dst) + } else { + None } ) } -impl_to_primitive_float! { f32 } -impl_to_primitive_float! { f64 } +macro_rules! uint_to { + ($dst:ident, $n:ident) => ( + if $n as u64 <= $dst::MAX as u64 { + Some($n as $dst) + } else { + None + } + ) +} pub trait FromPrimitive: Sized { - #[inline] - fn from_isize(n: isize) -> Option { - FromPrimitive::from_i64(n as i64) - } - - #[inline] - fn from_i8(n: i8) -> Option { - FromPrimitive::from_i64(n as i64) - } - - #[inline] - fn from_i16(n: i16) -> Option { - FromPrimitive::from_i64(n as i64) - } - - #[inline] - fn from_i32(n: i32) -> Option { - FromPrimitive::from_i64(n as i64) - } - + fn from_isize(n: isize) -> Option; + fn from_i8(n: i8) -> Option; + fn from_i16(n: i16) -> Option; + fn from_i32(n: i32) -> Option; fn from_i64(n: i64) -> Option; - - #[inline] - fn from_usize(n: usize) -> Option { - FromPrimitive::from_u64(n as u64) - } - - #[inline] - fn from_u8(n: u8) -> Option { - FromPrimitive::from_u64(n as u64) - } - - #[inline] - fn from_u16(n: u16) -> Option { - FromPrimitive::from_u64(n as u64) - } - - #[inline] - fn from_u32(n: u32) -> Option { - FromPrimitive::from_u64(n as u64) - } - + fn from_usize(n: usize) -> Option; + fn from_u8(n: u8) -> Option; + fn from_u16(n: u16) -> Option; + fn from_u32(n: u32) -> Option; fn from_u64(n: u64) -> Option; - - #[inline] - fn from_f32(n: f32) -> Option { - FromPrimitive::from_f64(n as f64) - } - - #[inline] - fn from_f64(n: f64) -> Option { - FromPrimitive::from_i64(n as i64) - } } -macro_rules! impl_from_primitive { - ($T:ty, $to_ty:ident) => ( - impl FromPrimitive for $T { - #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() } - - #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() } - - #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() } - #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() } +macro_rules! impl_from_primitive_for_int { + ($t:ident) => ( + impl FromPrimitive for $t { + #[inline] fn from_isize(n: isize) -> Option { int_to_int!($t, n) } + #[inline] fn from_i8(n: i8) -> Option { int_to_int!($t, n) } + #[inline] fn from_i16(n: i16) -> Option { int_to_int!($t, n) } + #[inline] fn from_i32(n: i32) -> Option { int_to_int!($t, n) } + #[inline] fn from_i64(n: i64) -> Option { int_to_int!($t, n) } + #[inline] fn from_usize(n: usize) -> Option { uint_to!($t, n) } + #[inline] fn from_u8(n: u8) -> Option { uint_to!($t, n) } + #[inline] fn from_u16(n: u16) -> Option { uint_to!($t, n) } + #[inline] fn from_u32(n: u32) -> Option { uint_to!($t, n) } + #[inline] fn from_u64(n: u64) -> Option { uint_to!($t, n) } } ) } -impl_from_primitive! { isize, to_isize } -impl_from_primitive! { i8, to_i8 } -impl_from_primitive! { i16, to_i16 } -impl_from_primitive! { i32, to_i32 } -impl_from_primitive! { i64, to_i64 } -impl_from_primitive! { usize, to_usize } -impl_from_primitive! { u8, to_u8 } -impl_from_primitive! { u16, to_u16 } -impl_from_primitive! { u32, to_u32 } -impl_from_primitive! { u64, to_u64 } -impl_from_primitive! { f32, to_f32 } -impl_from_primitive! { f64, to_f64 } +macro_rules! impl_from_primitive_for_uint { + ($t:ident) => ( + impl FromPrimitive for $t { + #[inline] fn from_isize(n: isize) -> Option { int_to_uint!($t, n) } + #[inline] fn from_i8(n: i8) -> Option { int_to_uint!($t, n) } + #[inline] fn from_i16(n: i16) -> Option { int_to_uint!($t, n) } + #[inline] fn from_i32(n: i32) -> Option { int_to_uint!($t, n) } + #[inline] fn from_i64(n: i64) -> Option { int_to_uint!($t, n) } + #[inline] fn from_usize(n: usize) -> Option { uint_to!($t, n) } + #[inline] fn from_u8(n: u8) -> Option { uint_to!($t, n) } + #[inline] fn from_u16(n: u16) -> Option { uint_to!($t, n) } + #[inline] fn from_u32(n: u32) -> Option { uint_to!($t, n) } + #[inline] fn from_u64(n: u64) -> Option { uint_to!($t, n) } + } + ) +} + +macro_rules! impl_from_primitive_for_float { + ($t:ident) => ( + impl FromPrimitive for $t { + #[inline] fn from_isize(n: isize) -> Option { Some(n as Self) } + #[inline] fn from_i8(n: i8) -> Option { Some(n as Self) } + #[inline] fn from_i16(n: i16) -> Option { Some(n as Self) } + #[inline] fn from_i32(n: i32) -> Option { Some(n as Self) } + #[inline] fn from_i64(n: i64) -> Option { Some(n as Self) } + #[inline] fn from_usize(n: usize) -> Option { Some(n as Self) } + #[inline] fn from_u8(n: u8) -> Option { Some(n as Self) } + #[inline] fn from_u16(n: u16) -> Option { Some(n as Self) } + #[inline] fn from_u32(n: u32) -> Option { Some(n as Self) } + #[inline] fn from_u64(n: u64) -> Option { Some(n as Self) } + } + ) +} + +impl_from_primitive_for_int!(isize); +impl_from_primitive_for_int!(i8); +impl_from_primitive_for_int!(i16); +impl_from_primitive_for_int!(i32); +impl_from_primitive_for_int!(i64); +impl_from_primitive_for_uint!(usize); +impl_from_primitive_for_uint!(u8); +impl_from_primitive_for_uint!(u16); +impl_from_primitive_for_uint!(u32); +impl_from_primitive_for_uint!(u64); +impl_from_primitive_for_float!(f32); +impl_from_primitive_for_float!(f64); diff --git a/serde/src/de/ignored_any.rs b/serde/src/de/ignored_any.rs new file mode 100644 index 00000000..a4f3abe2 --- /dev/null +++ b/serde/src/de/ignored_any.rs @@ -0,0 +1,215 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use lib::*; + +use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error}; + +/// An efficient way of discarding data from a deserializer. +/// +/// Think of this like `serde_json::Value` in that it can be deserialized from +/// any type, except that it does not store any information about the data that +/// gets deserialized. +/// +/// ```rust +/// use std::fmt; +/// use std::marker::PhantomData; +/// +/// use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, IgnoredAny}; +/// +/// /// A seed that can be used to deserialize only the `n`th element of a sequence +/// /// while efficiently discarding elements of any type before or after index `n`. +/// /// +/// /// For example to deserialize only the element at index 3: +/// /// +/// /// ```rust +/// /// NthElement::new(3).deserialize(deserializer) +/// /// ``` +/// pub struct NthElement { +/// n: usize, +/// marker: PhantomData, +/// } +/// +/// impl NthElement { +/// pub fn new(n: usize) -> Self { +/// NthElement { +/// n: n, +/// marker: PhantomData, +/// } +/// } +/// } +/// +/// impl<'de, T> Visitor<'de> for NthElement +/// where T: Deserialize<'de> +/// { +/// type Value = T; +/// +/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// write!(formatter, "a sequence in which we care about element {}", self.n) +/// } +/// +/// fn visit_seq(self, mut seq: A) -> Result +/// where A: SeqAccess<'de> +/// { +/// // Skip over the first `n` elements. +/// for i in 0..self.n { +/// // It is an error if the sequence ends before we get to element `n`. +/// if seq.next_element::()?.is_none() { +/// return Err(de::Error::invalid_length(i, &self)); +/// } +/// } +/// +/// // Deserialize the one we care about. +/// let nth = match seq.next_element()? { +/// Some(nth) => nth, +/// None => { +/// return Err(de::Error::invalid_length(self.n, &self)); +/// } +/// }; +/// +/// // Skip over any remaining elements in the sequence after `n`. +/// while let Some(IgnoredAny) = seq.next_element()? { +/// // ignore +/// } +/// +/// Ok(nth) +/// } +/// } +/// +/// impl<'de, T> DeserializeSeed<'de> for NthElement +/// where T: Deserialize<'de> +/// { +/// type Value = T; +/// +/// fn deserialize(self, deserializer: D) -> Result +/// where D: Deserializer<'de> +/// { +/// deserializer.deserialize_seq(self) +/// } +/// } +/// +/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> +/// # where D: Deserializer<'de> +/// # { +/// // Deserialize only the sequence element at index 3 from this deserializer. +/// // The element at index 3 is required to be a string. Elements before and +/// // after index 3 are allowed to be of any type. +/// let s: String = NthElement::new(3).deserialize(deserializer)?; +/// # Ok(()) +/// # } +/// ``` +#[derive(Copy, Clone, Debug, Default)] +pub struct IgnoredAny; + +impl<'de> Visitor<'de> for IgnoredAny { + type Value = IgnoredAny; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("anything at all") + } + + #[inline] + fn visit_bool(self, x: bool) -> Result { + let _ = x; + Ok(IgnoredAny) + } + + #[inline] + fn visit_i64(self, x: i64) -> Result { + let _ = x; + Ok(IgnoredAny) + } + + #[inline] + fn visit_u64(self, x: u64) -> Result { + let _ = x; + Ok(IgnoredAny) + } + + #[inline] + fn visit_f64(self, x: f64) -> Result { + let _ = x; + Ok(IgnoredAny) + } + + #[inline] + fn visit_str(self, s: &str) -> Result + where + E: Error, + { + let _ = s; + Ok(IgnoredAny) + } + + #[inline] + fn visit_none(self) -> Result { + Ok(IgnoredAny) + } + + #[inline] + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + IgnoredAny::deserialize(deserializer) + } + + #[inline] + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + IgnoredAny::deserialize(deserializer) + } + + #[inline] + fn visit_unit(self) -> Result { + Ok(IgnoredAny) + } + + #[inline] + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + while let Some(IgnoredAny) = try!(seq.next_element()) { + // Gobble + } + Ok(IgnoredAny) + } + + #[inline] + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, + { + while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) { + // Gobble + } + Ok(IgnoredAny) + } + + #[inline] + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: Error, + { + let _ = bytes; + Ok(IgnoredAny) + } +} + +impl<'de> Deserialize<'de> for IgnoredAny { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_ignored_any(IgnoredAny) + } +} diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index c67a1572..b1aedff4 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1,79 +1,29 @@ -//! This module contains `Deserialize` and `Visitor` implementations. +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. -#[cfg(feature = "std")] -use std::borrow::Cow; -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::borrow::Cow; +use lib::*; -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, Vec, String}; - -#[cfg(feature = "std")] -use std::collections::{HashMap, HashSet, BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; - -#[cfg(feature = "collections")] -use collections::borrow::ToOwned; +use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, + Visitor}; #[cfg(any(feature = "std", feature = "collections"))] -use core::cmp; -use core::fmt; -#[cfg(feature = "std")] -use core::hash::{Hash, BuildHasher}; -use core::marker::PhantomData; -#[cfg(feature = "std")] -use std::net; -#[cfg(feature = "std")] -use std::path; -use core::str; -#[cfg(feature = "std")] -use std::ffi::{CString, OsString}; -#[cfg(all(feature = "std", feature="unstable"))] -use std::ffi::CStr; +use de::MapAccess; -#[cfg(feature = "std")] -use std::rc::Rc; -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::rc::Rc; - -#[cfg(feature = "std")] -use std::sync::Arc; -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::arc::Arc; - -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::boxed::Box; - -use core::cell::{Cell, RefCell}; - -#[cfg(feature = "std")] -use std::sync::{Mutex, RwLock}; - -#[cfg(feature = "std")] -use std::time::Duration; - -#[cfg(feature = "std")] -use std; - -#[cfg(feature = "unstable")] -use core::nonzero::{NonZero, Zeroable}; - -#[cfg(feature = "unstable")] -#[allow(deprecated)] // required for impl Deserialize for NonZero -use core::num::Zero; - -use de::{Deserialize, Deserializer, EnumVisitor, Error, MapVisitor, SeqVisitor, Unexpected, - VariantVisitor, Visitor}; use de::from_primitive::FromPrimitive; -#[cfg(feature = "std")] -use bytes::ByteBuf; +#[cfg(any(feature = "std", feature = "collections"))] +use private::de::size_hint; -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A visitor that produces a `()`. -pub struct UnitVisitor; +struct UnitVisitor; -impl Visitor for UnitVisitor { +impl<'de> Visitor<'de> for UnitVisitor { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -81,32 +31,27 @@ impl Visitor for UnitVisitor { } fn visit_unit(self) -> Result<(), E> - where E: Error - { - Ok(()) - } - - fn visit_seq(self, _: V) -> Result<(), V::Error> - where V: SeqVisitor + where + E: Error, { Ok(()) } } -impl Deserialize for () { +impl<'de> Deserialize<'de> for () { fn deserialize(deserializer: D) -> Result<(), D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { deserializer.deserialize_unit(UnitVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A visitor that produces a `bool`. -pub struct BoolVisitor; +struct BoolVisitor; -impl Visitor for BoolVisitor { +impl<'de> Visitor<'de> for BoolVisitor { type Value = bool; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -114,37 +59,30 @@ impl Visitor for BoolVisitor { } fn visit_bool(self, v: bool) -> Result - where E: Error + where + E: Error, { Ok(v) } - - fn visit_str(self, s: &str) -> Result - where E: Error - { - match s.trim_matches(::utils::Pattern_White_Space) { - "true" => Ok(true), - "false" => Ok(false), - _ => Err(Error::invalid_type(Unexpected::Str(s), &self)), - } - } } -impl Deserialize for bool { +impl<'de> Deserialize<'de> for bool { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { deserializer.deserialize_bool(BoolVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -macro_rules! impl_deserialize_num_method { - ($ty:ident, $src_ty:ident, $method:ident, $from_method:ident, $group:ident, $group_ty:ident) => { +macro_rules! visit_integer_method { + ($src_ty:ident, $method:ident, $from_method:ident, $group:ident, $group_ty:ident) => { #[inline] - fn $method(self, v: $src_ty) -> Result<$ty, E> - where E: Error, + fn $method(self, v: $src_ty) -> Result + where + E: Error, { match FromPrimitive::$from_method(v) { Some(v) => Ok(v), @@ -154,67 +92,83 @@ macro_rules! impl_deserialize_num_method { } } +macro_rules! visit_float_method { + ($src_ty:ident, $method:ident) => { + #[inline] + fn $method(self, v: $src_ty) -> Result + where + E: Error, + { + Ok(v as Self::Value) + } + } +} + macro_rules! impl_deserialize_num { - ($ty:ident, $method:ident) => { - impl Deserialize for $ty { + ($ty:ident, $method:ident, $($visit:ident),*) => { + impl<'de> Deserialize<'de> for $ty { #[inline] fn deserialize(deserializer: D) -> Result<$ty, D::Error> - where D: Deserializer, + where + D: Deserializer<'de>, { struct PrimitiveVisitor; - impl Visitor for PrimitiveVisitor { + impl<'de> Visitor<'de> for PrimitiveVisitor { type Value = $ty; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(stringify!($ty)) } - 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, 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)) - }) - } + $( + impl_deserialize_num!($visit $ty); + )* } deserializer.$method(PrimitiveVisitor) } } - } + }; + + (integer $ty:ident) => { + visit_integer_method!(i8, visit_i8, from_i8, Signed, i64); + visit_integer_method!(i16, visit_i16, from_i16, Signed, i64); + visit_integer_method!(i32, visit_i32, from_i32, Signed, i64); + visit_integer_method!(i64, visit_i64, from_i64, Signed, i64); + + visit_integer_method!(u8, visit_u8, from_u8, Unsigned, u64); + visit_integer_method!(u16, visit_u16, from_u16, Unsigned, u64); + visit_integer_method!(u32, visit_u32, from_u32, Unsigned, u64); + visit_integer_method!(u64, visit_u64, from_u64, Unsigned, u64); + }; + + (float $ty:ident) => { + visit_float_method!(f32, visit_f32); + visit_float_method!(f64, visit_f64); + }; } -impl_deserialize_num!(isize, deserialize_i64); -impl_deserialize_num!(i8, deserialize_i8); -impl_deserialize_num!(i16, deserialize_i16); -impl_deserialize_num!(i32, deserialize_i32); -impl_deserialize_num!(i64, deserialize_i64); -impl_deserialize_num!(usize, deserialize_u64); -impl_deserialize_num!(u8, deserialize_u8); -impl_deserialize_num!(u16, deserialize_u16); -impl_deserialize_num!(u32, deserialize_u32); -impl_deserialize_num!(u64, deserialize_u64); -impl_deserialize_num!(f32, deserialize_f32); -impl_deserialize_num!(f64, deserialize_f64); +impl_deserialize_num!(i8, deserialize_i8, integer); +impl_deserialize_num!(i16, deserialize_i16, integer); +impl_deserialize_num!(i32, deserialize_i32, integer); +impl_deserialize_num!(i64, deserialize_i64, integer); +impl_deserialize_num!(isize, deserialize_i64, integer); -/////////////////////////////////////////////////////////////////////////////// +impl_deserialize_num!(u8, deserialize_u8, integer); +impl_deserialize_num!(u16, deserialize_u16, integer); +impl_deserialize_num!(u32, deserialize_u32, integer); +impl_deserialize_num!(u64, deserialize_u64, integer); +impl_deserialize_num!(usize, deserialize_u64, integer); + +impl_deserialize_num!(f32, deserialize_f32, integer, float); +impl_deserialize_num!(f64, deserialize_f64, integer, float); + +//////////////////////////////////////////////////////////////////////////////// struct CharVisitor; -impl Visitor for CharVisitor { +impl<'de> Visitor<'de> for CharVisitor { type Value = char; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -223,14 +177,16 @@ impl Visitor for CharVisitor { #[inline] fn visit_char(self, v: char) -> Result - where E: Error + where + E: Error, { Ok(v) } #[inline] fn visit_str(self, v: &str) -> Result - where E: Error + where + E: Error, { let mut iter = v.chars(); match (iter.next(), iter.next()) { @@ -240,22 +196,23 @@ impl Visitor for CharVisitor { } } -impl Deserialize for char { +impl<'de> Deserialize<'de> for char { #[inline] fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { deserializer.deserialize_char(CharVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "collections"))] struct StringVisitor; #[cfg(any(feature = "std", feature = "collections"))] -impl Visitor for StringVisitor { +impl<'de> Visitor<'de> for StringVisitor { type Value = String; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -263,25 +220,22 @@ impl Visitor for StringVisitor { } fn visit_str(self, v: &str) -> Result - where E: Error + where + E: Error, { Ok(v.to_owned()) } fn visit_string(self, v: String) -> Result - where E: Error + where + E: Error, { Ok(v) } - fn visit_unit(self) -> Result - where E: Error - { - Ok(String::new()) - } - fn visit_bytes(self, v: &[u8]) -> Result - where E: Error + where + E: Error, { match str::from_utf8(v) { Ok(s) => Ok(s.to_owned()), @@ -290,53 +244,182 @@ impl Visitor for StringVisitor { } fn visit_byte_buf(self, v: Vec) -> Result - where E: Error + where + E: Error, { match String::from_utf8(v) { Ok(s) => Ok(s), - Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)), + Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),), } } } #[cfg(any(feature = "std", feature = "collections"))] -impl Deserialize for String { +impl<'de> Deserialize<'de> for String { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { deserializer.deserialize_string(StringVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -#[cfg(all(feature = "std", feature="unstable"))] -impl Deserialize for Box { - fn deserialize(deserializer: D) -> Result - where D: Deserializer +struct StrVisitor; + +impl<'a> Visitor<'a> for StrVisitor { + type Value = &'a str; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed string") + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, { - let s = try!(CString::deserialize(deserializer)); - Ok(s.into_boxed_c_str()) + Ok(v) // so easy + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + str::from_utf8(v).map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a str { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(StrVisitor) + } +} + +//////////////////////////////////////////////////////////////////////////////// + +struct BytesVisitor; + +impl<'a> Visitor<'a> for BytesVisitor { + type Value = &'a [u8]; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed byte array") + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + Ok(v) + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, + { + Ok(v.as_bytes()) + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_bytes(BytesVisitor) + } +} + +//////////////////////////////////////////////////////////////////////////////// + +#[cfg(feature = "std")] +struct CStringVisitor; + +#[cfg(feature = "std")] +impl<'de> Visitor<'de> for CStringVisitor { + type Value = CString; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("byte array") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let len = size_hint::cautious(seq.size_hint()); + let mut values = Vec::with_capacity(len); + + while let Some(value) = try!(seq.next_element()) { + values.push(value); + } + + CString::new(values).map_err(Error::custom) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + CString::new(v).map_err(Error::custom) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error, + { + CString::new(v).map_err(Error::custom) + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + CString::new(v).map_err(Error::custom) + } + + fn visit_string(self, v: String) -> Result + where + E: Error, + { + CString::new(v).map_err(Error::custom) } } #[cfg(feature = "std")] -impl Deserialize for CString { +impl<'de> Deserialize<'de> for CString { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { - let bytes = try!(ByteBuf::deserialize(deserializer)); - CString::new(bytes).map_err(Error::custom) + deserializer.deserialize_byte_buf(CStringVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +#[cfg(all(feature = "std", feature = "unstable"))] +impl<'de> Deserialize<'de> for Box { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + CString::deserialize(deserializer).map(CString::into_boxed_c_str) + } +} + +//////////////////////////////////////////////////////////////////////////////// struct OptionVisitor { marker: PhantomData, } -impl Visitor for OptionVisitor { +impl<'de, T> Visitor<'de> for OptionVisitor +where + T: Deserialize<'de>, +{ type Value = Option; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -345,44 +428,48 @@ impl Visitor for OptionVisitor { #[inline] fn visit_unit(self) -> Result, E> - where E: Error + where + E: Error, { Ok(None) } #[inline] fn visit_none(self) -> Result, E> - where E: Error + where + E: Error, { Ok(None) } #[inline] fn visit_some(self, deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - Ok(Some(try!(Deserialize::deserialize(deserializer)))) + T::deserialize(deserializer).map(Some) } } -impl Deserialize for Option - where T: Deserialize +impl<'de, T> Deserialize<'de> for Option +where + T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { deserializer.deserialize_option(OptionVisitor { marker: PhantomData }) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A visitor that produces a `PhantomData`. -pub struct PhantomDataVisitor { +struct PhantomDataVisitor { marker: PhantomData, } -impl Visitor for PhantomDataVisitor { +impl<'de, T> Visitor<'de> for PhantomDataVisitor { type Value = PhantomData; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -391,85 +478,75 @@ impl Visitor for PhantomDataVisitor { #[inline] fn visit_unit(self) -> Result, E> - where E: Error + where + E: Error, { Ok(PhantomData) } } -impl Deserialize for PhantomData { +impl<'de, T> Deserialize<'de> for PhantomData { fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { let visitor = PhantomDataVisitor { marker: PhantomData }; deserializer.deserialize_unit_struct("PhantomData", visitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +#[cfg(any(feature = "std", feature = "collections"))] macro_rules! seq_impl { ( - $ty:ty, - $visitor_ty:ident < $($typaram:ident : $bound1:ident $(+ $bound2:ident)*),* >, - $visitor:ident, + $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, + $access:ident, $ctor:expr, $with_capacity:expr, $insert:expr ) => { - /// A visitor that produces a sequence. - pub struct $visitor_ty<$($typaram),*> { - marker: PhantomData<$ty>, - } - - impl<$($typaram),*> $visitor_ty<$($typaram),*> - where $($typaram: $bound1 $(+ $bound2)*),* + impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty + where + T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, + $($typaram: $bound1 $(+ $bound2)*,)* { - /// Construct a new sequence visitor. - pub fn new() -> Self { - $visitor_ty { - marker: PhantomData, - } - } - } - - impl<$($typaram),*> Visitor for $visitor_ty<$($typaram),*> - where $($typaram: $bound1 $(+ $bound2)*),* - { - 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, + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, { - Ok($ctor) - } - - #[inline] - fn visit_seq(self, mut $visitor: V) -> Result<$ty, V::Error> - where V: SeqVisitor, - { - let mut values = $with_capacity; - - while let Some(value) = try!($visitor.visit()) { - $insert(&mut values, value); + struct SeqVisitor { + marker: PhantomData<$ty>, } - Ok(values) - } - } + impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor + where + T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, + $($typaram: $bound1 $(+ $bound2)*,)* + { + type Value = $ty; - impl<$($typaram),*> Deserialize for $ty - where $($typaram: $bound1 $(+ $bound2)*),* - { - fn deserialize(deserializer: D) -> Result<$ty, D::Error> - where D: Deserializer, - { - deserializer.deserialize_seq($visitor_ty::new()) + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence") + } + + #[inline] + fn visit_seq(self, mut $access: A) -> Result + where + A: SeqAccess<'de>, + { + let mut values = $with_capacity; + + while let Some(value) = try!($access.next_element()) { + $insert(&mut values, value); + } + + Ok(values) + } + } + + let visitor = SeqVisitor { marker: PhantomData }; + deserializer.deserialize_seq(visitor) } } } @@ -477,18 +554,16 @@ macro_rules! seq_impl { #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( - BinaryHeap, - BinaryHeapVisitor, - visitor, + BinaryHeap, + seq, BinaryHeap::new(), - BinaryHeap::with_capacity(cmp::min(visitor.size_hint().0, 4096)), + BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::push); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( - BTreeSet, - BTreeSetVisitor, - visitor, + BTreeSet, + seq, BTreeSet::new(), BTreeSet::new(), BTreeSet::insert); @@ -496,55 +571,48 @@ seq_impl!( #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( LinkedList, - LinkedListVisitor, - visitor, + seq, LinkedList::new(), LinkedList::new(), LinkedList::push_back); #[cfg(feature = "std")] seq_impl!( - HashSet, - HashSetVisitor, - visitor, + HashSet, + seq, HashSet::with_hasher(S::default()), - HashSet::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default()), + HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::insert); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( Vec, - VecVisitor, - visitor, + seq, Vec::new(), - Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)), + Vec::with_capacity(size_hint::cautious(seq.size_hint())), Vec::push); #[cfg(any(feature = "std", feature = "collections"))] seq_impl!( VecDeque, - VecDequeVisitor, - visitor, + seq, VecDeque::new(), - VecDeque::with_capacity(cmp::min(visitor.size_hint().0, 4096)), + VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), VecDeque::push_back); -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// struct ArrayVisitor { marker: PhantomData, } impl ArrayVisitor { - pub fn new() -> Self { + fn new() -> Self { ArrayVisitor { marker: PhantomData } } } -impl Visitor for ArrayVisitor<[T; 0]> - where T: Deserialize -{ +impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> { type Value = [T; 0]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -552,34 +620,31 @@ impl Visitor for ArrayVisitor<[T; 0]> } #[inline] - fn visit_unit(self) -> Result<[T; 0], E> - where E: Error - { - Ok([]) - } - - #[inline] - fn visit_seq(self, _: V) -> Result<[T; 0], V::Error> - where V: SeqVisitor + fn visit_seq(self, _: A) -> Result<[T; 0], A::Error> + where + A: SeqAccess<'de>, { Ok([]) } } -impl Deserialize for [T; 0] - where T: Deserialize -{ +// Does not require T: Deserialize<'de>. +impl<'de, T> Deserialize<'de> for [T; 0] { fn deserialize(deserializer: D) -> Result<[T; 0], D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - deserializer.deserialize_seq_fixed_size(0, ArrayVisitor::<[T; 0]>::new()) + deserializer.deserialize_tuple(0, ArrayVisitor::<[T; 0]>::new()) } } macro_rules! array_impls { ($($len:expr => ($($n:tt $name:ident)+))+) => { $( - impl Visitor for ArrayVisitor<[T; $len]> where T: Deserialize { + impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> + where + T: Deserialize<'de>, + { type Value = [T; $len]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -587,11 +652,12 @@ macro_rules! array_impls { } #[inline] - fn visit_seq(self, mut visitor: V) -> Result<[T; $len], V::Error> - where V: SeqVisitor, + fn visit_seq(self, mut seq: A) -> Result<[T; $len], A::Error> + where + A: SeqAccess<'de>, { $( - let $name = match try!(visitor.visit()) { + let $name = match try!(seq.next_element()) { Some(val) => val, None => return Err(Error::invalid_length($n, &self)), }; @@ -601,13 +667,15 @@ macro_rules! array_impls { } } - impl Deserialize for [T; $len] - where T: Deserialize, + impl<'de, T> Deserialize<'de> for [T; $len] + where + T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result<[T; $len], D::Error> - where D: Deserializer, + where + D: Deserializer<'de>, { - deserializer.deserialize_seq_fixed_size($len, ArrayVisitor::<[T; $len]>::new()) + deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new()) } } )+ @@ -649,24 +717,22 @@ array_impls! { 32 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae 31 af) } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// macro_rules! tuple_impls { - ($($len:expr => $visitor:ident => ($($n:tt $name:ident)+))+) => { + ($($len:tt $visitor:ident => ($($n:tt $name:ident)+))+) => { $( - /// Construct a tuple visitor. - pub struct $visitor<$($name,)+> { + struct $visitor<$($name,)+> { marker: PhantomData<($($name,)+)>, } - impl<$($name: Deserialize,)+> $visitor<$($name,)+> { - /// Construct a `TupleVisitor*`. - pub fn new() -> Self { + impl<$($name,)+> $visitor<$($name,)+> { + fn new() -> Self { $visitor { marker: PhantomData } } } - impl<$($name: Deserialize),+> Visitor for $visitor<$($name,)+> { + impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> { type Value = ($($name,)+); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -675,11 +741,12 @@ macro_rules! tuple_impls { #[inline] #[allow(non_snake_case)] - fn visit_seq(self, mut visitor: V) -> Result<($($name,)+), V::Error> - where V: SeqVisitor, + fn visit_seq(self, mut seq: A) -> Result<($($name,)+), A::Error> + where + A: SeqAccess<'de>, { $( - let $name = match try!(visitor.visit()) { + let $name = match try!(seq.next_element()) { Some(value) => value, None => return Err(Error::invalid_length($n, &self)), }; @@ -689,10 +756,11 @@ macro_rules! tuple_impls { } } - impl<$($name: Deserialize),+> Deserialize for ($($name,)+) { + impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { #[inline] fn deserialize(deserializer: D) -> Result<($($name,)+), D::Error> - where D: Deserializer, + where + D: Deserializer<'de>, { deserializer.deserialize_tuple($len, $visitor::new()) } @@ -702,87 +770,77 @@ macro_rules! tuple_impls { } tuple_impls! { - 1 => TupleVisitor1 => (0 T0) - 2 => TupleVisitor2 => (0 T0 1 T1) - 3 => TupleVisitor3 => (0 T0 1 T1 2 T2) - 4 => TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3) - 5 => TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4) - 6 => TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) - 7 => TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) - 8 => TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) - 9 => TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) - 10 => TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) - 11 => TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) - 12 => TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) - 13 => TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) - 14 => TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) - 15 => TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) - 16 => TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) + 1 TupleVisitor1 => (0 T0) + 2 TupleVisitor2 => (0 T0 1 T1) + 3 TupleVisitor3 => (0 T0 1 T1 2 T2) + 4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3) + 5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4) + 6 TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) + 7 TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) + 8 TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) + 9 TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) + 10 TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) + 11 TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) + 12 TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) + 13 TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) + 14 TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) + 15 TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) + 16 TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +#[cfg(any(feature = "std", feature = "collections"))] macro_rules! map_impl { ( - $ty:ty, - $visitor_ty:ident < $($typaram:ident : $bound1:ident $(+ $bound2:ident)*),* >, - $visitor:ident, + $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, + $access:ident, $ctor:expr, $with_capacity:expr ) => { - /// A visitor that produces a map. - pub struct $visitor_ty<$($typaram),*> { - marker: PhantomData<$ty>, - } - - impl<$($typaram),*> $visitor_ty<$($typaram),*> - where $($typaram: $bound1 $(+ $bound2)*),* + impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty + where + K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, + V: Deserialize<'de>, + $($typaram: $bound1 $(+ $bound2)*),* { - /// Construct a `MapVisitor*`. - pub fn new() -> Self { - $visitor_ty { - marker: PhantomData, - } - } - } - - impl<$($typaram),*> Visitor for $visitor_ty<$($typaram),*> - where $($typaram: $bound1 $(+ $bound2)*),* - { - 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, + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, { - Ok($ctor) - } - - #[inline] - fn visit_map(self, mut $visitor: Visitor) -> Result<$ty, Visitor::Error> - where Visitor: MapVisitor, - { - let mut values = $with_capacity; - - while let Some((key, value)) = try!($visitor.visit()) { - values.insert(key, value); + struct MapVisitor { + marker: PhantomData<$ty>, } - Ok(values) - } - } + impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor + where + K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, + V: Deserialize<'de>, + $($typaram: $bound1 $(+ $bound2)*),* + { + type Value = $ty; - impl<$($typaram),*> Deserialize for $ty - where $($typaram: $bound1 $(+ $bound2)*),* - { - fn deserialize(deserializer: D) -> Result<$ty, D::Error> - where D: Deserializer, - { - deserializer.deserialize_map($visitor_ty::new()) + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_map(self, mut $access: A) -> Result + where + A: MapAccess<'de>, + { + let mut values = $with_capacity; + + while let Some((key, value)) = try!($access.next_entry()) { + values.insert(key, value); + } + + Ok(values) + } + } + + let visitor = MapVisitor { marker: PhantomData }; + deserializer.deserialize_map(visitor) } } } @@ -790,143 +848,97 @@ macro_rules! map_impl { #[cfg(any(feature = "std", feature = "collections"))] map_impl!( - BTreeMap, - BTreeMapVisitor, - visitor, + BTreeMap, + map, BTreeMap::new(), BTreeMap::new()); #[cfg(feature = "std")] map_impl!( - HashMap, - HashMapVisitor, - visitor, + HashMap, + map, HashMap::with_hasher(S::default()), - HashMap::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default())); + HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default())); -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] -impl Deserialize for net::IpAddr { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - let s = try!(String::deserialize(deserializer)); - match s.parse() { - Ok(s) => Ok(s), - Err(err) => Err(D::Error::custom(err)), +macro_rules! parse_impl { + ($ty:ty) => { + impl<'de> Deserialize<'de> for $ty { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = try!(String::deserialize(deserializer)); + s.parse().map_err(Error::custom) + } } } } #[cfg(feature = "std")] -impl Deserialize for net::Ipv4Addr { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - let s = try!(String::deserialize(deserializer)); - match s.parse() { - Ok(s) => Ok(s), - Err(err) => Err(D::Error::custom(err)), - } - } -} +parse_impl!(net::IpAddr); #[cfg(feature = "std")] -impl Deserialize for net::Ipv6Addr { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - let s = try!(String::deserialize(deserializer)); - match s.parse() { - Ok(s) => Ok(s), - Err(err) => Err(D::Error::custom(err)), - } - } -} - -/////////////////////////////////////////////////////////////////////////////// +parse_impl!(net::Ipv4Addr); #[cfg(feature = "std")] -impl Deserialize for net::SocketAddr { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - let s = try!(String::deserialize(deserializer)); - match s.parse() { - Ok(s) => Ok(s), - Err(err) => Err(D::Error::custom(err)), - } - } -} +parse_impl!(net::Ipv6Addr); #[cfg(feature = "std")] -impl Deserialize for net::SocketAddrV4 { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - let s = try!(String::deserialize(deserializer)); - match s.parse() { - Ok(s) => Ok(s), - Err(err) => Err(D::Error::custom(err)), - } - } -} +parse_impl!(net::SocketAddr); #[cfg(feature = "std")] -impl Deserialize for net::SocketAddrV6 { - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - let s = try!(String::deserialize(deserializer)); - match s.parse() { - Ok(s) => Ok(s), - Err(err) => Err(D::Error::custom(err)), - } - } -} +parse_impl!(net::SocketAddrV4); -/////////////////////////////////////////////////////////////////////////////// +#[cfg(feature = "std")] +parse_impl!(net::SocketAddrV6); + +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] struct PathBufVisitor; #[cfg(feature = "std")] -impl Visitor for PathBufVisitor { - type Value = path::PathBuf; +impl<'de> Visitor<'de> for PathBufVisitor { + type Value = 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 + fn visit_str(self, v: &str) -> Result + where + E: Error, { Ok(From::from(v)) } - fn visit_string(self, v: String) -> Result - where E: Error + fn visit_string(self, v: String) -> Result + where + E: Error, { Ok(From::from(v)) } } - #[cfg(feature = "std")] -impl Deserialize for path::PathBuf { - fn deserialize(deserializer: D) -> Result - where D: Deserializer +impl<'de> Deserialize<'de> for PathBuf { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, { deserializer.deserialize_string(PathBufVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// If this were outside of the serde crate, it would just use: +// +// #[derive(Deserialize)] +// #[serde(variant_identifier)] #[cfg(all(feature = "std", any(unix, windows)))] enum OsStringKind { Unix, @@ -937,13 +949,14 @@ enum OsStringKind { static OSSTR_VARIANTS: &'static [&'static str] = &["Unix", "Windows"]; #[cfg(all(feature = "std", any(unix, windows)))] -impl Deserialize for OsStringKind { +impl<'de> Deserialize<'de> for OsStringKind { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { struct KindVisitor; - impl Visitor for KindVisitor { + impl<'de> Visitor<'de> for KindVisitor { type Value = OsStringKind; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -951,17 +964,19 @@ impl Deserialize for OsStringKind { } fn visit_u32(self, value: u32) -> Result - where E: Error, + where + E: Error, { match value { 0 => Ok(OsStringKind::Unix), 1 => Ok(OsStringKind::Windows), - _ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)) + _ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),), } } fn visit_str(self, value: &str) -> Result - where E: Error, + where + E: Error, { match value { "Unix" => Ok(OsStringKind::Unix), @@ -971,7 +986,8 @@ impl Deserialize for OsStringKind { } fn visit_bytes(self, value: &[u8]) -> Result - where E: Error, + where + E: Error, { match value { b"Unix" => Ok(OsStringKind::Unix), @@ -979,16 +995,14 @@ impl Deserialize for OsStringKind { _ => { match str::from_utf8(value) { Ok(value) => Err(Error::unknown_variant(value, OSSTR_VARIANTS)), - Err(_) => { - Err(Error::invalid_value(Unexpected::Bytes(value), &self)) - } + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)), } } } } } - deserializer.deserialize(KindVisitor) + deserializer.deserialize_identifier(KindVisitor) } } @@ -996,7 +1010,7 @@ impl Deserialize for OsStringKind { struct OsStringVisitor; #[cfg(all(feature = "std", any(unix, windows)))] -impl Visitor for OsStringVisitor { +impl<'de> Visitor<'de> for OsStringVisitor { type Value = OsString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -1004,152 +1018,176 @@ impl Visitor for OsStringVisitor { } #[cfg(unix)] - fn visit_enum(self, visitor: V) -> Result - where V: EnumVisitor, + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, { use std::os::unix::ffi::OsStringExt; - match try!(visitor.visit_variant()) { - (OsStringKind::Unix, variant) => { - variant.visit_newtype().map(OsString::from_vec) - } - (OsStringKind::Windows, _) => { - Err(Error::custom("cannot deserialize Windows OS string on Unix")) - } + match try!(data.variant()) { + (OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec), + (OsStringKind::Windows, _) => Err(Error::custom("cannot deserialize Windows OS string on Unix",),), } } #[cfg(windows)] - fn visit_enum(self, visitor: V) -> Result - where V: EnumVisitor, + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, { use std::os::windows::ffi::OsStringExt; - match try!(visitor.visit_variant()) { - (OsStringKind::Windows, variant) => { - variant.visit_newtype::>().map(|vec| OsString::from_wide(&vec)) - } - (OsStringKind::Unix, _) => { - Err(Error::custom("cannot deserialize Unix OS string on Windows")) + match try!(data.variant()) { + (OsStringKind::Windows, v) => { + v.newtype_variant::>().map(|vec| OsString::from_wide(&vec)) } + (OsStringKind::Unix, _) => Err(Error::custom("cannot deserialize Unix OS string on Windows",),), } } } #[cfg(all(feature = "std", any(unix, windows)))] -impl Deserialize for OsString { +impl<'de> Deserialize<'de> for OsString { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { deserializer.deserialize_enum("OsString", OSSTR_VARIANTS, OsStringVisitor) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] -impl Deserialize for Box { +impl<'de, T> Deserialize<'de> for Box +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(Box::new(val)) + T::deserialize(deserializer).map(Box::new) } } #[cfg(any(feature = "std", feature = "collections"))] -impl Deserialize for Box<[T]> { +impl<'de, T> Deserialize<'de> for Box<[T]> +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let v: Vec = try!(Deserialize::deserialize(deserializer)); - Ok(v.into_boxed_slice()) + Vec::::deserialize(deserializer).map(Vec::into_boxed_slice) } } #[cfg(any(feature = "std", feature = "collections"))] -impl Deserialize for Box { +impl<'de> Deserialize<'de> for Box { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { - let s = try!(String::deserialize(deserializer)); - Ok(s.into_boxed_str()) + String::deserialize(deserializer).map(String::into_boxed_str) } } -#[cfg(any(feature = "std", feature = "alloc"))] -impl Deserialize for Arc { +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +impl<'de, T> Deserialize<'de> for Arc +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(Arc::new(val)) + T::deserialize(deserializer).map(Arc::new) } } -#[cfg(any(feature = "std", feature = "alloc"))] -impl Deserialize for Rc { +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +impl<'de, T> Deserialize<'de> for Rc +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(Rc::new(val)) + T::deserialize(deserializer).map(Rc::new) } } #[cfg(any(feature = "std", feature = "collections"))] -impl<'a, T: ?Sized> Deserialize for Cow<'a, T> - where T: ToOwned, - T::Owned: Deserialize +impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> +where + T: ToOwned, + T::Owned: Deserialize<'de>, { #[inline] fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(Cow::Owned(val)) + T::Owned::deserialize(deserializer).map(Cow::Owned) } } -impl Deserialize for Cell { +//////////////////////////////////////////////////////////////////////////////// + +impl<'de, T> Deserialize<'de> for Cell +where + T: Deserialize<'de> + Copy, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(Cell::new(val)) + T::deserialize(deserializer).map(Cell::new) } } -impl Deserialize for RefCell { +impl<'de, T> Deserialize<'de> for RefCell +where + T: Deserialize<'de> +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(RefCell::new(val)) + T::deserialize(deserializer).map(RefCell::new) } } #[cfg(feature = "std")] -impl Deserialize for Mutex { +impl<'de, T> Deserialize<'de> for Mutex +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(Mutex::new(val)) + T::deserialize(deserializer).map(Mutex::new) } } #[cfg(feature = "std")] -impl Deserialize for RwLock { +impl<'de, T> Deserialize<'de> for RwLock +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { - let val = try!(Deserialize::deserialize(deserializer)); - Ok(RwLock::new(val)) + T::deserialize(deserializer).map(RwLock::new) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // This is a cleaned-up version of the impl generated by: // @@ -1160,22 +1198,28 @@ impl Deserialize for RwLock { // nanos: u32, // } #[cfg(feature = "std")] -impl Deserialize for Duration { +impl<'de> Deserialize<'de> for Duration { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { + // If this were outside of the serde crate, it would just use: + // + // #[derive(Deserialize)] + // #[serde(field_identifier, rename_all = "lowercase")] enum Field { Secs, Nanos, }; - impl Deserialize for Field { + impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { struct FieldVisitor; - impl Visitor for FieldVisitor { + impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -1183,7 +1227,8 @@ impl Deserialize for Duration { } fn visit_str(self, value: &str) -> Result - where E: Error + where + E: Error, { match value { "secs" => Ok(Field::Secs), @@ -1193,7 +1238,8 @@ impl Deserialize for Duration { } fn visit_bytes(self, value: &[u8]) -> Result - where E: Error + where + E: Error, { match value { b"secs" => Ok(Field::Secs), @@ -1206,29 +1252,30 @@ impl Deserialize for Duration { } } - deserializer.deserialize_struct_field(FieldVisitor) + deserializer.deserialize_identifier(FieldVisitor) } } struct DurationVisitor; - impl Visitor for DurationVisitor { + impl<'de> Visitor<'de> 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 + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, { - let secs: u64 = match try!(visitor.visit()) { + let secs: u64 = match try!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - let nanos: u32 = match try!(visitor.visit()) { + let nanos: u32 = match try!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); @@ -1237,34 +1284,35 @@ impl Deserialize for Duration { Ok(Duration::new(secs, nanos)) } - fn visit_map(self, mut visitor: V) -> Result - where V: MapVisitor + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, { let mut secs: Option = None; let mut nanos: Option = None; - while let Some(key) = try!(visitor.visit_key::()) { + while let Some(key) = try!(map.next_key()) { match key { Field::Secs => { if secs.is_some() { - return Err(::duplicate_field("secs")); + return Err(::duplicate_field("secs")); } - secs = Some(try!(visitor.visit_value())); + secs = Some(try!(map.next_value())); } Field::Nanos => { if nanos.is_some() { - return Err(::duplicate_field("nanos")); + return Err(::duplicate_field("nanos")); } - nanos = Some(try!(visitor.visit_value())); + nanos = Some(try!(map.next_value())); } } } let secs = match secs { Some(secs) => secs, - None => return Err(::missing_field("secs")), + None => return Err(::missing_field("secs")), }; let nanos = match nanos { Some(nanos) => nanos, - None => return Err(::missing_field("nanos")), + None => return Err(::missing_field("nanos")), }; Ok(Duration::new(secs, nanos)) } @@ -1275,7 +1323,7 @@ impl Deserialize for Duration { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // Similar to: // @@ -1286,22 +1334,31 @@ impl Deserialize for Duration { // end: u32, // } #[cfg(feature = "std")] -impl Deserialize for std::ops::Range { +impl<'de, Idx> Deserialize<'de> for ops::Range +where + Idx: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { + // If this were outside of the serde crate, it would just use: + // + // #[derive(Deserialize)] + // #[serde(field_identifier, rename_all = "lowercase")] enum Field { Start, End, }; - impl Deserialize for Field { + impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { struct FieldVisitor; - impl Visitor for FieldVisitor { + impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -1309,7 +1366,8 @@ impl Deserialize for std::ops::Range { } fn visit_str(self, value: &str) -> Result - where E: Error + where + E: Error, { match value { "start" => Ok(Field::Start), @@ -1319,7 +1377,8 @@ impl Deserialize for std::ops::Range { } fn visit_bytes(self, value: &[u8]) -> Result - where E: Error + where + E: Error, { match value { b"start" => Ok(Field::Start), @@ -1332,7 +1391,7 @@ impl Deserialize for std::ops::Range { } } - deserializer.deserialize_struct_field(FieldVisitor) + deserializer.deserialize_identifier(FieldVisitor) } } @@ -1340,23 +1399,27 @@ impl Deserialize for std::ops::Range { phantom: PhantomData, } - impl Visitor for RangeVisitor { - type Value = std::ops::Range; + impl<'de, Idx> Visitor<'de> for RangeVisitor + where + Idx: Deserialize<'de>, + { + type Value = ops::Range; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct Range") } - fn visit_seq(self, mut visitor: V) -> Result, V::Error> - where V: SeqVisitor + fn visit_seq(self, mut seq: A) -> Result, A::Error> + where + A: SeqAccess<'de>, { - let start: Idx = match try!(visitor.visit()) { + let start: Idx = match try!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - let end: Idx = match try!(visitor.visit()) { + let end: Idx = match try!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); @@ -1365,34 +1428,35 @@ impl Deserialize for std::ops::Range { Ok(start..end) } - fn visit_map(self, mut visitor: V) -> Result, V::Error> - where V: MapVisitor + fn visit_map(self, mut map: A) -> Result, A::Error> + where + A: MapAccess<'de>, { let mut start: Option = None; let mut end: Option = None; - while let Some(key) = try!(visitor.visit_key::()) { + while let Some(key) = try!(map.next_key()) { match key { Field::Start => { if start.is_some() { - return Err(::duplicate_field("start")); + return Err(::duplicate_field("start")); } - start = Some(try!(visitor.visit_value())); + start = Some(try!(map.next_value())); } Field::End => { if end.is_some() { - return Err(::duplicate_field("end")); + return Err(::duplicate_field("end")); } - end = Some(try!(visitor.visit_value())); + end = Some(try!(map.next_value())); } } } let start = match start { Some(start) => start, - None => return Err(::missing_field("start")), + None => return Err(::missing_field("start")), }; let end = match end { Some(end) => end, - None => return Err(::missing_field("end")), + None => return Err(::missing_field("end")), }; Ok(start..end) } @@ -1403,50 +1467,57 @@ impl Deserialize for std::ops::Range { } } -/////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "unstable")] #[allow(deprecated)] // num::Zero is deprecated but there is no replacement -impl Deserialize for NonZero - where T: Deserialize + PartialEq + Zeroable + Zero +impl<'de, T> Deserialize<'de> for NonZero +where + T: Deserialize<'de> + PartialEq + Zeroable + Zero, { fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { let value = try!(Deserialize::deserialize(deserializer)); if value == Zero::zero() { return Err(Error::custom("expected a non-zero value")); } + // Waiting for a safe way to construct NonZero: + // https://github.com/rust-lang/rust/issues/27730#issuecomment-269726075 unsafe { Ok(NonZero::new(value)) } } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// - -impl Deserialize for Result - where T: Deserialize, - E: Deserialize +impl<'de, T, E> Deserialize<'de> for Result +where + T: Deserialize<'de>, + E: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result, D::Error> - where D: Deserializer + where + D: Deserializer<'de>, { + // If this were outside of the serde crate, it would just use: + // + // #[derive(Deserialize)] + // #[serde(variant_identifier)] enum Field { Ok, Err, } - impl Deserialize for Field { + impl<'de> Deserialize<'de> for Field { #[inline] fn deserialize(deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { struct FieldVisitor; - impl Visitor for FieldVisitor { + impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -1454,19 +1525,21 @@ impl Deserialize for Result } fn visit_u32(self, value: u32) -> Result - where E: Error + where + E: Error, { match value { 0 => Ok(Field::Ok), 1 => Ok(Field::Err), _ => { - Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)) + Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),) } } } fn visit_str(self, value: &str) -> Result - where E: Error + where + E: Error, { match value { "Ok" => Ok(Field::Ok), @@ -1476,7 +1549,8 @@ impl Deserialize for Result } fn visit_bytes(self, value: &[u8]) -> Result - where E: Error + where + E: Error, { match value { b"Ok" => Ok(Field::Ok), @@ -1493,15 +1567,16 @@ impl Deserialize for Result } } - deserializer.deserialize(FieldVisitor) + deserializer.deserialize_identifier(FieldVisitor) } } struct ResultVisitor(PhantomData>); - impl Visitor for ResultVisitor - where T: Deserialize, - E: Deserialize + impl<'de, T, E> Visitor<'de> for ResultVisitor + where + T: Deserialize<'de>, + E: Deserialize<'de>, { type Value = Result; @@ -1509,12 +1584,13 @@ impl Deserialize for Result formatter.write_str("enum Result") } - fn visit_enum(self, visitor: V) -> Result, V::Error> - where V: EnumVisitor + fn visit_enum(self, data: A) -> Result, A::Error> + where + A: EnumAccess<'de>, { - match try!(visitor.visit_variant()) { - (Field::Ok, variant) => variant.visit_newtype().map(Ok), - (Field::Err, variant) => variant.visit_newtype().map(Err), + match try!(data.variant()) { + (Field::Ok, v) => v.newtype_variant().map(Ok), + (Field::Err, v) => v.newtype_variant().map(Err), } } } @@ -1524,107 +1600,3 @@ impl Deserialize for Result deserializer.deserialize_enum("Result", VARIANTS, ResultVisitor(PhantomData)) } } - -/////////////////////////////////////////////////////////////////////////////// - -/// A target for deserializers that want to ignore data. Implements -/// Deserialize and silently eats data given to it. -pub struct IgnoredAny; - -impl Deserialize for IgnoredAny { - #[inline] - fn deserialize(deserializer: D) -> Result - where D: Deserializer - { - struct IgnoredAnyVisitor; - - 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) - } - - #[inline] - fn visit_i64(self, _: i64) -> Result { - Ok(IgnoredAny) - } - - #[inline] - fn visit_u64(self, _: u64) -> Result { - Ok(IgnoredAny) - } - - #[inline] - fn visit_f64(self, _: f64) -> Result { - Ok(IgnoredAny) - } - - #[inline] - fn visit_str(self, _: &str) -> Result - where E: Error - { - Ok(IgnoredAny) - } - - #[inline] - fn visit_none(self) -> Result { - Ok(IgnoredAny) - } - - #[inline] - fn visit_some(self, _: D) -> Result - where D: Deserializer - { - Ok(IgnoredAny) - } - - #[inline] - fn visit_newtype_struct(self, _: D) -> Result - where D: Deserializer - { - Ok(IgnoredAny) - } - - #[inline] - fn visit_unit(self) -> Result { - Ok(IgnoredAny) - } - - #[inline] - fn visit_seq(self, mut visitor: V) -> Result - where V: SeqVisitor - { - while let Some(_) = try!(visitor.visit::()) { - // Gobble - } - Ok(IgnoredAny) - } - - #[inline] - fn visit_map(self, mut visitor: V) -> Result - where V: MapVisitor - { - while let Some((_, _)) = try!(visitor.visit::()) { - // Gobble - } - Ok(IgnoredAny) - } - - #[inline] - fn visit_bytes(self, _: &[u8]) -> Result - where E: Error - { - Ok(IgnoredAny) - } - } - - // TODO maybe not necessary with impl specialization - deserializer.deserialize_ignored_any(IgnoredAnyVisitor) - } -} diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 72c1bce4..dd5f09da 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1,7 +1,15 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! Generic data structure deserialization framework. //! -//! The two most important traits in this module are `Deserialize` and -//! `Deserializer`. +//! The two most important traits in this module are [`Deserialize`] and +//! [`Deserializer`]. //! //! - **A type that implements `Deserialize` is a data structure** that can be //! deserialized from any data format supported by Serde, and conversely @@ -10,43 +18,42 @@ //! //! # The Deserialize trait //! -//! Serde provides `Deserialize` implementations for many Rust primitive and +//! Serde provides [`Deserialize`] implementations for many Rust primitive and //! standard library types. The complete list is below. All of these can be //! deserialized using Serde out of the box. //! -//! Additionally, Serde provides a procedural macro called `serde_derive` to -//! automatically generate `Deserialize` implementations for structs and enums -//! in your program. See the [codegen section of the manual][codegen] for how to -//! use this. +//! Additionally, Serde provides a procedural macro called [`serde_derive`] to +//! automatically generate [`Deserialize`] implementations for structs and enums +//! in your program. See the [codegen section of the manual] for how to use +//! this. //! -//! In rare cases it may be necessary to implement `Deserialize` manually for -//! some type in your program. See the [Implementing -//! `Deserialize`][impl-deserialize] section of the manual for more about this. +//! In rare cases it may be necessary to implement [`Deserialize`] manually for +//! some type in your program. See the [Implementing `Deserialize`] section of +//! the manual for more about this. //! -//! Third-party crates may provide `Deserialize` implementations for types that -//! they expose. For example the `linked-hash-map` crate provides a -//! `LinkedHashMap` type that is deserializable by Serde because the crate -//! provides an implementation of `Deserialize` for it. +//! Third-party crates may provide [`Deserialize`] implementations for types +//! that they expose. For example the [`linked-hash-map`] crate provides a +//! [`LinkedHashMap`] type that is deserializable by Serde because the +//! crate provides an implementation of [`Deserialize`] for it. //! //! # The Deserializer trait //! -//! `Deserializer` implementations are provided by third-party crates, for -//! example [`serde_json`][serde_json], [`serde_yaml`][serde_yaml] and -//! [`bincode`][bincode]. +//! [`Deserializer`] implementations are provided by third-party crates, for +//! example [`serde_json`], [`serde_yaml`] and [`bincode`]. //! //! A partial list of well-maintained formats is given on the [Serde -//! website][data-formats]. +//! website][data formats]. //! //! # Implementations of Deserialize provided by Serde //! //! This is a slightly different set of types than what is supported for //! serialization. Some types can be serialized by Serde but not deserialized. -//! One example is `&str`. +//! One example is `OsStr`. //! //! - **Primitive types**: //! - bool -//! - isize, i8, i16, i32, i64 -//! - usize, u8, u16, u32, u64 +//! - i8, i16, i32, i64, isize +//! - u8, u16, u32, u64, usize //! - f32, f64 //! - char //! - **Compound types**: @@ -78,10 +85,18 @@ //! - VecDeque\ //! - Vec\ //! - EnumSet\ (unstable) +//! - **Zero-copy types**: +//! - &str +//! - &[u8] +//! - **FFI types**: +//! - CString +//! - Box\ +//! - OsString //! - **Miscellaneous standard library types**: //! - Duration //! - Path //! - PathBuf +//! - Range\ //! - NonZero\ (unstable) //! - **Net types**: //! - IpAddr @@ -91,164 +106,176 @@ //! - SocketAddrV4 //! - SocketAddrV6 //! -//! [codegen]: https://serde.rs/codegen.html -//! [impl-deserialize]: https://serde.rs/impl-deserialize.html -//! [serde_json]: https://github.com/serde-rs/json -//! [serde_yaml]: https://github.com/dtolnay/serde-yaml -//! [bincode]: https://github.com/TyOverby/bincode -//! [data-formats]: https://serde.rs/#data-formats +//! [Implementing `Deserialize`]: https://serde.rs/impl-deserialize.html +//! [`Deserialize`]: ../trait.Deserialize.html +//! [`Deserializer`]: ../trait.Deserializer.html +//! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html +//! [`bincode`]: https://github.com/TyOverby/bincode +//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map +//! [`serde_derive`]: https://crates.io/crates/serde_derive +//! [`serde_json`]: https://github.com/serde-rs/json +//! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml +//! [codegen section of the manual]: https://serde.rs/codegen.html +//! [data formats]: https://serde.rs/#data-formats -#[cfg(feature = "std")] -use std::error; -#[cfg(not(feature = "std"))] -use error; +use lib::*; -#[cfg(all(not(feature = "std"), feature = "collections"))] -use collections::{String, Vec}; +//////////////////////////////////////////////////////////////////////////////// -use core::fmt::{self, Display}; -use core::marker::PhantomData; - -/////////////////////////////////////////////////////////////////////////////// - -#[doc(hidden)] -pub mod impls; pub mod value; + mod from_primitive; +mod ignored_any; +mod impls; +mod utf8; -// Helpers used by generated code. Not public API. -#[doc(hidden)] -pub mod private; -#[cfg(any(feature = "std", feature = "collections"))] -mod content; +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 Deserialize for IpAddr { - /// fn deserialize(deserializer: D) -> Result - /// where D: Deserializer - /// { - /// 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:ident)::+)*) => { + /// 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 std::str::FromStr; + /// # + /// # struct IpAddr; + /// # + /// # impl FromStr for IpAddr { + /// # type Err = String; + /// # + /// # fn from_str(_: &str) -> Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// use serde::de::{self, Deserialize, Deserializer}; + /// + /// 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(de::Error::custom) + /// } + /// } + /// ``` + fn custom(msg: T) -> Self + where + T: Display; - /// 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 + Debug + Display); + /// `Unexpected` represents an unexpected invocation of any one of the `Visitor` /// trait methods. /// @@ -256,23 +283,27 @@ pub trait Error: Sized + error::Error { /// `invalid_length` methods of the `Error` trait to build error messages. /// /// ```rust -/// # use serde::de::{Error, Unexpected, Visitor}; /// # use std::fmt; -/// # #[allow(dead_code)] +/// # +/// # use serde::de::{self, Unexpected, Visitor}; +/// # /// # struct Example; -/// # impl Visitor for Example { -/// # type Value = (); +/// # +/// # impl<'de> Visitor<'de> for Example { +/// # type Value = (); +/// # +/// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// # write!(formatter, "definitely not a boolean") +/// # } +/// # /// fn visit_bool(self, v: bool) -> Result -/// where E: Error +/// where E: de::Error /// { -/// Err(Error::invalid_type(Unexpected::Bool(v), &self)) +/// Err(de::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)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Unexpected<'a> { /// The input contained a boolean value that was not expected. Bool(bool), @@ -376,31 +407,37 @@ impl<'a> fmt::Display for Unexpected<'a> { /// (`&self`) is an implementation of this trait. /// /// ```rust -/// # use serde::de::{Error, Unexpected, Visitor}; /// # use std::fmt; -/// # #[allow(dead_code)] +/// # +/// # use serde::de::{self, Unexpected, Visitor}; +/// # /// # struct Example; -/// # impl Visitor for Example { -/// # type Value = (); +/// # +/// # impl<'de> Visitor<'de> for Example { +/// # type Value = (); +/// # +/// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// # write!(formatter, "definitely not a boolean") +/// # } +/// # /// fn visit_bool(self, v: bool) -> Result -/// where E: Error +/// where E: de::Error /// { -/// Err(Error::invalid_type(Unexpected::Bool(v), &self)) +/// Err(de::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}; -/// # #[allow(dead_code)] -/// # fn example() -> Result<(), E> { -/// # let v = true; -/// return Err(Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); +/// # use serde::de::{self, Unexpected}; +/// # +/// # fn example() -> Result<(), E> +/// # where E: de::Error +/// # { +/// # let v = true; +/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); /// # } /// ``` pub trait Expected { @@ -409,8 +446,9 @@ pub trait Expected { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result; } -impl Expected for T - where T: Visitor +impl<'de, T> Expected for T +where + T: Visitor<'de>, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.expecting(formatter) @@ -429,7 +467,7 @@ impl<'a> Display for Expected + 'a { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// /// A **data structure** that can be deserialized from any data format supported /// by Serde. @@ -455,14 +493,44 @@ impl<'a> Display for Expected + 'a { /// [de]: https://docs.serde.rs/serde/de/index.html /// [codegen]: https://serde.rs/codegen.html /// [impl-deserialize]: https://serde.rs/impl-deserialize.html -pub trait Deserialize: Sized { +pub trait Deserialize<'de>: Sized { /// Deserialize this value from the given Serde deserializer. /// /// See the [Implementing `Deserialize`][impl-deserialize] section of the /// manual for more information about how to implement this method. /// /// [impl-deserialize]: https://serde.rs/impl-deserialize.html - fn deserialize(deserializer: D) -> Result where D: Deserializer; + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>; +} + +/// A data structure that can be deserialized without borrowing any data from +/// the deserializer. +/// +/// This is primarily useful for trait bounds on functions. For example a +/// `from_str` function may be able to deserialize a data structure that borrows +/// from the input string, but a `from_reader` function may only deserialize +/// owned data. +/// +/// ```rust +/// # use serde::de::{Deserialize, DeserializeOwned}; +/// # use std::io::{Read, Result}; +/// # +/// # trait Ignore { +/// fn from_str<'a, T>(s: &'a str) -> Result +/// where T: Deserialize<'a>; +/// +/// fn from_reader(rdr: R) -> Result +/// where R: Read, +/// T: DeserializeOwned; +/// # } +/// ``` +pub trait DeserializeOwned: for<'de> Deserialize<'de> {} +impl DeserializeOwned for T +where + T: for<'de> Deserialize<'de>, +{ } /// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you @@ -480,11 +548,13 @@ pub trait Deserialize: Sized { /// /// ```rust /// # use serde::Deserialize; -/// # #[allow(dead_code)] +/// # /// # enum Error {} -/// # #[allow(dead_code)] -/// fn func() -> Result -/// # { unimplemented!() } +/// # +/// fn func<'de, T: Deserialize<'de>>() -> Result +/// # { +/// # unimplemented!() +/// # } /// ``` /// /// Adjusting an API like this to support stateful deserialization is a matter @@ -492,10 +562,10 @@ pub trait Deserialize: Sized { /// /// ```rust /// # use serde::de::DeserializeSeed; -/// # #[allow(dead_code)] +/// # /// # enum Error {} -/// # #[allow(dead_code)] -/// fn func_seed(seed: T) -> Result +/// # +/// fn func_seed<'de, T: DeserializeSeed<'de>>(seed: T) -> Result /// # { /// # let _ = seed; /// # unimplemented!() @@ -516,10 +586,11 @@ pub trait Deserialize: Sized { /// trait. /// /// ```rust -/// # use serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, SeqVisitor}; -/// # use std::fmt; -/// # use std::marker::PhantomData; -/// # +/// use std::fmt; +/// use std::marker::PhantomData; +/// +/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess}; +/// /// // 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 @@ -527,8 +598,8 @@ pub trait Deserialize: Sized { /// // 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 +/// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T> +/// where T: Deserialize<'de> /// { /// // The return type of the `deserialize` method. This implementation /// // appends onto an existing vector but does not create any new data @@ -536,31 +607,31 @@ pub trait Deserialize: Sized { /// type Value = (); /// /// fn deserialize(self, deserializer: D) -> Result -/// where D: Deserializer +/// where D: Deserializer<'de> /// { /// // 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 +/// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T> +/// where T: Deserialize<'de> /// { /// type Value = (); /// -/// fn visit_seq(self, mut visitor: V) -> Result<(), V::Error> -/// where V: SeqVisitor +/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// write!(formatter, "an array of integers") +/// } +/// +/// fn visit_seq(self, mut seq: A) -> Result<(), A::Error> +/// where A: SeqAccess<'de> /// { /// // Visit each element in the inner array and push it onto /// // the existing vector. -/// while let Some(elem) = visitor.visit()? { +/// while let Some(elem) = seq.next_element()? { /// 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)) @@ -570,69 +641,74 @@ pub trait Deserialize: Sized { /// // Visitor implementation that will walk the outer array of the JSON input. /// struct FlattenedVecVisitor(PhantomData); /// -/// impl Visitor for FlattenedVecVisitor -/// where T: Deserialize +/// impl<'de, T> Visitor<'de> for FlattenedVecVisitor +/// where T: Deserialize<'de> /// { /// // 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 +/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +/// write!(formatter, "an array of arrays") +/// } +/// +/// fn visit_seq(self, mut seq: A) -> Result, A::Error> +/// where A: SeqAccess<'de> /// { /// // 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))? { +/// while let Some(()) = seq.next_element_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") -/// # } /// } /// -/// # #[allow(dead_code)] -/// # fn example(deserializer: D) -> Result<(), D::Error> { +/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> +/// # where D: Deserializer<'de> +/// # { /// let visitor = FlattenedVecVisitor(PhantomData); /// let flattened: Vec = deserializer.deserialize_seq(visitor)?; -/// # let _ = flattened; -/// # Ok(()) } +/// # Ok(()) +/// # } /// ``` -pub trait DeserializeSeed: Sized { +pub trait DeserializeSeed<'de>: 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; + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>; } -impl DeserializeSeed for PhantomData - where T: Deserialize +impl<'de, T> DeserializeSeed<'de> for PhantomData +where + T: Deserialize<'de>, { type Value = T; #[inline] fn deserialize(self, deserializer: D) -> Result - where D: Deserializer + where + D: Deserializer<'de>, { T::deserialize(deserializer) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// /// A **data format** that can deserialize any data structure supported by /// Serde. /// /// The role of this trait is to define the deserialization half of the Serde -/// data model, which is a way to categorize every Rust data type into one of 28 +/// data model, which is a way to categorize every Rust data type into one of 27 /// possible types. Each method of the `Serializer` trait corresponds to one of /// the types of the data model. /// @@ -642,47 +718,54 @@ impl DeserializeSeed for PhantomData /// /// The types that make up the Serde data model are: /// -/// - 12 primitive types: +/// - **12 primitive types** /// - bool /// - i8, i16, i32, i64 /// - u8, u16, u32, u64 /// - f32, f64 /// - char -/// - string -/// - byte array - [u8] -/// - option -/// - either none or some value -/// - unit -/// - unit is the type of () in Rust -/// - unit_struct -/// - for example `struct Unit` or `PhantomData` -/// - unit_variant -/// - the `E::A` and `E::B` in `enum E { A, B }` -/// - newtype_struct -/// - for example `struct Millimeters(u8)` -/// - newtype_variant -/// - the `E::N` in `enum E { N(u8) }` -/// - seq -/// - a dynamically sized sequence of values, for example `Vec` or -/// `HashSet` -/// - seq_fixed_size -/// - a statically sized sequence of values for which the size will be known -/// at deserialization time without looking at the serialized data, for -/// example `[u64; 10]` -/// - tuple -/// - for example `(u8,)` or `(String, u64, Vec)` -/// - tuple_struct -/// - for example `struct Rgb(u8, u8, u8)` -/// - tuple_variant -/// - the `E::T` in `enum E { T(u8, u8) }` -/// - map -/// - for example `BTreeMap` -/// - struct -/// - a key-value pairing in which the keys will be known at deserialization -/// time without looking at the serialized data, for example `struct S { r: -/// u8, g: u8, b: u8 }` -/// - struct_variant -/// - the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }` +/// - **string** +/// - UTF-8 bytes with a length and no null terminator. +/// - When serializing, all strings are handled equally. When deserializing, +/// there are three flavors of strings: transient, owned, and borrowed. +/// - **byte array** - [u8] +/// - Similar to strings, during deserialization byte arrays can be transient, +/// owned, or borrowed. +/// - **option** +/// - Either none or some value. +/// - **unit** +/// - The type of `()` in Rust. It represents an anonymous value containing no +/// data. +/// - **unit_struct** +/// - For example `struct Unit` or `PhantomData`. It represents a named value +/// containing no data. +/// - **unit_variant** +/// - For example the `E::A` and `E::B` in `enum E { A, B }`. +/// - **newtype_struct** +/// - For example `struct Millimeters(u8)`. +/// - **newtype_variant** +/// - For example the `E::N` in `enum E { N(u8) }`. +/// - **seq** +/// - A variably sized heterogeneous sequence of values, for example `Vec` or +/// `HashSet`. When serializing, the length may or may not be known before +/// iterating through all the data. When deserializing, the length is determined +/// by looking at the serialized data. +/// - **tuple** +/// - A statically sized heterogeneous sequence of values for which the length +/// will be known at deserialization time without looking at the serialized +/// data, for example `(u8,)` or `(String, u64, Vec)` or `[u64; 10]`. +/// - **tuple_struct** +/// - A named tuple, for example `struct Rgb(u8, u8, u8)`. +/// - **tuple_variant** +/// - For example the `E::T` in `enum E { T(u8, u8) }`. +/// - **map** +/// - A heterogeneous key-value pairing, for example `BTreeMap`. +/// - **struct** +/// - A heterogeneous key-value pairing in which the keys are strings and will be +/// known at deserialization time without looking at the serialized data, for +/// example `struct S { r: u8, g: u8, b: u8 }`. +/// - **struct_variant** +/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// /// The `Deserializer` trait supports two entry point styles which enables /// different kinds of deserialization. @@ -691,25 +774,25 @@ impl DeserializeSeed for PhantomData /// to look at the serialized data and tell what it represents. For example /// the JSON deserializer may see an opening curly brace (`{`) and know that /// it is seeing a map. If the data format supports -/// `Deserializer::deserialize`, it will drive the Visitor using whatever +/// `Deserializer::deserialize_any`, it will drive the Visitor using whatever /// type it sees in the input. JSON uses this approach when deserializing /// `serde_json::Value` which is an enum that can represent any JSON /// document. Without knowing what is in a JSON document, we can deserialize -/// it to `serde_json::Value` by going through `Deserializer::deserialize`. +/// it to `serde_json::Value` by going through `Deserializer::deserialize_any`. /// /// 2. The various `deserialize_*` methods. Non-self-describing formats like /// Bincode need to be told what is in the input in order to deserialize it. /// The `deserialize_*` methods are hints to the deserializer for how to /// interpret the next piece of input. Non-self-describing formats are not /// able to deserialize something like `serde_json::Value` which relies on -/// `Deserializer::deserialize`. +/// `Deserializer::deserialize_any`. /// /// When implementing `Deserialize`, you should avoid relying on -/// `Deserializer::deserialize` unless you need to be told by the Deserializer -/// what type is in the input. Know that relying on `Deserializer::deserialize` +/// `Deserializer::deserialize_any` unless you need to be told by the Deserializer +/// what type is in the input. Know that relying on `Deserializer::deserialize_any` /// means your data type will be able to deserialize from self-describing /// formats only, ruling out Bincode and many others. -pub trait Deserializer: Sized { +pub trait Deserializer<'de>: Sized { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; @@ -718,48 +801,74 @@ pub trait Deserializer: Sized { /// on what data type is in the input. /// /// When implementing `Deserialize`, you should avoid relying on - /// `Deserializer::deserialize` unless you need to be told by the + /// `Deserializer::deserialize_any` unless you need to be told by the /// Deserializer what type is in the input. Know that relying on - /// `Deserializer::deserialize` means your data type will be able to + /// `Deserializer::deserialize_any` means your data type will be able to /// deserialize from self-describing formats only, ruling out Bincode and /// many others. - fn deserialize(self, visitor: V) -> Result where V: Visitor; + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `bool` value. - fn deserialize_bool(self, visitor: V) -> Result where V: Visitor; - - /// Hint that the `Deserialize` type is expecting a `u8` value. - fn deserialize_u8(self, visitor: V) -> Result where V: Visitor; - - /// Hint that the `Deserialize` type is expecting a `u16` value. - fn deserialize_u16(self, visitor: V) -> Result where V: Visitor; - - /// Hint that the `Deserialize` type is expecting a `u32` value. - fn deserialize_u32(self, visitor: V) -> Result where V: Visitor; - - /// Hint that the `Deserialize` type is expecting a `u64` value. - fn deserialize_u64(self, visitor: V) -> Result where V: Visitor; + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i8` value. - fn deserialize_i8(self, visitor: V) -> Result where V: Visitor; + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i16` value. - fn deserialize_i16(self, visitor: V) -> Result where V: Visitor; + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i32` value. - fn deserialize_i32(self, visitor: V) -> Result where V: Visitor; + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i64` value. - fn deserialize_i64(self, visitor: V) -> Result where V: Visitor; + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>; + + /// Hint that the `Deserialize` type is expecting a `u8` value. + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>; + + /// Hint that the `Deserialize` type is expecting a `u16` value. + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>; + + /// Hint that the `Deserialize` type is expecting a `u32` value. + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>; + + /// Hint that the `Deserialize` type is expecting a `u64` value. + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `f32` value. - fn deserialize_f32(self, visitor: V) -> Result where V: Visitor; + fn deserialize_f32(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `f64` value. - fn deserialize_f64(self, visitor: V) -> Result where V: Visitor; + fn deserialize_f64(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `char` value. - fn deserialize_char(self, visitor: V) -> Result where V: Visitor; + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a string value and does /// not benefit from taking ownership of buffered data owned by the @@ -768,7 +877,9 @@ pub trait Deserializer: Sized { /// If the `Visitor` would benefit from taking ownership of `String` data, /// indiciate this to the `Deserializer` by using `deserialize_string` /// instead. - fn deserialize_str(self, visitor: V) -> Result where V: Visitor; + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a string value and would /// benefit from taking ownership of buffered data owned by the @@ -777,7 +888,9 @@ pub trait Deserializer: Sized { /// If the `Visitor` would not benefit from taking ownership of `String` /// data, indicate that to the `Deserializer` by using `deserialize_str` /// instead. - fn deserialize_string(self, visitor: V) -> Result where V: Visitor; + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a byte array and does not /// benefit from taking ownership of buffered data owned by the @@ -786,7 +899,9 @@ pub trait Deserializer: Sized { /// If the `Visitor` would benefit from taking ownership of `Vec` data, /// indicate this to the `Deserializer` by using `deserialize_byte_buf` /// instead. - fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor; + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a byte array and would /// benefit from taking ownership of buffered data owned by the @@ -795,108 +910,124 @@ pub trait Deserializer: Sized { /// If the `Visitor` would not benefit from taking ownership of `Vec` /// data, indicate that to the `Deserializer` by using `deserialize_bytes` /// instead. - fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor; + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an optional value. /// /// This allows deserializers that encode an optional value as a nullable /// value to convert the null value into `None` and a regular value into /// `Some(value)`. - fn deserialize_option(self, visitor: V) -> Result where V: Visitor; + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a unit value. - fn deserialize_unit(self, visitor: V) -> Result where V: Visitor; + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a unit struct with a /// particular name. - fn deserialize_unit_struct(self, - name: &'static str, - visitor: V) - -> Result - where V: Visitor; + fn deserialize_unit_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a newtype struct with a /// particular name. - fn deserialize_newtype_struct(self, - name: &'static str, - visitor: V) - -> Result - where V: Visitor; + fn deserialize_newtype_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a sequence of values. - fn deserialize_seq(self, visitor: V) -> Result where V: Visitor; + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a sequence of values and /// knows how many values there are without looking at the serialized data. - fn deserialize_seq_fixed_size(self, - len: usize, - visitor: V) - -> Result - where V: Visitor; - - /// Hint that the `Deserialize` type is expecting a tuple value with a - /// particular number of elements. fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where V: Visitor; + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a tuple struct with a /// particular name and number of fields. - fn deserialize_tuple_struct(self, - name: &'static str, - len: usize, - visitor: V) - -> Result - where V: Visitor; + fn deserialize_tuple_struct( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a map of key-value pairs. - fn deserialize_map(self, visitor: V) -> Result where V: Visitor; + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a struct with a particular /// name and fields. - fn deserialize_struct(self, - name: &'static str, - fields: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor; - - /// Hint that the `Deserialize` type is expecting the name of a struct - /// field. - fn deserialize_struct_field(self, visitor: V) -> Result - where V: Visitor; + fn deserialize_struct( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an enum value with a /// particular name and possible variants. - fn deserialize_enum(self, - name: &'static str, - variants: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor; + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; + + /// Hint that the `Deserialize` type is expecting the name of a struct + /// field or the discriminant of an enum variant. + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>; /// Hint that the `Deserialize` type needs to deserialize a value whose type /// doesn't matter because it is ignored. /// /// Deserializers for non-self-describing formats may not support this mode. fn deserialize_ignored_any(self, visitor: V) -> Result - where V: Visitor; + where + V: Visitor<'de>; } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// /// This trait represents a visitor that walks through a deserializer. /// /// ```rust -/// # use serde::de::{Error, Unexpected, Visitor}; /// # use std::fmt; +/// # +/// # use serde::de::{self, Unexpected, Visitor}; +/// # /// /// A visitor that deserializes a long string - a string containing at least /// /// some minimum number of bytes. -/// # #[allow(dead_code)] /// struct LongString { /// min: usize, /// } /// -/// impl Visitor for LongString { +/// impl<'de> Visitor<'de> for LongString { /// type Value = String; /// /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -904,17 +1035,17 @@ pub trait Deserializer: Sized { /// } /// /// fn visit_str(self, s: &str) -> Result -/// where E: Error +/// where E: de::Error /// { /// if s.len() >= self.min { /// Ok(s.to_owned()) /// } else { -/// Err(Error::invalid_value(Unexpected::Str(s), &self)) +/// Err(de::Error::invalid_value(Unexpected::Str(s), &self)) /// } /// } /// } /// ``` -pub trait Visitor: Sized { +pub trait Visitor<'de>: Sized { /// The value produced by this visitor. type Value; @@ -927,10 +1058,14 @@ pub trait Visitor: Sized { /// /// ```rust /// # use std::fmt; - /// # #[allow(dead_code)] - /// # struct S { max: usize } - /// # impl serde::de::Visitor for S { - /// # type Value = (); + /// # + /// # struct S { + /// # max: usize, + /// # } + /// # + /// # impl<'de> serde::de::Visitor<'de> for S { + /// # type Value = (); + /// # /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// write!(formatter, "an integer between 0 and {}", self.max) /// } @@ -938,92 +1073,146 @@ pub trait Visitor: Sized { /// ``` fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result; - /// Deserialize a `bool` into a `Value`. + /// The input contains a boolean. + /// + /// The default implementation fails with a type error. fn visit_bool(self, v: bool) -> Result - where E: Error + where + E: Error, { Err(Error::invalid_type(Unexpected::Bool(v), &self)) } - /// Deserialize an `i8` into a `Value`. + /// The input contains an `i8`. + /// + /// The default implementation forwards to [`visit_i64`]. + /// + /// [`visit_i64`]: #method.visit_i64 fn visit_i8(self, v: i8) -> Result - where E: Error + where + E: Error, { self.visit_i64(v as i64) } - /// Deserialize an `i16` into a `Value`. + /// The input contains an `i16`. + /// + /// The default implementation forwards to [`visit_i64`]. + /// + /// [`visit_i64`]: #method.visit_i64 fn visit_i16(self, v: i16) -> Result - where E: Error + where + E: Error, { self.visit_i64(v as i64) } - /// Deserialize an `i32` into a `Value`. + /// The input contains an `i32`. + /// + /// The default implementation forwards to [`visit_i64`]. + /// + /// [`visit_i64`]: #method.visit_i64 fn visit_i32(self, v: i32) -> Result - where E: Error + where + E: Error, { self.visit_i64(v as i64) } - /// Deserialize an `i64` into a `Value`. + /// The input contains an `i32`. + /// + /// The default implementation fails with a type error. fn visit_i64(self, v: i64) -> Result - where E: Error + where + E: Error, { Err(Error::invalid_type(Unexpected::Signed(v), &self)) } - /// Deserialize a `u8` into a `Value`. + /// The input contains a `u8`. + /// + /// The default implementation forwards to [`visit_u64`]. + /// + /// [`visit_u64`]: #method.visit_u64 fn visit_u8(self, v: u8) -> Result - where E: Error + where + E: Error, { self.visit_u64(v as u64) } - /// Deserialize a `u16` into a `Value`. + /// The input contains a `u16`. + /// + /// The default implementation forwards to [`visit_u64`]. + /// + /// [`visit_u64`]: #method.visit_u64 fn visit_u16(self, v: u16) -> Result - where E: Error + where + E: Error, { self.visit_u64(v as u64) } - /// Deserialize a `u32` into a `Value`. + /// The input contains a `u32`. + /// + /// The default implementation forwards to [`visit_u64`]. + /// + /// [`visit_u64`]: #method.visit_u64 fn visit_u32(self, v: u32) -> Result - where E: Error + where + E: Error, { self.visit_u64(v as u64) } - /// Deserialize a `u64` into a `Value`. + /// The input contains a `u64`. + /// + /// The default implementation fails with a type error. fn visit_u64(self, v: u64) -> Result - where E: Error + where + E: Error, { Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) } - /// Deserialize a `f32` into a `Value`. + /// The input contains an `f32`. + /// + /// The default implementation forwards to [`visit_f64`]. + /// + /// [`visit_f64`]: #method.visit_f64 fn visit_f32(self, v: f32) -> Result - where E: Error + where + E: Error, { self.visit_f64(v as f64) } - /// Deserialize a `f64` into a `Value`. + /// The input contains an `f64`. + /// + /// The default implementation fails with a type error. fn visit_f64(self, v: f64) -> Result - where E: Error + where + E: Error, { Err(Error::invalid_type(Unexpected::Float(v), &self)) } - /// Deserialize a `char` into a `Value`. + /// The input contains a `char`. + /// + /// The default implementation forwards to [`visit_str`] as a one-character + /// string. + /// + /// [`visit_str`]: #method.visit_str #[inline] fn visit_char(self, v: char) -> Result - where E: Error + where + E: Error, { - self.visit_str(::utils::encode_utf8(v).as_str()) + self.visit_str(utf8::encode(v).as_str()) } - /// Deserialize a `&str` into a `Value`. + /// The input contains a string. The lifetime of the string is ephemeral and + /// it may be destroyed after this method returns. /// /// This method allows the `Deserializer` to avoid a copy by retaining /// ownership of any buffered data. `Deserialize` implementations that do @@ -1034,12 +1223,31 @@ pub trait Visitor: Sized { /// It is never correct to implement `visit_string` without implementing /// `visit_str`. Implement neither, both, or just `visit_str`. fn visit_str(self, v: &str) -> Result - where E: Error + where + E: Error, { Err(Error::invalid_type(Unexpected::Str(v), &self)) } - /// Deserialize a `String` into a `Value`. + /// The input contains a string that lives at least as long as the + /// `Deserializer`. + /// + /// This enables zero-copy deserialization of strings in some formats. For + /// example JSON input containing the JSON string `"borrowed"` can be + /// deserialized with zero copying into a `&'a str` as long as the input + /// data outlives `'a`. + /// + /// The default implementation forwards to `visit_str`. + #[inline] + fn visit_borrowed_str(self, v: &'de str) -> Result + where + E: Error, + { + self.visit_str(v) + } + + /// The input contains a string and ownership of the string is being given + /// to the `Visitor`. /// /// This method allows the `Visitor` to avoid a copy by taking ownership of /// a string created by the `Deserializer`. `Deserialize` implementations @@ -1056,66 +1264,14 @@ pub trait Visitor: Sized { #[inline] #[cfg(any(feature = "std", feature = "collections"))] fn visit_string(self, v: String) -> Result - where E: Error + where + E: Error, { self.visit_str(&v) } - /// Deserialize a `()` into a `Value`. - fn visit_unit(self) -> Result - where E: Error - { - Err(Error::invalid_type(Unexpected::Unit, &self)) - } - - /// Deserialize an absent optional `Value`. - fn visit_none(self) -> Result - where E: Error - { - Err(Error::invalid_type(Unexpected::Option, &self)) - } - - /// Deserialize a present optional `Value`. - fn visit_some(self, deserializer: D) -> Result - where D: Deserializer - { - let _ = deserializer; - Err(Error::invalid_type(Unexpected::Option, &self)) - } - - /// Deserialize `Value` as a newtype struct. - fn visit_newtype_struct(self, deserializer: D) -> Result - where D: Deserializer - { - let _ = deserializer; - Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) - } - - /// Deserialize `Value` as a sequence of elements. - fn visit_seq(self, visitor: V) -> Result - where V: SeqVisitor - { - let _ = visitor; - Err(Error::invalid_type(Unexpected::Seq, &self)) - } - - /// Deserialize `Value` as a key-value map. - fn visit_map(self, visitor: V) -> Result - where V: MapVisitor - { - let _ = visitor; - Err(Error::invalid_type(Unexpected::Map, &self)) - } - - /// Deserialize `Value` as an enum. - fn visit_enum(self, visitor: V) -> Result - where V: EnumVisitor - { - let _ = visitor; - Err(Error::invalid_type(Unexpected::Enum, &self)) - } - - /// Deserialize a `&[u8]` into a `Value`. + /// The input contains a byte array. The lifetime of the byte array is + /// ephemeral and it may be destroyed after this method returns. /// /// This method allows the `Deserializer` to avoid a copy by retaining /// ownership of any buffered data. `Deserialize` implementations that do @@ -1126,13 +1282,31 @@ pub trait Visitor: Sized { /// It is never correct to implement `visit_byte_buf` without implementing /// `visit_bytes`. Implement neither, both, or just `visit_bytes`. fn visit_bytes(self, v: &[u8]) -> Result - where E: Error + where + E: Error, { let _ = v; Err(Error::invalid_type(Unexpected::Bytes(v), &self)) } - /// Deserialize a `Vec` into a `Value`. + /// The input contains a byte array that lives at least as long as the + /// `Deserializer`. + /// + /// This enables zero-copy deserialization of bytes in some formats. For + /// example Bincode data containing bytes can be deserialized with zero + /// copying into a `&'a [u8]` as long as the input data outlives `'a`. + /// + /// The default implementation forwards to `visit_bytes`. + #[inline] + fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result + where + E: Error, + { + self.visit_bytes(v) + } + + /// The input contains a byte array and ownership of the byte array is being + /// given to the `Visitor`. /// /// This method allows the `Visitor` to avoid a copy by taking ownership of /// a byte buffer created by the `Deserializer`. `Deserialize` @@ -1149,19 +1323,98 @@ pub trait Visitor: Sized { /// `Vec`. #[cfg(any(feature = "std", feature = "collections"))] fn visit_byte_buf(self, v: Vec) -> Result - where E: Error + where + E: Error, { self.visit_bytes(&v) } + + /// The input contains an optional that is absent. + /// + /// The default implementation fails with a type error. + fn visit_none(self) -> Result + where + E: Error, + { + Err(Error::invalid_type(Unexpected::Option, &self)) + } + + /// The input contains an optional that is present. + /// + /// The default implementation fails with a type error. + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let _ = deserializer; + Err(Error::invalid_type(Unexpected::Option, &self)) + } + + /// The input contains a unit `()`. + /// + /// The default implementation fails with a type error. + fn visit_unit(self) -> Result + where + E: Error, + { + Err(Error::invalid_type(Unexpected::Unit, &self)) + } + + /// The input contains a newtype struct. + /// + /// The content of the newtype struct may be read from the given + /// `Deserializer`. + /// + /// The default implementation fails with a type error. + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let _ = deserializer; + Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) + } + + /// The input contains a sequence of elements. + /// + /// The default implementation fails with a type error. + fn visit_seq(self, seq: A) -> Result + where + A: SeqAccess<'de>, + { + let _ = seq; + Err(Error::invalid_type(Unexpected::Seq, &self)) + } + + /// The input contains a key-value map. + /// + /// The default implementation fails with a type error. + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'de>, + { + let _ = map; + Err(Error::invalid_type(Unexpected::Map, &self)) + } + + /// The input contains an enum. + /// + /// The default implementation fails with a type error. + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, + { + let _ = data; + Err(Error::invalid_type(Unexpected::Enum, &self)) + } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// `SeqVisitor` visits each item in a sequence. +/// Provides a `Visitor` access to each element of a sequence in the input. /// /// This is a trait that a `Deserializer` passes to a `Visitor` implementation, /// which deserializes each item in a sequence. -pub trait SeqVisitor { +pub trait SeqAccess<'de> { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; @@ -1169,61 +1422,66 @@ pub trait SeqVisitor { /// 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; + /// `Deserialize` implementations should typically use + /// `SeqAcccess::next_element` instead. + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>; /// 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 override the default behavior. + /// `SeqAccess` implementations should not override the default behavior. #[inline] - fn visit(&mut self) -> Result, Self::Error> - where T: Deserialize + fn next_element(&mut self) -> Result, Self::Error> + where + T: Deserialize<'de>, { - self.visit_seed(PhantomData) + self.next_element_seed(PhantomData) } - /// Return the lower and upper bound of items remaining in the sequence. + /// Returns the number of elements remaining in the sequence, if known. #[inline] - fn size_hint(&self) -> (usize, Option) { - (0, None) + fn size_hint(&self) -> Option { + None } } -impl<'a, V> SeqVisitor for &'a mut V - where V: SeqVisitor +impl<'de, 'a, A> SeqAccess<'de> for &'a mut A +where + A: SeqAccess<'de>, { - type Error = V::Error; + type Error = A::Error; #[inline] - fn visit_seed(&mut self, seed: T) -> Result, V::Error> - where T: DeserializeSeed + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, { - (**self).visit_seed(seed) + (**self).next_element_seed(seed) } #[inline] - fn visit(&mut self) -> Result, V::Error> - where T: Deserialize + fn next_element(&mut self) -> Result, Self::Error> + where + T: Deserialize<'de>, { - (**self).visit() + (**self).next_element() } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> Option { (**self).size_hint() } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// `MapVisitor` visits each item in a sequence. +/// Provides a `Visitor` access to each entry of a map in the input. /// /// This is a trait that a `Deserializer` passes to a `Visitor` implementation. -pub trait MapVisitor { +pub trait MapAccess<'de> { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; @@ -1232,36 +1490,45 @@ pub trait MapVisitor { /// 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; + /// `MapAccess::next_key` or `MapAccess::next_entry` instead. + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: DeserializeSeed<'de>; /// 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; + /// `MapAccess::next_value` instead. + /// + /// # Panics + /// + /// Calling `next_value_seed` before `next_key_seed` is incorrect and is + /// allowed to panic or return bogus results. + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>; /// 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 + /// `MapAccess` implementations should override the default behavior if a /// more efficient implementation is possible. /// - /// `Deserialize` implementations should typically use `MapVisitor::visit` - /// instead. + /// `Deserialize` implementations should typically use + /// `MapAccess::next_entry` instead. #[inline] - fn visit_seed(&mut self, - kseed: K, - vseed: V) - -> Result, Self::Error> - where K: DeserializeSeed, - V: DeserializeSeed + fn next_entry_seed( + &mut self, + kseed: K, + vseed: V, + ) -> Result, Self::Error> + where + K: DeserializeSeed<'de>, + V: DeserializeSeed<'de>, { - match try!(self.visit_key_seed(kseed)) { + match try!(self.next_key_seed(kseed)) { Some(key) => { - let value = try!(self.visit_value_seed(vseed)); + let value = try!(self.next_value_seed(vseed)); Ok(Some((key, value))) } None => Ok(None), @@ -1272,141 +1539,160 @@ pub trait MapVisitor { /// if there are no more remaining entries. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `MapVisitor` implementations should not override the default behavior. + /// `MapAccess` implementations should not override the default behavior. #[inline] - fn visit_key(&mut self) -> Result, Self::Error> - where K: Deserialize + fn next_key(&mut self) -> Result, Self::Error> + where + K: Deserialize<'de>, { - self.visit_key_seed(PhantomData) + self.next_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 override the default behavior. + /// `MapAccess` implementations should not override the default behavior. + /// + /// # Panics + /// + /// Calling `next_value` before `next_key` is incorrect and is allowed to + /// panic or return bogus results. #[inline] - fn visit_value(&mut self) -> Result - where V: Deserialize + fn next_value(&mut self) -> Result + where + V: Deserialize<'de>, { - self.visit_value_seed(PhantomData) + self.next_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 override the default behavior. + /// `MapAccess` implementations should not override the default behavior. #[inline] - fn visit(&mut self) -> Result, Self::Error> - where K: Deserialize, - V: Deserialize + fn next_entry(&mut self) -> Result, Self::Error> + where + K: Deserialize<'de>, + V: Deserialize<'de>, { - self.visit_seed(PhantomData, PhantomData) + self.next_entry_seed(PhantomData, PhantomData) } - /// Return the lower and upper bound of items remaining in the sequence. + /// Returns the number of entries remaining in the map, if known. #[inline] - fn size_hint(&self) -> (usize, Option) { - (0, None) + fn size_hint(&self) -> Option { + None } } -impl<'a, V_> MapVisitor for &'a mut V_ - where V_: MapVisitor +impl<'de, 'a, A> MapAccess<'de> for &'a mut A +where + A: MapAccess<'de>, { - type Error = V_::Error; + type Error = A::Error; #[inline] - fn visit_key_seed(&mut self, seed: K) -> Result, Self::Error> - where K: DeserializeSeed + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: DeserializeSeed<'de>, { - (**self).visit_key_seed(seed) + (**self).next_key_seed(seed) } #[inline] - fn visit_value_seed(&mut self, seed: V) -> Result - where V: DeserializeSeed + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, { - (**self).visit_value_seed(seed) + (**self).next_value_seed(seed) } #[inline] - fn visit_seed(&mut self, - kseed: K, - vseed: V) - -> Result, Self::Error> - where K: DeserializeSeed, - V: DeserializeSeed + fn next_entry_seed( + &mut self, + kseed: K, + vseed: V, + ) -> Result, Self::Error> + where + K: DeserializeSeed<'de>, + V: DeserializeSeed<'de>, { - (**self).visit_seed(kseed, vseed) + (**self).next_entry_seed(kseed, vseed) } #[inline] - fn visit(&mut self) -> Result, V_::Error> - where K: Deserialize, - V: Deserialize + fn next_entry(&mut self) -> Result, Self::Error> + where + K: Deserialize<'de>, + V: Deserialize<'de>, { - (**self).visit() + (**self).next_entry() } #[inline] - fn visit_key(&mut self) -> Result, V_::Error> - where K: Deserialize + fn next_key(&mut self) -> Result, Self::Error> + where + K: Deserialize<'de>, { - (**self).visit_key() + (**self).next_key() } #[inline] - fn visit_value(&mut self) -> Result - where V: Deserialize + fn next_value(&mut self) -> Result + where + V: Deserialize<'de>, { - (**self).visit_value() + (**self).next_value() } #[inline] - fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> Option { (**self).size_hint() } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// `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: Sized { +/// Provides a `Visitor` access to the data of an enum in the input. +/// +/// `EnumAccess` is created by the `Deserializer` and passed to the +/// `Visitor` in order to identify which variant of an enum to deserialize. +pub trait EnumAccess<'de>: 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 /// variant. - type Variant: VariantVisitor; + type Variant: VariantAccess<'de, Error = Self::Error>; - /// `visit_variant` is called to identify which variant to deserialize. + /// `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; + /// `Deserialize` implementations should typically use `EnumAccess::variant` + /// instead. + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>; - /// `visit_variant` is called to identify which variant to deserialize. + /// `variant` is called to identify which variant to deserialize. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `EnumVisitor` implementations should not override the default behavior. + /// `EnumAccess` implementations should not override the default behavior. #[inline] - fn visit_variant(self) -> Result<(V, Self::Variant), Self::Error> - where V: Deserialize + fn variant(self) -> Result<(V, Self::Variant), Self::Error> + where + V: Deserialize<'de>, { - self.visit_variant_seed(PhantomData) + self.variant_seed(PhantomData) } } -/// `VariantVisitor` is a visitor that is created by the `Deserializer` and +/// `VariantAccess` 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: Sized { +pub trait VariantAccess<'de>: Sized { /// The error type that can be returned if some error occurs during - /// deserialization. Must match the error type of our `EnumVisitor`. + /// deserialization. Must match the error type of our `EnumAccess`. type Error: Error; /// Called when deserializing a variant with no values. @@ -1414,45 +1700,87 @@ pub trait VariantVisitor: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust,ignore - /// fn visit_unit(self) -> Result<(), Self::Error> { + /// ```rust + /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; + /// # + /// # struct X; + /// # + /// # impl<'de> VariantAccess<'de> for X { + /// # type Error = value::Error; + /// # + /// fn unit_variant(self) -> Result<(), Self::Error> { /// // What the data actually contained; suppose it is a tuple variant. /// let unexp = Unexpected::TupleVariant; /// Err(de::Error::invalid_type(unexp, &"unit variant")) /// } + /// # + /// # fn newtype_variant_seed(self, _: T) -> Result + /// # where T: DeserializeSeed<'de> + /// # { unimplemented!() } + /// # + /// # fn tuple_variant(self, _: usize, _: V) -> Result + /// # where V: Visitor<'de> + /// # { unimplemented!() } + /// # + /// # fn struct_variant(self, _: &[&str], _: V) -> Result + /// # where V: Visitor<'de> + /// # { unimplemented!() } + /// # } /// ``` - fn visit_unit(self) -> Result<(), Self::Error>; + fn unit_variant(self) -> Result<(), Self::Error>; /// Called when deserializing a variant with a single value. /// /// `Deserialize` implementations should typically use - /// `VariantVisitor::visit_newtype` instead. + /// `VariantAccess::newtype_variant` instead. /// /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust,ignore - /// fn visit_newtype_seed(self, _seed: T) -> Result - /// where T: de::DeserializeSeed + /// ```rust + /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; + /// # + /// # struct X; + /// # + /// # impl<'de> VariantAccess<'de> for X { + /// # type Error = value::Error; + /// # + /// # fn unit_variant(self) -> Result<(), Self::Error> { + /// # unimplemented!() + /// # } + /// # + /// fn newtype_variant_seed(self, _seed: T) -> Result + /// where T: DeserializeSeed<'de> /// { /// // What the data actually contained; suppose it is a unit variant. /// let unexp = Unexpected::UnitVariant; /// Err(de::Error::invalid_type(unexp, &"newtype variant")) /// } + /// # + /// # fn tuple_variant(self, _: usize, _: V) -> Result + /// # where V: Visitor<'de> + /// # { unimplemented!() } + /// # + /// # fn struct_variant(self, _: &[&str], _: V) -> Result + /// # where V: Visitor<'de> + /// # { unimplemented!() } + /// # } /// ``` - fn visit_newtype_seed(self, seed: T) -> Result - where T: DeserializeSeed; + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>; /// Called when deserializing a variant with a single value. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `VariantVisitor` implementations should not override the default + /// `VariantAccess` implementations should not override the default /// behavior. #[inline] - fn visit_newtype(self) -> Result - where T: Deserialize + fn newtype_variant(self) -> Result + where + T: Deserialize<'de>, { - self.visit_newtype_seed(PhantomData) + self.newtype_variant_seed(PhantomData) } /// Called when deserializing a tuple-like variant. @@ -1462,19 +1790,40 @@ pub trait VariantVisitor: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust,ignore - /// fn visit_tuple(self, - /// _len: usize, - /// _visitor: V) -> Result - /// where V: Visitor + /// ```rust + /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; + /// # + /// # struct X; + /// # + /// # impl<'de> VariantAccess<'de> for X { + /// # type Error = value::Error; + /// # + /// # fn unit_variant(self) -> Result<(), Self::Error> { + /// # unimplemented!() + /// # } + /// # + /// # fn newtype_variant_seed(self, _: T) -> Result + /// # where T: DeserializeSeed<'de> + /// # { unimplemented!() } + /// # + /// fn tuple_variant(self, + /// _len: usize, + /// _visitor: V) -> Result + /// where V: Visitor<'de> /// { /// // What the data actually contained; suppose it is a unit variant. /// let unexp = Unexpected::UnitVariant; - /// Err(Error::invalid_type(unexp, &"tuple variant")) + /// Err(de::Error::invalid_type(unexp, &"tuple variant")) /// } + /// # + /// # fn struct_variant(self, _: &[&str], _: V) -> Result + /// # where V: Visitor<'de> + /// # { unimplemented!() } + /// # } /// ``` - fn visit_tuple(self, len: usize, visitor: V) -> Result - where V: Visitor; + fn tuple_variant(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>; /// Called when deserializing a struct-like variant. /// @@ -1483,25 +1832,85 @@ pub trait VariantVisitor: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```rust,ignore - /// fn visit_struct(self, - /// _fields: &'static [&'static str], - /// _visitor: V) -> Result - /// where V: Visitor + /// ```rust + /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; + /// # + /// # struct X; + /// # + /// # impl<'de> VariantAccess<'de> for X { + /// # type Error = value::Error; + /// # + /// # fn unit_variant(self) -> Result<(), Self::Error> { + /// # unimplemented!() + /// # } + /// # + /// # fn newtype_variant_seed(self, _: T) -> Result + /// # where T: DeserializeSeed<'de> + /// # { unimplemented!() } + /// # + /// # fn tuple_variant(self, _: usize, _: V) -> Result + /// # where V: Visitor<'de> + /// # { unimplemented!() } + /// # + /// fn struct_variant(self, + /// _fields: &'static [&'static str], + /// _visitor: V) -> Result + /// where V: Visitor<'de> /// { /// // What the data actually contained; suppose it is a unit variant. /// let unexp = Unexpected::UnitVariant; - /// Err(Error::invalid_type(unexp, &"struct variant")) + /// Err(de::Error::invalid_type(unexp, &"struct variant")) /// } + /// # } /// ``` - fn visit_struct(self, - fields: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor; + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>; } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/// Converts an existing value into a `Deserializer` from which other values can +/// be deserialized. +/// +/// ```rust +/// #[macro_use] +/// extern crate serde_derive; +/// +/// extern crate serde; +/// +/// use std::str::FromStr; +/// use serde::de::{value, Deserialize, IntoDeserializer}; +/// +/// #[derive(Deserialize)] +/// enum Setting { +/// On, +/// Off, +/// } +/// +/// impl FromStr for Setting { +/// type Err = value::Error; +/// +/// fn from_str(s: &str) -> Result { +/// Self::deserialize(s.into_deserializer()) +/// } +/// } +/// # +/// # fn main() {} +/// ``` +pub trait IntoDeserializer<'de, E: Error = value::Error> { + /// The type of the deserializer being converted into. + type Deserializer: Deserializer<'de, Error = E>; + + /// Convert this value into a deserializer. + fn into_deserializer(self) -> Self::Deserializer; +} + +//////////////////////////////////////////////////////////////////////////////// /// Used in error messages. /// diff --git a/serde/src/de/private.rs b/serde/src/de/private.rs deleted file mode 100644 index 092d66a6..00000000 --- a/serde/src/de/private.rs +++ /dev/null @@ -1,44 +0,0 @@ -use core::marker::PhantomData; - -use de::{Deserialize, Deserializer, Error, Visitor}; - -#[cfg(any(feature = "std", feature = "collections"))] -pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor, - TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor, - UntaggedUnitVisitor}; - -/// 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 u8 u16 u32 u64 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/utf8.rs b/serde/src/de/utf8.rs new file mode 100644 index 00000000..37221a1e --- /dev/null +++ b/serde/src/de/utf8.rs @@ -0,0 +1,54 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use lib::*; + +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; + +#[inline] +pub fn encode(c: char) -> Encode { + let code = c as u32; + let mut buf = [0; 4]; + let pos = if code < MAX_ONE_B { + buf[3] = code as u8; + 3 + } else if code < MAX_TWO_B { + buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + buf[3] = (code & 0x3F) as u8 | TAG_CONT; + 2 + } else if code < MAX_THREE_B { + buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; + buf[3] = (code & 0x3F) as u8 | TAG_CONT; + 1 + } else { + buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; + buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; + buf[3] = (code & 0x3F) as u8 | TAG_CONT; + 0 + }; + Encode { buf: buf, pos: pos } +} + +pub struct Encode { + buf: [u8; 4], + pos: usize, +} + +impl Encode { + pub fn as_str(&self) -> &str { + str::from_utf8(&self.buf[self.pos..]).unwrap() + } +} diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 00f32d68..f3bf0558 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -1,39 +1,51 @@ -//! This module supports deserializing from primitives with the `ValueDeserializer` trait. +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. -#[cfg(feature = "std")] -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, btree_map, btree_set, hash_map, - hash_set}; -#[cfg(feature = "std")] -use std::borrow::Cow; -#[cfg(feature = "std")] -use std::vec; +//! Building blocks for deserializing basic values using the `IntoDeserializer` +//! trait. +//! +//! ```rust +//! #[macro_use] +//! extern crate serde_derive; +//! +//! extern crate serde; +//! +//! use std::str::FromStr; +//! use serde::de::{value, Deserialize, IntoDeserializer}; +//! +//! #[derive(Deserialize)] +//! enum Setting { +//! On, +//! Off, +//! } +//! +//! impl FromStr for Setting { +//! type Err = value::Error; +//! +//! fn from_str(s: &str) -> Result { +//! Self::deserialize(s.into_deserializer()) +//! } +//! } +//! # +//! # fn main() {} +//! ``` -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::{BTreeMap, BTreeSet, Vec, String, btree_map, btree_set, vec}; -#[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; +use lib::*; -#[cfg(feature = "std")] -use core::hash::Hash; -#[cfg(feature = "std")] -use std::error; -#[cfg(not(feature = "std"))] -use error; +use de::{self, IntoDeserializer, Expected, SeqAccess}; +use private::de::size_hint; +use ser; +use self::private::{First, Second}; -use core::fmt::{self, Display}; -use core::iter::{self, Iterator}; -use core::marker::PhantomData; +//////////////////////////////////////////////////////////////////////////////// -use de::{self, Expected, SeqVisitor}; -use bytes; - -/////////////////////////////////////////////////////////////////////////////// - -/// This represents all the possible errors that can occur using the `ValueDeserializer`. +/// A minimal representation of all possible errors that can occur using the +/// `IntoDeserializer` trait. #[derive(Clone, Debug, PartialEq)] pub struct Error { err: ErrorImpl, @@ -46,16 +58,32 @@ type ErrorImpl = (); impl de::Error for Error { #[cfg(any(feature = "std", feature = "collections"))] - fn custom(msg: T) -> Self { + fn custom(msg: T) -> Self + where + T: Display, + { Error { err: msg.to_string().into_boxed_str() } } #[cfg(not(any(feature = "std", feature = "collections")))] - fn custom(_msg: T) -> Self { + fn custom(msg: T) -> Self + where + T: Display, + { + let _ = msg; Error { err: () } } } +impl ser::Error for Error { + fn custom(msg: T) -> Self + where + T: Display, + { + de::Error::custom(msg) + } +} + impl Display for Error { #[cfg(any(feature = "std", feature = "collections"))] fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -68,33 +96,18 @@ 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" - } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// This trait converts primitive types into a deserializer. -pub trait ValueDeserializer { - /// The actual deserializer type. - type Deserializer: de::Deserializer; - - /// Convert this value into a deserializer. - fn into_deserializer(self) -> Self::Deserializer; -} - -/////////////////////////////////////////////////////////////////////////////// - -impl ValueDeserializer for () - where E: de::Error +impl<'de, E> IntoDeserializer<'de, E> for () +where + E: de::Error, { type Deserializer = UnitDeserializer; @@ -103,47 +116,54 @@ impl ValueDeserializer for () } } -/// A helper deserializer that deserializes a `()`. +/// A deserializer holding a `()`. +#[derive(Clone, Debug)] pub struct UnitDeserializer { marker: PhantomData, } -impl de::Deserializer for UnitDeserializer - where E: de::Error +impl<'de, E> de::Deserializer<'de> for UnitDeserializer +where + E: de::Error, { type Error = E; - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq - seq_fixed_size bytes map unit_struct newtype_struct tuple_struct struct - struct_field tuple enum ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map + struct enum identifier ignored_any } - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { visitor.visit_unit() } fn deserialize_option(self, visitor: V) -> Result - where V: de::Visitor + where + V: de::Visitor<'de>, { visitor.visit_none() } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// macro_rules! primitive_deserializer { - ($ty:ty, $name:ident, $method:ident $($cast:tt)*) => { - /// A helper deserializer that deserializes a number. + ($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => { + #[doc = "A deserializer holding"] + #[doc = $doc] + #[derive(Clone, Debug)] pub struct $name { value: $ty, marker: PhantomData } - impl ValueDeserializer for $ty - where E: de::Error, + impl<'de, E> IntoDeserializer<'de, E> for $ty + where + E: de::Error, { type Deserializer = $name; @@ -155,19 +175,21 @@ macro_rules! primitive_deserializer { } } - impl de::Deserializer for $name - where E: de::Error, + impl<'de, E> de::Deserializer<'de> for $name + where + E: de::Error, { type Error = E; - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit - option seq seq_fixed_size bytes map unit_struct newtype_struct - tuple_struct struct struct_field tuple enum ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any } - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor, + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { visitor.$method(self.value $($cast)*) } @@ -175,28 +197,30 @@ macro_rules! primitive_deserializer { } } -primitive_deserializer!(bool, BoolDeserializer, visit_bool); -primitive_deserializer!(i8, I8Deserializer, visit_i8); -primitive_deserializer!(i16, I16Deserializer, visit_i16); -primitive_deserializer!(i32, I32Deserializer, visit_i32); -primitive_deserializer!(i64, I64Deserializer, visit_i64); -primitive_deserializer!(isize, IsizeDeserializer, visit_i64 as i64); -primitive_deserializer!(u8, U8Deserializer, visit_u8); -primitive_deserializer!(u16, U16Deserializer, visit_u16); -primitive_deserializer!(u64, U64Deserializer, visit_u64); -primitive_deserializer!(usize, UsizeDeserializer, visit_u64 as u64); -primitive_deserializer!(f32, F32Deserializer, visit_f32); -primitive_deserializer!(f64, F64Deserializer, visit_f64); -primitive_deserializer!(char, CharDeserializer, visit_char); +primitive_deserializer!(bool, "a `bool`.", BoolDeserializer, visit_bool); +primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8); +primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16); +primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32); +primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64); +primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64); +primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8); +primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16); +primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64); +primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64); +primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32); +primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64); +primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char); -/// A helper deserializer that deserializes a number. +/// A deserializer holding a `u32`. +#[derive(Clone, Debug)] pub struct U32Deserializer { value: u32, marker: PhantomData, } -impl ValueDeserializer for u32 - where E: de::Error +impl<'de, E> IntoDeserializer<'de, E> for u32 +where + E: de::Error, { type Deserializer = U32Deserializer; @@ -208,57 +232,67 @@ impl ValueDeserializer for u32 } } -impl de::Deserializer for U32Deserializer - where E: de::Error +impl<'de, E> de::Deserializer<'de> for U32Deserializer +where + E: de::Error, { type Error = E; - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct identifier ignored_any } - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { visitor.visit_u32(self.value) } - fn deserialize_enum(self, - _name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor + fn deserialize_enum( + self, + name: &str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { + let _ = name; + let _ = variants; visitor.visit_enum(self) } } -impl de::EnumVisitor for U32Deserializer - where E: de::Error +impl<'de, E> de::EnumAccess<'de> for U32Deserializer +where + E: de::Error, { type Error = E; type Variant = private::UnitOnly; - fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> - where T: de::DeserializeSeed + fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A helper deserializer that deserializes a `&str`. +/// A deserializer holding a `&str`. +#[derive(Clone, Debug)] pub struct StrDeserializer<'a, E> { value: &'a str, marker: PhantomData, } -impl<'a, E> ValueDeserializer for &'a str - where E: de::Error +impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str +where + E: de::Error, { type Deserializer = StrDeserializer<'a, E>; @@ -270,59 +304,69 @@ impl<'a, E> ValueDeserializer for &'a str } } -impl<'a, E> de::Deserializer for StrDeserializer<'a, E> - where E: de::Error +impl<'de, 'a, E> de::Deserializer<'de> for StrDeserializer<'a, E> +where + E: de::Error, { type Error = E; - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { visitor.visit_str(self.value) } - fn deserialize_enum(self, - _name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor + fn deserialize_enum( + self, + name: &str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { + let _ = name; + let _ = variants; visitor.visit_enum(self) } - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct identifier ignored_any } } -impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E> - where E: de::Error +impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E> +where + E: de::Error, { type Error = E; type Variant = private::UnitOnly; - fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> - where T: de::DeserializeSeed + fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A helper deserializer that deserializes a `String`. +/// A deserializer holding a `String`. #[cfg(any(feature = "std", feature = "collections"))] +#[derive(Clone, Debug)] pub struct StringDeserializer { value: String, marker: PhantomData, } #[cfg(any(feature = "std", feature = "collections"))] -impl ValueDeserializer for String - where E: de::Error +impl<'de, E> IntoDeserializer<'de, E> for String +where + E: de::Error, { type Deserializer = StringDeserializer; @@ -335,60 +379,70 @@ impl ValueDeserializer for String } #[cfg(any(feature = "std", feature = "collections"))] -impl de::Deserializer for StringDeserializer - where E: de::Error +impl<'de, E> de::Deserializer<'de> for StringDeserializer +where + E: de::Error, { type Error = E; - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { visitor.visit_string(self.value) } - fn deserialize_enum(self, - _name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor + fn deserialize_enum( + self, + name: &str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { + let _ = name; + let _ = variants; visitor.visit_enum(self) } - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct identifier ignored_any } } #[cfg(any(feature = "std", feature = "collections"))] -impl<'a, E> de::EnumVisitor for StringDeserializer - where E: de::Error +impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer +where + E: de::Error, { type Error = E; type Variant = private::UnitOnly; - fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> - where T: de::DeserializeSeed + fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A helper deserializer that deserializes a `String`. +/// A deserializer holding a `Cow`. #[cfg(any(feature = "std", feature = "collections"))] +#[derive(Clone, Debug)] pub struct CowStrDeserializer<'a, E> { value: Cow<'a, str>, marker: PhantomData, } #[cfg(any(feature = "std", feature = "collections"))] -impl<'a, E> ValueDeserializer for Cow<'a, str> - where E: de::Error +impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> +where + E: de::Error, { type Deserializer = CowStrDeserializer<'a, E>; @@ -401,13 +455,15 @@ impl<'a, E> ValueDeserializer for Cow<'a, str> } #[cfg(any(feature = "std", feature = "collections"))] -impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E> - where E: de::Error +impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> +where + E: de::Error, { type Error = E; - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { match self.value { Cow::Borrowed(string) => visitor.visit_str(string), @@ -415,40 +471,47 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E> } } - fn deserialize_enum(self, - _name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor + fn deserialize_enum( + self, + name: &str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { + let _ = name; + let _ = variants; visitor.visit_enum(self) } - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct identifier ignored_any } } #[cfg(any(feature = "std", feature = "collections"))] -impl<'a, E> de::EnumVisitor for CowStrDeserializer<'a, E> - where E: de::Error +impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> +where + E: de::Error, { type Error = E; type Variant = private::UnitOnly; - fn visit_variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> - where T: de::DeserializeSeed + fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A helper deserializer that deserializes a sequence. +/// A deserializer that iterates over a sequence. +#[derive(Clone, Debug)] pub struct SeqDeserializer { iter: iter::Fuse, count: usize, @@ -456,10 +519,10 @@ pub struct SeqDeserializer { } impl SeqDeserializer - where I: Iterator, - E: de::Error +where + I: Iterator, { - /// Construct a new `SeqDeserializer`. + /// Construct a new `SeqDeserializer`. pub fn new(iter: I) -> Self { SeqDeserializer { iter: iter.fuse(), @@ -467,7 +530,13 @@ impl SeqDeserializer marker: PhantomData, } } +} +impl SeqDeserializer +where + I: Iterator, + E: de::Error, +{ /// Check for remaining elements after passing a `SeqDeserializer` to /// `Visitor::visit_seq`. pub fn end(mut self) -> Result<(), E> { @@ -480,42 +549,46 @@ impl SeqDeserializer } 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))) + Err(de::Error::invalid_length(self.count + remaining, &ExpectedInSeq(self.count)),) } } } -impl de::Deserializer for SeqDeserializer - where I: Iterator, - T: ValueDeserializer, - E: de::Error +impl<'de, I, T, E> de::Deserializer<'de> for SeqDeserializer +where + I: Iterator, + T: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - fn deserialize(mut self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, { let v = try!(visitor.visit_seq(&mut self)); try!(self.end()); Ok(v) } - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple enum ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum identifier ignored_any } } -impl de::SeqVisitor for SeqDeserializer - where I: Iterator, - T: ValueDeserializer, - E: de::Error +impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer +where + I: Iterator, + T: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - fn visit_seed(&mut self, seed: V) -> Result, Self::Error> - where V: de::DeserializeSeed + fn next_element_seed(&mut self, seed: V) -> Result, Self::Error> + where + V: de::DeserializeSeed<'de>, { match self.iter.next() { Some(value) => { @@ -526,8 +599,8 @@ impl de::SeqVisitor for SeqDeserializer } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } @@ -543,14 +616,15 @@ impl Expected for ExpectedInSeq { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "collections"))] -impl ValueDeserializer for Vec - where T: ValueDeserializer, - E: de::Error +impl<'de, T, E> IntoDeserializer<'de, E> for Vec +where + T: IntoDeserializer<'de, E>, + E: de::Error, { - type Deserializer = SeqDeserializer, E>; + type Deserializer = SeqDeserializer< as IntoIterator>::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { SeqDeserializer::new(self.into_iter()) @@ -558,11 +632,12 @@ impl ValueDeserializer for Vec } #[cfg(any(feature = "std", feature = "collections"))] -impl ValueDeserializer for BTreeSet - where T: ValueDeserializer + Eq + Ord, - E: de::Error +impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet +where + T: IntoDeserializer<'de, E> + Eq + Ord, + E: de::Error, { - type Deserializer = SeqDeserializer, E>; + type Deserializer = SeqDeserializer< as IntoIterator>::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { SeqDeserializer::new(self.into_iter()) @@ -570,88 +645,91 @@ impl ValueDeserializer for BTreeSet } #[cfg(feature = "std")] -impl ValueDeserializer for HashSet - where T: ValueDeserializer + Eq + Hash, - E: de::Error +impl<'de, T, E> IntoDeserializer<'de, E> for HashSet +where + T: IntoDeserializer<'de, E> + Eq + Hash, + E: de::Error, { - type Deserializer = SeqDeserializer, E>; + type Deserializer = SeqDeserializer< as IntoIterator>::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { SeqDeserializer::new(self.into_iter()) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A helper deserializer that deserializes a sequence using a `SeqVisitor`. -pub struct SeqVisitorDeserializer { - visitor: V_, - marker: PhantomData, +/// A deserializer holding a `SeqAccess`. +#[derive(Clone, Debug)] +pub struct SeqAccessDeserializer { + seq: A, } -impl SeqVisitorDeserializer - where V_: de::SeqVisitor, - E: de::Error +impl SeqAccessDeserializer { + /// Construct a new `SeqAccessDeserializer`. + pub fn new(seq: A) -> Self { + SeqAccessDeserializer { seq: seq } + } +} + +impl<'de, A> de::Deserializer<'de> for SeqAccessDeserializer +where + A: de::SeqAccess<'de>, { - /// Construct a new `SeqVisitorDeserializer`. - pub fn new(visitor: V_) -> Self { - SeqVisitorDeserializer { - visitor: visitor, - marker: PhantomData, - } + type Error = A::Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_seq(self.seq) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum identifier ignored_any } } -impl de::Deserializer for SeqVisitorDeserializer - where V_: de::SeqVisitor, - E: de::Error -{ - type Error = E; +//////////////////////////////////////////////////////////////////////////////// - fn deserialize(self, visitor: V) -> Result { - visitor.visit_seq(self.visitor) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple enum ignored_any byte_buf - } -} - -/////////////////////////////////////////////////////////////////////////////// - -/// A helper deserializer that deserializes a map. -pub struct MapDeserializer - where I: Iterator, - I::Item: private::Pair, - ::First: ValueDeserializer, - ::Second: ValueDeserializer, - E: de::Error +/// A deserializer that iterates over a map. +pub struct MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, { iter: iter::Fuse, - value: Option<::Second>, + value: Option>, count: usize, - marker: PhantomData, + lifetime: PhantomData<&'de ()>, + error: PhantomData, } -impl MapDeserializer - where I: Iterator, - I::Item: private::Pair, - ::First: ValueDeserializer, - ::Second: ValueDeserializer, - E: de::Error +impl<'de, I, E> MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, { - /// Construct a new `MapDeserializer`. + /// Construct a new `MapDeserializer`. pub fn new(iter: I) -> Self { MapDeserializer { iter: iter.fuse(), value: None, count: 0, - marker: PhantomData, + lifetime: PhantomData, + error: PhantomData, } } +} +impl<'de, I, E> MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, + E: de::Error, +{ /// Check for remaining elements after passing a `MapDeserializer` to /// `Visitor::visit_map`. pub fn end(mut self) -> Result<(), E> { @@ -664,13 +742,17 @@ impl MapDeserializer } 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))) + Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)),) } } +} - fn next_pair - (&mut self) - -> Option<(::First, ::Second)> { +impl<'de, I, E> MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, +{ + fn next_pair(&mut self) -> Option<(First, Second)> { match self.iter.next() { Some(kv) => { self.count += 1; @@ -681,58 +763,66 @@ impl MapDeserializer } } -impl de::Deserializer for MapDeserializer - where I: Iterator, - I::Item: private::Pair, - ::First: ValueDeserializer, - ::Second: ValueDeserializer, - E: de::Error +impl<'de, I, E> de::Deserializer<'de> for MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, + First: IntoDeserializer<'de, E>, + Second: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - fn deserialize(mut self, visitor: V_) -> Result - where V_: de::Visitor + fn deserialize_any(mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, { let value = try!(visitor.visit_map(&mut self)); try!(self.end()); Ok(value) } - fn deserialize_seq(mut self, visitor: V_) -> Result - where V_: de::Visitor + fn deserialize_seq(mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, { let value = try!(visitor.visit_seq(&mut self)); try!(self.end()); Ok(value) } - fn deserialize_seq_fixed_size(self, - _len: usize, - visitor: V_) - -> Result - where V_: de::Visitor + fn deserialize_tuple( + self, + len: usize, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { + let _ = len; self.deserialize_seq(visitor) } - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - bytes map unit_struct newtype_struct tuple_struct struct struct_field - tuple enum ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct tuple_struct map struct + enum identifier ignored_any } } -impl de::MapVisitor for MapDeserializer - where I: Iterator, - I::Item: private::Pair, - ::First: ValueDeserializer, - ::Second: ValueDeserializer, - E: de::Error +impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, + First: IntoDeserializer<'de, E>, + Second: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - fn visit_key_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed + fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { @@ -743,22 +833,25 @@ impl de::MapVisitor for MapDeserializer } } - fn visit_value_seed(&mut self, seed: T) -> Result - where T: de::DeserializeSeed + fn next_value_seed(&mut self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, { 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"); + let value = value.expect("MapAccess::visit_value called before visit_key"); seed.deserialize(value.into_deserializer()) } - fn visit_seed(&mut self, - kseed: TK, - vseed: TV) - -> Result, Self::Error> - where TK: de::DeserializeSeed, - TV: de::DeserializeSeed + fn next_entry_seed( + &mut self, + kseed: TK, + vseed: TV, + ) -> Result, Self::Error> + where + TK: de::DeserializeSeed<'de>, + TV: de::DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { @@ -770,22 +863,24 @@ impl de::MapVisitor for MapDeserializer } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } -impl de::SeqVisitor for MapDeserializer - where I: Iterator, - I::Item: private::Pair, - ::First: ValueDeserializer, - ::Second: ValueDeserializer, - E: de::Error +impl<'de, I, E> de::SeqAccess<'de> for MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, + First: IntoDeserializer<'de, E>, + Second: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - fn visit_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, { match self.next_pair() { Some((k, v)) => { @@ -796,51 +891,91 @@ impl de::SeqVisitor for MapDeserializer } } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) } } -// Used in the `impl SeqVisitor for MapDeserializer` to visit the map as a +// Cannot #[derive(Clone)] because of the bound `Second: Clone`. +impl<'de, I, E> Clone for MapDeserializer<'de, I, E> +where + I: Iterator + Clone, + I::Item: private::Pair, + Second: Clone, +{ + fn clone(&self) -> Self { + MapDeserializer { + iter: self.iter.clone(), + value: self.value.clone(), + count: self.count, + lifetime: self.lifetime, + error: self.error, + } + } +} + +// Cannot #[derive(Debug)] because of the bound `Second: Debug`. +impl<'de, I, E> Debug for MapDeserializer<'de, I, E> +where + I: Iterator + Debug, + I::Item: private::Pair, + Second: Debug, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.debug_struct("MapDeserializer") + .field("iter", &self.iter) + .field("value", &self.value) + .field("count", &self.count) + .field("lifetime", &self.lifetime) + .field("error", &self.error) + .finish() + } +} + +// Used in the `impl SeqAccess for MapDeserializer` to visit the map as a // sequence of pairs. struct PairDeserializer(A, B, PhantomData); -impl de::Deserializer for PairDeserializer - where A: ValueDeserializer, - B: ValueDeserializer, - E: de::Error +impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer +where + A: IntoDeserializer<'de, E>, + B: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - bytes map unit_struct newtype_struct tuple_struct struct struct_field - tuple enum ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct tuple_struct map struct + enum identifier ignored_any } - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_seq(self, visitor: V) -> Result - where V: de::Visitor + where + V: de::Visitor<'de>, { let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData); let pair = try!(visitor.visit_seq(&mut pair_visitor)); if pair_visitor.1.is_none() { Ok(pair) } else { - let remaining = pair_visitor.size_hint().0; + let remaining = pair_visitor.size_hint().unwrap(); // 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))) } } - fn deserialize_seq_fixed_size(self, len: usize, visitor: V) -> Result - where V: de::Visitor + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, { if len == 2 { self.deserialize_seq(visitor) @@ -854,15 +989,17 @@ impl de::Deserializer for PairDeserializer struct PairVisitor(Option, Option, PhantomData); -impl de::SeqVisitor for PairVisitor - where A: ValueDeserializer, - B: ValueDeserializer, - E: de::Error +impl<'de, A, B, E> de::SeqAccess<'de> for PairVisitor +where + A: IntoDeserializer<'de, E>, + B: IntoDeserializer<'de, E>, + E: de::Error, { type Error = E; - fn visit_seed(&mut self, seed: T) -> Result, Self::Error> - where T: de::DeserializeSeed + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, { if let Some(k) = self.0.take() { seed.deserialize(k.into_deserializer()).map(Some) @@ -873,15 +1010,14 @@ impl de::SeqVisitor for PairVisitor } } - fn size_hint(&self) -> (usize, Option) { - let len = if self.0.is_some() { - 2 + fn size_hint(&self) -> Option { + if self.0.is_some() { + Some(2) } else if self.1.is_some() { - 1 + Some(1) } else { - 0 - }; - (len, Some(len)) + Some(0) + } } } @@ -897,15 +1033,16 @@ impl Expected for ExpectedInMap { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "collections"))] -impl ValueDeserializer for BTreeMap - where K: ValueDeserializer + Eq + Ord, - V: ValueDeserializer, - E: de::Error +impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap +where + K: IntoDeserializer<'de, E> + Eq + Ord, + V: IntoDeserializer<'de, E>, + E: de::Error, { - type Deserializer = MapDeserializer, E>; + type Deserializer = MapDeserializer<'de, as IntoIterator>::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { MapDeserializer::new(self.into_iter()) @@ -913,143 +1050,62 @@ impl ValueDeserializer for BTreeMap } #[cfg(feature = "std")] -impl ValueDeserializer for HashMap - where K: ValueDeserializer + Eq + Hash, - V: ValueDeserializer, - E: de::Error +impl<'de, K, V, E> IntoDeserializer<'de, E> for HashMap +where + K: IntoDeserializer<'de, E> + Eq + Hash, + V: IntoDeserializer<'de, E>, + E: de::Error, { - type Deserializer = MapDeserializer, E>; + type Deserializer = MapDeserializer<'de, as IntoIterator>::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { MapDeserializer::new(self.into_iter()) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -/// A helper deserializer that deserializes a map using a `MapVisitor`. -pub struct MapVisitorDeserializer { - visitor: V_, - marker: PhantomData, +/// A deserializer holding a `MapAccess`. +#[derive(Clone, Debug)] +pub struct MapAccessDeserializer { + map: A, } -impl MapVisitorDeserializer - where V_: de::MapVisitor, - E: de::Error -{ - /// Construct a new `MapVisitorDeserializer`. - pub fn new(visitor: V_) -> Self { - MapVisitorDeserializer { - visitor: visitor, - marker: PhantomData, - } +impl MapAccessDeserializer { + /// Construct a new `MapAccessDeserializer`. + pub fn new(map: A) -> Self { + MapAccessDeserializer { map: map } } } -impl de::Deserializer for MapVisitorDeserializer - where V_: de::MapVisitor, - E: de::Error +impl<'de, A> de::Deserializer<'de> for MapAccessDeserializer +where + A: de::MapAccess<'de>, { - type Error = E; + type Error = A::Error; - fn deserialize(self, visitor: V) -> Result { - visitor.visit_map(self.visitor) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple enum ignored_any byte_buf - } -} - -/////////////////////////////////////////////////////////////////////////////// - -impl<'a, E> ValueDeserializer for bytes::Bytes<'a> - where E: de::Error -{ - type Deserializer = BytesDeserializer<'a, E>; - - fn into_deserializer(self) -> BytesDeserializer<'a, E> { - BytesDeserializer { - value: self.into(), - marker: PhantomData, - } - } -} - -/// A helper deserializer that deserializes a `&[u8]`. -pub struct BytesDeserializer<'a, E> { - value: &'a [u8], - marker: PhantomData, -} - -impl<'a, E> de::Deserializer for BytesDeserializer<'a, E> - where E: de::Error -{ - type Error = E; - - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, { - visitor.visit_bytes(self.value) + visitor.visit_map(self.map) } - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple enum ignored_any byte_buf + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum identifier ignored_any } } -/////////////////////////////////////////////////////////////////////////////// - -#[cfg(any(feature = "std", feature = "collections"))] -impl ValueDeserializer for bytes::ByteBuf - where E: de::Error -{ - type Deserializer = ByteBufDeserializer; - - fn into_deserializer(self) -> Self::Deserializer { - ByteBufDeserializer { - value: self.into(), - marker: PhantomData, - } - } -} - -/// A helper deserializer that deserializes a `Vec`. -#[cfg(any(feature = "std", feature = "collections"))] -pub struct ByteBufDeserializer { - value: Vec, - marker: PhantomData, -} - -#[cfg(any(feature = "std", feature = "collections"))] -impl de::Deserializer for ByteBufDeserializer - where E: de::Error -{ - type Error = E; - - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor - { - visitor.visit_byte_buf(self.value) - } - - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option - seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct - struct struct_field tuple enum ignored_any byte_buf - } -} - -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// mod private { - use de::{self, Unexpected}; - use core::marker::PhantomData; + use lib::*; + use de::{self, Unexpected}; + + #[derive(Clone, Debug)] pub struct UnitOnly { marker: PhantomData, } @@ -1058,34 +1114,39 @@ mod private { (t, UnitOnly { marker: PhantomData }) } - impl de::VariantVisitor for UnitOnly - where E: de::Error + impl<'de, E> de::VariantAccess<'de> for UnitOnly + where + E: de::Error, { type Error = E; - fn visit_unit(self) -> Result<(), Self::Error> { + fn unit_variant(self) -> Result<(), Self::Error> { Ok(()) } - fn visit_newtype_seed(self, _seed: T) -> Result - where T: de::DeserializeSeed + fn newtype_variant_seed(self, _seed: T) -> Result + where + T: de::DeserializeSeed<'de>, { - Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant")) + Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"),) } - fn visit_tuple(self, _len: usize, _visitor: V) -> Result - where V: de::Visitor + fn tuple_variant(self, _len: usize, _visitor: V) -> Result + where + V: de::Visitor<'de>, { - Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant")) + Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"),) } - fn visit_struct(self, - _fields: &'static [&'static str], - _visitor: V) - -> Result - where V: de::Visitor + fn struct_variant( + self, + _fields: &'static [&'static str], + _visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { - Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant")) + Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"),) } } @@ -1104,4 +1165,7 @@ mod private { self } } + + pub type First = ::First; + pub type Second = ::Second; } 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/export.rs b/serde/src/export.rs index c4fd3c68..bf017bbd 100644 --- a/serde/src/export.rs +++ b/serde/src/export.rs @@ -1,36 +1,41 @@ -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::String; - -#[cfg(feature = "std")] -use std::borrow::Cow; -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::borrow::Cow; - -pub use core::clone::Clone; -pub use core::convert::{From, Into}; -pub use core::default::Default; -pub use core::fmt; -pub use core::marker::PhantomData; -pub use core::option::Option::{self, None, Some}; -pub use core::result::Result::{self, Ok, Err}; - -#[cfg(any(feature = "collections", feature = "std"))] -pub fn from_utf8_lossy(bytes: &[u8]) -> Cow { - String::from_utf8_lossy(bytes) -} - -// The generated code calls this like: +// Copyright 2017 Serde Developers // -// let value = &_serde::export::from_utf8_lossy(bytes); -// Err(_serde::de::Error::unknown_variant(value, VARIANTS)) -// -// so it is okay for the return type to be different from the std case as long -// as the above works. -#[cfg(not(any(feature = "collections", feature = "std")))] -pub fn from_utf8_lossy(bytes: &[u8]) -> &str { - use core::str; - // Three unicode replacement characters if it fails. They look like a - // white-on-black question mark. The user will recognize it as invalid - // UTF-8. - str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}") +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use lib::clone::Clone; +pub use lib::convert::{From, Into}; +pub use lib::default::Default; +pub use lib::fmt::{self, Formatter}; +pub use lib::marker::PhantomData; +pub use lib::option::Option::{self, None, Some}; +pub use lib::result::Result::{self, Ok, Err}; + +pub use self::string::from_utf8_lossy; + +mod string { + use lib::*; + + #[cfg(any(feature = "std", feature = "collections"))] + pub fn from_utf8_lossy(bytes: &[u8]) -> Cow { + String::from_utf8_lossy(bytes) + } + + // The generated code calls this like: + // + // let value = &_serde::export::from_utf8_lossy(bytes); + // Err(_serde::de::Error::unknown_variant(value, VARIANTS)) + // + // so it is okay for the return type to be different from the std case as long + // as the above works. + #[cfg(not(any(feature = "std", feature = "collections")))] + pub fn from_utf8_lossy(bytes: &[u8]) -> &str { + // Three unicode replacement characters if it fails. They look like a + // white-on-black question mark. The user will recognize it as invalid + // UTF-8. + str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}") + } } diff --git a/serde/src/iter.rs b/serde/src/iter.rs deleted file mode 100644 index 784fe9bc..00000000 --- a/serde/src/iter.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Module that contains helper iterators. - -use std::io; -use std::iter::Peekable; - -/// Iterator over a byte stream that tracks the current position's line and column. -pub struct LineColIterator>> { - iter: Iter, - line: usize, - col: usize, -} - -impl>> LineColIterator { - /// Construct a new `LineColIterator`. - pub fn new(iter: Iter) -> LineColIterator { - LineColIterator { - iter: iter, - line: 1, - col: 0, - } - } - - /// Report the current line inside the iterator. - pub fn line(&self) -> usize { - self.line - } - - /// Report the current column inside the iterator. - pub fn col(&self) -> usize { - self.col - } - - /// Gets a reference to the underlying iterator. - pub fn get_ref(&self) -> &Iter { - &self.iter - } - - /// Gets a mutable reference to the underlying iterator. - pub fn get_mut(&mut self) -> &mut Iter { - &mut self.iter - } - - /// Unwraps this `LineColIterator`, returning the underlying iterator. - pub fn into_inner(self) -> Iter { - self.iter - } -} - -impl>> LineColIterator> { - /// peeks at the next value - pub fn peek(&mut self) -> Option<&io::Result> { - self.iter.peek() - } -} - -impl>> Iterator for LineColIterator { - type Item = io::Result; - fn next(&mut self) -> Option> { - match self.iter.next() { - None => None, - Some(Ok(b'\n')) => { - self.line += 1; - self.col = 0; - Some(Ok(b'\n')) - } - Some(Ok(c)) => { - self.col += 1; - Some(Ok(c)) - } - Some(Err(e)) => Some(Err(e)), - } - } -} diff --git a/serde/src/lib.rs b/serde/src/lib.rs index cfd2f7d0..c97339d4 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! # Serde //! //! Serde is a framework for ***ser***ializing and ***de***serializing Rust data @@ -9,63 +17,92 @@ //! these two groups interact with each other, allowing any supported data //! structure to be serialized and deserialized using any supported data format. //! -//! See the Serde website https://serde.rs/ for additional documentation and +//! See the Serde website [https://serde.rs/] for additional documentation and //! usage examples. //! -//! ### Design +//! [https://serde.rs/]: https://serde.rs/ +//! +//! ## Design //! //! Where many other languages rely on runtime reflection for serializing data, //! Serde is instead built on Rust's powerful trait system. A data structure //! that knows how to serialize and deserialize itself is one that implements -//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code -//! generation to automatically derive implementations at compile time). This +//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive +//! attribute to automatically generate implementations at compile time). This //! avoids any overhead of reflection or runtime type information. In fact in //! many situations the interaction between data structure and data format can //! be completely optimized away by the Rust compiler, leaving Serde -//! serialization to perform roughly the same speed as a handwritten serializer -//! for the specific selection of data structure and data format. +//! serialization to perform the same speed as a handwritten serializer for the +//! specific selection of data structure and data format. //! -//! ### Data formats +//! ## Data formats //! //! The following is a partial list of data formats that have been implemented //! for Serde by the community. //! -//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object -//! Notation used by many HTTP APIs. -//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format +//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs. +//! - [Bincode], a compact binary format //! used for IPC within the Servo rendering engine. -//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object -//! Representation designed for small message size without the need for -//! version negotiation. -//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly -//! configuration language that ain't markup language. -//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary -//! format that resembles a compact JSON. -//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration -//! format used by [Cargo](http://doc.crates.io/manifest.html). -//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in -//! the Python world. -//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed -//! to be readable and writable by humans. -//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network -//! transfer format used by MongoDB. -//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded -//! format. -//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C -//! standard. *(deserialization only)* -//! - [Envy](https://github.com/softprops/envy), a way to deserialize -//! environment variables into Rust structs. *(deserialization only)* -//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from -//! Redis when using [redis-rs](https://crates.io/crates/redis). +//! - [CBOR], a Concise Binary Object Representation designed for small message +//! size without the need for version negotiation. +//! - [YAML], a popular human-friendly configuration language that ain't markup +//! language. +//! - [MessagePack], an efficient binary format that resembles a compact JSON. +//! - [TOML], a minimal configuration format used by [Cargo]. +//! - [Pickle], a format common in the Python world. +//! - [Hjson], a variant of JSON designed to be readable and writable by humans. +//! - [BSON], the data storage and network transfer format used by MongoDB. +//! - [URL], the x-www-form-urlencoded format. +//! - [XML], the flexible machine-friendly W3C standard. //! *(deserialization only)* +//! - [Envy], a way to deserialize environment variables into Rust structs. +//! *(deserialization only)* +//! - [Redis], deserialize values from Redis when using [redis-rs]. +//! *(deserialization only)* +//! +//! [JSON]: https://github.com/serde-rs/json +//! [Bincode]: https://github.com/TyOverby/bincode +//! [CBOR]: https://github.com/pyfisch/cbor +//! [YAML]: https://github.com/dtolnay/serde-yaml +//! [MessagePack]: https://github.com/3Hren/msgpack-rust +//! [TOML]: https://github.com/alexcrichton/toml-rs +//! [Pickle]: https://github.com/birkenfeld/serde-pickle +//! [Hjson]: https://github.com/laktak/hjson-rust +//! [BSON]: https://github.com/zonyitoo/bson-rs +//! [URL]: https://github.com/nox/serde_urlencoded +//! [XML]: https://github.com/RReverser/serde-xml-rs +//! [Envy]: https://github.com/softprops/envy +//! [Redis]: https://github.com/OneSignal/serde-redis +//! [Cargo]: http://doc.crates.io/manifest.html +//! [redis-rs]: https://crates.io/crates/redis -#![doc(html_root_url="https://docs.serde.rs")] +//////////////////////////////////////////////////////////////////////////////// + +// Serde types in rustdoc of other crates get linked to here. +#![doc(html_root_url = "https://docs.rs/serde/0.9.13")] + +// Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one, into_boxed_c_str))] + +// Unstable functionality only if the user asks for it. For tracking and +// discussion of these features please refer to this issue: +// +// https://github.com/serde-rs/serde/issues/812 +#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one))] +#![cfg_attr(all(feature = "std", feature = "unstable"), feature(into_boxed_c_str))] #![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "collections", feature(collections))] -#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))] -#![deny(missing_docs)] + +// Whitelisted clippy lints. +#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))] +#![cfg_attr(feature = "cargo-clippy", allow(linkedlist))] +#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))] +#![cfg_attr(feature = "cargo-clippy", allow(zero_prefixed_literal))] + +// Blacklisted Rust lints. +#![deny(missing_docs, unused_imports)] + +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "collections")] extern crate collections; @@ -73,40 +110,115 @@ extern crate collections; #[cfg(feature = "alloc")] extern crate alloc; -#[cfg(feature = "unstable")] -extern crate core as actual_core; +#[cfg(all(feature = "unstable", feature = "std"))] +extern crate core; + +/// A facade around all the types we need from the `std`, `core`, `alloc`, and +/// `collections` crates. This avoids elaborate import wrangling having to +/// happen in every module. +mod lib { + mod core { + #[cfg(feature = "std")] + pub use std::*; + #[cfg(not(feature = "std"))] + pub use core::*; + } + + pub use self::core::{cmp, iter, mem, ops, str}; + pub use self::core::{i8, i16, i32, i64, isize}; + pub use self::core::{u8, u16, u32, u64, usize}; + pub use self::core::{f32, f64}; + + pub use self::core::cell::{Cell, RefCell}; + pub use self::core::clone::{self, Clone}; + pub use self::core::convert::{self, From, Into}; + pub use self::core::default::{self, Default}; + pub use self::core::fmt::{self, Debug, Display}; + pub use self::core::marker::{self, PhantomData}; + pub use self::core::option::{self, Option}; + pub use self::core::result::{self, Result}; + + #[cfg(feature = "std")] + pub use std::borrow::{Cow, ToOwned}; + #[cfg(all(feature = "collections", not(feature = "std")))] + pub use collections::borrow::{Cow, ToOwned}; + + #[cfg(feature = "std")] + pub use std::string::String; + #[cfg(all(feature = "collections", not(feature = "std")))] + pub use collections::string::{String, ToString}; + + #[cfg(feature = "std")] + pub use std::vec::Vec; + #[cfg(all(feature = "collections", not(feature = "std")))] + pub use collections::vec::Vec; + + #[cfg(feature = "std")] + pub use std::boxed::Box; + #[cfg(all(feature = "alloc", not(feature = "std")))] + pub use alloc::boxed::Box; + + #[cfg(all(feature = "rc", feature = "std"))] + pub use std::rc::Rc; + #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] + pub use alloc::rc::Rc; + + #[cfg(all(feature = "rc", feature = "std"))] + pub use std::sync::Arc; + #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] + pub use alloc::arc::Arc; + + #[cfg(feature = "std")] + pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; + #[cfg(all(feature = "collections", not(feature = "std")))] + pub use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; + + #[cfg(feature = "std")] + pub use std::{error, net}; + + #[cfg(feature = "std")] + pub use std::collections::{HashMap, HashSet}; + #[cfg(feature = "std")] + pub use std::ffi::{CString, CStr, OsString, OsStr}; + #[cfg(feature = "std")] + pub use std::hash::{Hash, BuildHasher}; + #[cfg(feature = "std")] + pub use std::io::Write; + #[cfg(feature = "std")] + pub use std::path::{Path, PathBuf}; + #[cfg(feature = "std")] + pub use std::time::Duration; + #[cfg(feature = "std")] + pub use std::sync::{Mutex, RwLock}; -#[cfg(feature = "std")] -mod core { - pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize, - usize, f32, f64, char, str, num, slice, iter, cell, default, result, option, - clone, convert}; #[cfg(feature = "unstable")] - pub use actual_core::nonzero; + pub use core::nonzero::{NonZero, Zeroable}; + #[cfg(feature = "unstable")] + #[allow(deprecated)] // required for impl Deserialize for NonZero + pub use core::num::Zero; } +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +mod macros; + +pub mod ser; +pub mod de; + #[doc(inline)] pub use ser::{Serialize, Serializer}; #[doc(inline)] pub use de::{Deserialize, Deserializer}; -#[macro_use] -mod macros; - -pub mod bytes; -pub mod de; -#[cfg(feature = "std")] -#[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. #[doc(hidden)] pub mod export; +// Helpers used by generated code and doc tests. Not public API. +#[doc(hidden)] +pub mod private; + // Re-export #[derive(Serialize, Deserialize)]. // // This is a workaround for https://github.com/rust-lang/cargo/issues/1286. diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 0a83a131..2a3d0872 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -1,107 +1,10 @@ -#[doc(hidden)] -#[macro_export] -macro_rules! forward_to_deserialize_method { - ($func:ident($($arg:ty),*)) => { - #[inline] - fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> $crate::export::Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor - { - self.deserialize(visitor) - } - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! forward_to_deserialize_helper { - (bool) => { - forward_to_deserialize_method!{deserialize_bool()} - }; - (u8) => { - forward_to_deserialize_method!{deserialize_u8()} - }; - (u16) => { - forward_to_deserialize_method!{deserialize_u16()} - }; - (u32) => { - forward_to_deserialize_method!{deserialize_u32()} - }; - (u64) => { - forward_to_deserialize_method!{deserialize_u64()} - }; - (i8) => { - forward_to_deserialize_method!{deserialize_i8()} - }; - (i16) => { - forward_to_deserialize_method!{deserialize_i16()} - }; - (i32) => { - forward_to_deserialize_method!{deserialize_i32()} - }; - (i64) => { - forward_to_deserialize_method!{deserialize_i64()} - }; - (f32) => { - forward_to_deserialize_method!{deserialize_f32()} - }; - (f64) => { - forward_to_deserialize_method!{deserialize_f64()} - }; - (char) => { - forward_to_deserialize_method!{deserialize_char()} - }; - (str) => { - forward_to_deserialize_method!{deserialize_str()} - }; - (string) => { - forward_to_deserialize_method!{deserialize_string()} - }; - (unit) => { - forward_to_deserialize_method!{deserialize_unit()} - }; - (option) => { - forward_to_deserialize_method!{deserialize_option()} - }; - (seq) => { - forward_to_deserialize_method!{deserialize_seq()} - }; - (seq_fixed_size) => { - forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)} - }; - (bytes) => { - forward_to_deserialize_method!{deserialize_bytes()} - }; - (byte_buf) => { - forward_to_deserialize_method!{deserialize_byte_buf()} - }; - (map) => { - forward_to_deserialize_method!{deserialize_map()} - }; - (unit_struct) => { - forward_to_deserialize_method!{deserialize_unit_struct(&'static str)} - }; - (newtype_struct) => { - forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)} - }; - (tuple_struct) => { - forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)} - }; - (struct) => { - forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])} - }; - (struct_field) => { - forward_to_deserialize_method!{deserialize_struct_field()} - }; - (tuple) => { - forward_to_deserialize_method!{deserialize_tuple(usize)} - }; - (enum) => { - forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])} - }; - (ignored_any) => { - forward_to_deserialize_method!{deserialize_ignored_any()} - }; -} +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. // Super explicit first paragraph because this shows up at the top level and // trips up people who are just looking for basic Serialize / Deserialize @@ -110,98 +13,230 @@ macro_rules! forward_to_deserialize_helper { /// Helper macro when implementing the `Deserializer` part of a new data format /// for Serde. /// -/// Some `Deserializer` implementations for self-describing formats do not care -/// what hint the `Visitor` gives them, they just want to blindly call the -/// `Visitor` method corresponding to the data they can tell is in the input. -/// This requires repetitive implementations of all the `Deserializer` trait -/// methods. +/// Some [`Deserializer`] implementations for self-describing formats do not +/// care what hint the [`Visitor`] gives them, they just want to blindly call +/// the [`Visitor`] method corresponding to the data they can tell is in the +/// input. This requires repetitive implementations of all the [`Deserializer`] +/// trait methods. /// /// ```rust -/// # #[macro_use] extern crate serde; +/// # #[macro_use] +/// # extern crate serde; +/// # /// # use serde::de::{value, Deserializer, Visitor}; -/// # pub struct MyDeserializer; -/// # impl Deserializer for MyDeserializer { +/// # +/// # struct MyDeserializer; +/// # +/// # impl<'de> Deserializer<'de> for MyDeserializer { /// # type Error = value::Error; -/// # fn deserialize(self, _: V) -> Result -/// # where V: Visitor -/// # { unimplemented!() } +/// # +/// # fn deserialize_any(self, _: V) -> Result +/// # where V: Visitor<'de> +/// # { +/// # unimplemented!() +/// # } /// # /// #[inline] /// fn deserialize_bool(self, visitor: V) -> Result -/// where V: Visitor +/// where V: Visitor<'de> /// { -/// self.deserialize(visitor) +/// self.deserialize_any(visitor) /// } -/// # forward_to_deserialize! { -/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option -/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct -/// # tuple_struct struct struct_field tuple enum ignored_any +/// # +/// # forward_to_deserialize_any! { +/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes +/// # byte_buf option unit unit_struct newtype_struct seq tuple +/// # tuple_struct map struct enum identifier ignored_any /// # } /// # } +/// # /// # fn main() {} /// ``` /// -/// The `forward_to_deserialize!` macro implements these simple forwarding -/// methods so that they forward directly to `Deserializer::deserialize`. You -/// can choose which methods to forward. +/// The `forward_to_deserialize_any!` macro implements these simple forwarding +/// methods so that they forward directly to [`Deserializer::deserialize_any`]. +/// You can choose which methods to forward. /// /// ```rust -/// # #[macro_use] extern crate serde; +/// # #[macro_use] +/// # extern crate serde; +/// # /// # use serde::de::{value, Deserializer, Visitor}; -/// # pub struct MyDeserializer; -/// impl Deserializer for MyDeserializer { +/// # +/// # struct MyDeserializer; +/// # +/// impl<'de> Deserializer<'de> for MyDeserializer { /// # type Error = value::Error; -/// fn deserialize(self, visitor: V) -> Result -/// where V: Visitor +/// # +/// fn deserialize_any(self, visitor: V) -> Result +/// where V: Visitor<'de> /// { /// /* ... */ /// # let _ = visitor; /// # unimplemented!() /// } /// -/// forward_to_deserialize! { -/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option -/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct -/// tuple_struct struct struct_field tuple enum ignored_any +/// forward_to_deserialize_any! { +/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes +/// byte_buf option unit unit_struct newtype_struct seq tuple +/// tuple_struct map struct enum identifier ignored_any /// } /// } +/// # /// # fn main() {} /// ``` +/// +/// The macro assumes the convention that your `Deserializer` lifetime parameter +/// is called `'de` and that the `Visitor` type parameters on each method are +/// called `V`. A different type parameter and a different lifetime can be +/// specified explicitly if necessary. +/// +/// ```rust +/// # #[macro_use] +/// # extern crate serde; +/// # +/// # use std::marker::PhantomData; +/// # +/// # use serde::de::{value, Deserializer, Visitor}; +/// # +/// # struct MyDeserializer(PhantomData); +/// # +/// # impl<'q, V> Deserializer<'q> for MyDeserializer { +/// # type Error = value::Error; +/// # +/// # fn deserialize_any(self, visitor: W) -> Result +/// # where W: Visitor<'q> +/// # { +/// # unimplemented!() +/// # } +/// # +/// forward_to_deserialize_any! { +/// > +/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes +/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct +/// map struct enum identifier ignored_any +/// } +/// # } +/// # +/// # fn main() {} +/// ``` +/// +/// [`Deserializer`]: trait.Deserializer.html +/// [`Visitor`]: de/trait.Visitor.html +/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any #[macro_export] -macro_rules! forward_to_deserialize { +macro_rules! forward_to_deserialize_any { + (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { + $(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})* + }; + // This case must be after the previous one. ($($func:ident)*) => { - $(forward_to_deserialize_helper!{$func})* + $(forward_to_deserialize_any_helper!{$func<'de, V>})* }; } -/// Seralize the `$value` that implements Display as a string, -/// when that string is statically known to never have more than -/// a constant `$MAX_LEN` bytes. -/// -/// Panics if the Display impl tries to write more than `$MAX_LEN` bytes. -#[cfg(feature = "std")] -// Not exported -macro_rules! serialize_display_bounded_length { - ($value: expr, $MAX_LEN: expr, $serializer: expr) => { +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_any_method { + ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => { + #[inline] + fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error> + where + $v: $crate::de::Visitor<$l>, { - use std::io::Write; - let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() }; - let remaining_len; - { - let mut remaining = &mut buffer[..]; - write!(remaining, "{}", $value).unwrap(); - remaining_len = remaining.len() - } - let written_len = buffer.len() - remaining_len; - let written = &buffer[..written_len]; - - // write! only provides std::fmt::Formatter to Display implementations, - // which has methods write_str and write_char but no method to write arbitrary bytes. - // Therefore, `written` is well-formed in UTF-8. - let written_str = unsafe { - ::std::str::from_utf8_unchecked(written) - }; - $serializer.serialize_str(written_str) + $( + let _ = $arg; + )* + self.deserialize_any(visitor) } - } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_any_helper { + (bool<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()} + }; + (i8<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_i8<$l, $v>()} + }; + (i16<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_i16<$l, $v>()} + }; + (i32<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_i32<$l, $v>()} + }; + (i64<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()} + }; + (u8<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()} + }; + (u16<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_u16<$l, $v>()} + }; + (u32<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_u32<$l, $v>()} + }; + (u64<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()} + }; + (f32<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()} + }; + (f64<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()} + }; + (char<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_char<$l, $v>()} + }; + (str<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_str<$l, $v>()} + }; + (string<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_string<$l, $v>()} + }; + (bytes<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_bytes<$l, $v>()} + }; + (byte_buf<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_byte_buf<$l, $v>()} + }; + (option<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_option<$l, $v>()} + }; + (unit<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_unit<$l, $v>()} + }; + (unit_struct<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_unit_struct<$l, $v>(name: &'static str)} + }; + (newtype_struct<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)} + }; + (seq<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_seq<$l, $v>()} + }; + (tuple<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_tuple<$l, $v>(len: usize)} + }; + (tuple_struct<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)} + }; + (map<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_map<$l, $v>()} + }; + (struct<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])} + }; + (enum<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])} + }; + (identifier<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_identifier<$l, $v>()} + }; + (ignored_any<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_ignored_any<$l, $v>()} + }; } diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs new file mode 100644 index 00000000..6666ada2 --- /dev/null +++ b/serde/src/private/de.rs @@ -0,0 +1,1849 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use lib::*; + +use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor}; + +#[cfg(any(feature = "std", feature = "collections"))] +use de::Unexpected; + +#[cfg(any(feature = "std", feature = "collections"))] +pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer, + TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor, + InternallyTaggedUnitVisitor, UntaggedUnitVisitor}; + +/// If the missing field is of type `Option` then treat is as `None`, +/// otherwise it is an error. +pub fn missing_field<'de, V, E>(field: &'static str) -> Result +where + V: Deserialize<'de>, + E: Error, +{ + struct MissingFieldDeserializer(&'static str, PhantomData); + + impl<'de, E> Deserializer<'de> for MissingFieldDeserializer + where + E: Error, + { + type Error = E; + + fn deserialize_any(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::missing_field(self.0)) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_none() + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map + struct enum identifier ignored_any + } + } + + let deserializer = MissingFieldDeserializer(field, PhantomData); + Deserialize::deserialize(deserializer) +} + +#[cfg(any(feature = "std", feature = "collections"))] +pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct CowStrVisitor; + + impl<'a> Visitor<'a> for CowStrVisitor { + type Value = Cow<'a, str>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.to_owned())) + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_string(self, v: String) -> Result + where + E: Error, + { + Ok(Cow::Owned(v)) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + match str::from_utf8(v) { + Ok(s) => Ok(Cow::Owned(s.to_owned())), + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), + } + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + match str::from_utf8(v) { + Ok(s) => Ok(Cow::Borrowed(s)), + Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), + } + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error, + { + match String::from_utf8(v) { + Ok(s) => Ok(Cow::Owned(s)), + Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),), + } + } + } + + deserializer.deserialize_str(CowStrVisitor) +} + +#[cfg(any(feature = "std", feature = "collections"))] +pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct CowBytesVisitor; + + impl<'a> Visitor<'a> for CowBytesVisitor { + type Value = Cow<'a, [u8]>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.as_bytes().to_vec())) + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, + { + Ok(Cow::Borrowed(v.as_bytes())) + } + + fn visit_string(self, v: String) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.into_bytes())) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + Ok(Cow::Owned(v.to_vec())) + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error, + { + Ok(Cow::Owned(v)) + } + } + + deserializer.deserialize_str(CowBytesVisitor) +} + +pub mod size_hint { + use lib::*; + + pub fn from_bounds(iter: &I) -> Option + where I: Iterator + { + helper(iter.size_hint()) + } + + pub fn cautious(hint: Option) -> usize { + cmp::min(hint.unwrap_or(0), 4096) + } + + fn helper(bounds: (usize, Option)) -> Option { + match bounds { + (lower, Some(upper)) if lower == upper => { + Some(upper) + } + _ => None, + } + } +} + +#[cfg(any(feature = "std", feature = "collections"))] +mod content { + // This module is private and nothing here should be used outside of + // generated code. + // + // We will iterate on the implementation for a few releases and only have to + // worry about backward compatibility for the `untagged` and `tag` attributes + // rather than for this entire mechanism. + // + // This issue is tracking making some of this stuff public: + // https://github.com/serde-rs/serde/issues/741 + + use lib::*; + + use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, MapAccess, + EnumAccess, Unexpected}; + use super::size_hint; + + /// Used from generated code to buffer the contents of the Deserializer when + /// deserializing untagged enums and internally tagged enums. + /// + /// Not public API. Use serde-value instead. + #[derive(Debug)] + pub enum Content { + Bool(bool), + + U8(u8), + U16(u16), + U32(u32), + U64(u64), + + I8(i8), + I16(i16), + I32(i32), + I64(i64), + + F32(f32), + F64(f64), + + Char(char), + String(String), + Bytes(Vec), + + None, + Some(Box), + + Unit, + Newtype(Box), + Seq(Vec), + Map(Vec<(Content, Content)>), + } + + impl Content { + fn unexpected(&self) -> Unexpected { + match *self { + Content::Bool(b) => Unexpected::Bool(b), + Content::U8(n) => Unexpected::Unsigned(n as u64), + Content::U16(n) => Unexpected::Unsigned(n as u64), + Content::U32(n) => Unexpected::Unsigned(n as u64), + Content::U64(n) => Unexpected::Unsigned(n), + Content::I8(n) => Unexpected::Signed(n as i64), + Content::I16(n) => Unexpected::Signed(n as i64), + Content::I32(n) => Unexpected::Signed(n as i64), + Content::I64(n) => Unexpected::Signed(n), + Content::F32(f) => Unexpected::Float(f as f64), + Content::F64(f) => Unexpected::Float(f), + Content::Char(c) => Unexpected::Char(c), + Content::String(ref s) => Unexpected::Str(s), + Content::Bytes(ref b) => Unexpected::Bytes(b), + Content::None | Content::Some(_) => Unexpected::Option, + Content::Unit => Unexpected::Unit, + Content::Newtype(_) => Unexpected::NewtypeStruct, + Content::Seq(_) => Unexpected::Seq, + Content::Map(_) => Unexpected::Map, + } + } + } + + impl<'de> Deserialize<'de> for Content { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Untagged and internally tagged enums are only supported in + // self-describing formats. + deserializer.deserialize_any(ContentVisitor) + } + } + + struct ContentVisitor; + + impl<'de> Visitor<'de> for ContentVisitor { + type Value = Content; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("any value") + } + + fn visit_bool(self, value: bool) -> Result + where + F: de::Error, + { + Ok(Content::Bool(value)) + } + + fn visit_i8(self, value: i8) -> Result + where + F: de::Error, + { + Ok(Content::I8(value)) + } + + fn visit_i16(self, value: i16) -> Result + where + F: de::Error, + { + Ok(Content::I16(value)) + } + + fn visit_i32(self, value: i32) -> Result + where + F: de::Error, + { + Ok(Content::I32(value)) + } + + fn visit_i64(self, value: i64) -> Result + where + F: de::Error, + { + Ok(Content::I64(value)) + } + + fn visit_u8(self, value: u8) -> Result + where + F: de::Error, + { + Ok(Content::U8(value)) + } + + fn visit_u16(self, value: u16) -> Result + where + F: de::Error, + { + Ok(Content::U16(value)) + } + + fn visit_u32(self, value: u32) -> Result + where + F: de::Error, + { + Ok(Content::U32(value)) + } + + fn visit_u64(self, value: u64) -> Result + where + F: de::Error, + { + Ok(Content::U64(value)) + } + + fn visit_f32(self, value: f32) -> Result + where + F: de::Error, + { + Ok(Content::F32(value)) + } + + fn visit_f64(self, value: f64) -> Result + where + F: de::Error, + { + Ok(Content::F64(value)) + } + + fn visit_char(self, value: char) -> Result + where + F: de::Error, + { + Ok(Content::Char(value)) + } + + fn visit_str(self, value: &str) -> Result + where + F: de::Error, + { + Ok(Content::String(value.into())) + } + + fn visit_string(self, value: String) -> Result + where + F: de::Error, + { + Ok(Content::String(value)) + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + F: de::Error, + { + Ok(Content::Bytes(value.into())) + } + + fn visit_byte_buf(self, value: Vec) -> Result + where + F: de::Error, + { + Ok(Content::Bytes(value)) + } + + fn visit_unit(self) -> Result + where + F: de::Error, + { + Ok(Content::Unit) + } + + fn visit_none(self) -> Result + where + F: de::Error, + { + Ok(Content::None) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v))) + } + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v))) + } + + fn visit_seq(self, mut visitor: V) -> Result + where + V: SeqAccess<'de>, + { + let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); + while let Some(e) = try!(visitor.next_element()) { + vec.push(e); + } + Ok(Content::Seq(vec)) + } + + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'de>, + { + let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); + while let Some(kv) = try!(visitor.next_entry()) { + vec.push(kv); + } + Ok(Content::Map(vec)) + } + + fn visit_enum(self, _visitor: V) -> Result + where + V: EnumAccess<'de>, + { + Err(de::Error::custom("untagged and internally tagged enums do not support enum input",),) + } + } + + /// This is the type of the map keys in an internally tagged enum. + /// + /// Not public API. + pub enum TagOrContent { + Tag, + Content(Content), + } + + struct TagOrContentVisitor { + name: &'static str, + } + + impl TagOrContentVisitor { + fn new(name: &'static str) -> Self { + TagOrContentVisitor { name: name } + } + } + + impl<'de> DeserializeSeed<'de> for TagOrContentVisitor { + type Value = TagOrContent; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Internally tagged enums are only supported in self-describing + // formats. + deserializer.deserialize_any(self) + } + } + + impl<'de> Visitor<'de> for TagOrContentVisitor { + type Value = TagOrContent; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "a type tag `{}` or any other value", self.name) + } + + fn visit_bool(self, value: bool) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_bool(value) + .map(TagOrContent::Content) + } + + fn visit_i8(self, value: i8) -> Result + where + F: de::Error, + { + ContentVisitor.visit_i8(value).map(TagOrContent::Content) + } + + fn visit_i16(self, value: i16) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_i16(value) + .map(TagOrContent::Content) + } + + fn visit_i32(self, value: i32) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_i32(value) + .map(TagOrContent::Content) + } + + fn visit_i64(self, value: i64) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_i64(value) + .map(TagOrContent::Content) + } + + fn visit_u8(self, value: u8) -> Result + where + F: de::Error, + { + ContentVisitor.visit_u8(value).map(TagOrContent::Content) + } + + fn visit_u16(self, value: u16) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_u16(value) + .map(TagOrContent::Content) + } + + fn visit_u32(self, value: u32) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_u32(value) + .map(TagOrContent::Content) + } + + fn visit_u64(self, value: u64) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_u64(value) + .map(TagOrContent::Content) + } + + fn visit_f32(self, value: f32) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_f32(value) + .map(TagOrContent::Content) + } + + fn visit_f64(self, value: f64) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_f64(value) + .map(TagOrContent::Content) + } + + fn visit_char(self, value: char) -> Result + where + F: de::Error, + { + ContentVisitor + .visit_char(value) + .map(TagOrContent::Content) + } + + fn visit_str(self, value: &str) -> Result + where + F: de::Error, + { + if value == self.name { + Ok(TagOrContent::Tag) + } else { + ContentVisitor + .visit_str(value) + .map(TagOrContent::Content) + } + } + + fn visit_string(self, value: String) -> Result + where + F: de::Error, + { + if value == self.name { + Ok(TagOrContent::Tag) + } else { + ContentVisitor + .visit_string(value) + .map(TagOrContent::Content) + } + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + F: de::Error, + { + if value == self.name.as_bytes() { + Ok(TagOrContent::Tag) + } else { + ContentVisitor + .visit_bytes(value) + .map(TagOrContent::Content) + } + } + + fn visit_byte_buf(self, value: Vec) -> Result + where + F: de::Error, + { + if value == self.name.as_bytes() { + Ok(TagOrContent::Tag) + } else { + ContentVisitor + .visit_byte_buf(value) + .map(TagOrContent::Content) + } + } + + fn visit_unit(self) -> Result + where + F: de::Error, + { + ContentVisitor.visit_unit().map(TagOrContent::Content) + } + + fn visit_none(self) -> Result + where + F: de::Error, + { + ContentVisitor.visit_none().map(TagOrContent::Content) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + ContentVisitor + .visit_some(deserializer) + .map(TagOrContent::Content) + } + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + ContentVisitor + .visit_newtype_struct(deserializer) + .map(TagOrContent::Content) + } + + fn visit_seq(self, visitor: V) -> Result + where + V: SeqAccess<'de>, + { + ContentVisitor + .visit_seq(visitor) + .map(TagOrContent::Content) + } + + fn visit_map(self, visitor: V) -> Result + where + V: MapAccess<'de>, + { + ContentVisitor + .visit_map(visitor) + .map(TagOrContent::Content) + } + + fn visit_enum(self, visitor: V) -> Result + where + V: EnumAccess<'de>, + { + ContentVisitor + .visit_enum(visitor) + .map(TagOrContent::Content) + } + } + + /// Used by generated code to deserialize an internally tagged enum. + /// + /// Not public API. + pub struct TaggedContent { + pub tag: T, + pub content: Content, + } + + /// Not public API. + pub struct TaggedContentVisitor { + tag_name: &'static str, + tag: PhantomData, + } + + impl TaggedContentVisitor { + /// Visitor for the content of an internally tagged enum with the given tag + /// name. + pub fn new(name: &'static str) -> Self { + TaggedContentVisitor { + tag_name: name, + tag: PhantomData, + } + } + } + + impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor + where + T: Deserialize<'de>, + { + type Value = TaggedContent; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Internally tagged enums are only supported in self-describing + // formats. + deserializer.deserialize_any(self) + } + } + + impl<'de, T> Visitor<'de> for TaggedContentVisitor + where + T: Deserialize<'de>, + { + type Value = TaggedContent; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("any value") + } + + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'de>, + { + let mut tag = None; + let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); + while let Some(k) = + try!(visitor.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { + match k { + TagOrContent::Tag => { + if tag.is_some() { + return Err(de::Error::duplicate_field(self.tag_name)); + } + tag = Some(try!(visitor.next_value())); + } + TagOrContent::Content(k) => { + let v = try!(visitor.next_value()); + vec.push((k, v)); + } + } + } + match tag { + None => Err(de::Error::missing_field(self.tag_name)), + Some(tag) => { + Ok( + TaggedContent { + tag: tag, + content: Content::Map(vec), + }, + ) + } + } + } + } + + /// Used by generated code to deserialize an adjacently tagged enum. + /// + /// Not public API. + pub enum TagOrContentField { + Tag, + Content, + } + + /// Not public API. + pub struct TagOrContentFieldVisitor { + pub tag: &'static str, + pub content: &'static str, + } + + impl<'de> DeserializeSeed<'de> for TagOrContentFieldVisitor { + type Value = TagOrContentField; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(self) + } + } + + impl<'de> Visitor<'de> for TagOrContentFieldVisitor { + type Value = TagOrContentField; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "{:?} or {:?}", self.tag, self.content) + } + + fn visit_str(self, field: &str) -> Result + where + E: de::Error, + { + if field == self.tag { + Ok(TagOrContentField::Tag) + } else if field == self.content { + Ok(TagOrContentField::Content) + } else { + Err(de::Error::invalid_value(Unexpected::Str(field), &self)) + } + } + } + + /// Not public API + pub struct ContentDeserializer { + content: Content, + err: PhantomData, + } + + /// Used when deserializing an internally tagged enum because the content will + /// be used exactly once. + impl<'de, E> Deserializer<'de> for ContentDeserializer + where + E: de::Error, + { + type Error = E; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Bool(v) => visitor.visit_bool(v), + Content::U8(v) => visitor.visit_u8(v), + Content::U16(v) => visitor.visit_u16(v), + Content::U32(v) => visitor.visit_u32(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I8(v) => visitor.visit_i8(v), + Content::I16(v) => visitor.visit_i16(v), + Content::I32(v) => visitor.visit_i32(v), + Content::I64(v) => visitor.visit_i64(v), + Content::F32(v) => visitor.visit_f32(v), + Content::F64(v) => visitor.visit_f64(v), + Content::Char(v) => visitor.visit_char(v), + Content::String(v) => visitor.visit_string(v), + Content::Unit => visitor.visit_unit(), + Content::None => visitor.visit_none(), + Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), + Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)), + Content::Seq(v) => { + let seq = v.into_iter().map(ContentDeserializer::new); + let mut seq_visitor = de::value::SeqDeserializer::new(seq); + let value = try!(visitor.visit_seq(&mut seq_visitor)); + try!(seq_visitor.end()); + Ok(value) + } + Content::Map(v) => { + let map = v.into_iter().map(|(k, v)| { + (ContentDeserializer::new(k), + ContentDeserializer::new(v)) + }); + let mut map_visitor = de::value::MapDeserializer::new(map); + let value = try!(visitor.visit_map(&mut map_visitor)); + try!(map_visitor.end()); + Ok(value) + } + Content::Bytes(v) => visitor.visit_byte_buf(v), + } + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::None => visitor.visit_none(), + Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), + Content::Unit => visitor.visit_unit(), + _ => visitor.visit_some(self), + } + } + + fn deserialize_newtype_struct( + self, + _name: &str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let (variant, value) = match self.content { + Content::Map(value) => { + let mut iter = value.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err( + de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + ), + ); + } + }; + // enums are encoded in json as maps with a single key:value pair + if iter.next().is_some() { + return Err( + de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + ), + ); + } + (variant, Some(value)) + } + Content::String(variant) => (Content::String(variant), None), + other => { + return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),); + } + }; + + visitor.visit_enum( + EnumDeserializer { + variant: variant, + value: value, + err: PhantomData, + }, + ) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf unit unit_struct seq tuple tuple_struct map struct + identifier ignored_any + } + } + + impl ContentDeserializer { + /// private API, don't use + pub fn new(content: Content) -> Self { + ContentDeserializer { + content: content, + err: PhantomData, + } + } + } + + struct EnumDeserializer + where + E: de::Error, + { + variant: Content, + value: Option, + err: PhantomData, + } + + impl<'de, E> de::EnumAccess<'de> for EnumDeserializer + where + E: de::Error, + { + type Error = E; + type Variant = VariantDeserializer; + + fn variant_seed( + self, + seed: V, + ) -> Result<(V::Value, VariantDeserializer), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + let visitor = VariantDeserializer { + value: self.value, + err: PhantomData, + }; + seed.deserialize(ContentDeserializer::new(self.variant)) + .map(|v| (v, visitor)) + } + } + + struct VariantDeserializer + where + E: de::Error, + { + value: Option, + err: PhantomData, + } + + impl<'de, E> de::VariantAccess<'de> for VariantDeserializer + where + E: de::Error, + { + type Error = E; + + fn unit_variant(self) -> Result<(), E> { + match self.value { + Some(value) => de::Deserialize::deserialize(ContentDeserializer::new(value)), + None => Ok(()), + } + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(ContentDeserializer::new(value)), + None => { + Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),) + } + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(Content::Seq(v)) => { + de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) + } + Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),), + None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),), + } + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(Content::Map(v)) => { + de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor) + } + Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),), + _ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),), + } + } + } + + struct SeqDeserializer + where + E: de::Error, + { + iter: as IntoIterator>::IntoIter, + err: PhantomData, + } + + impl SeqDeserializer + where + E: de::Error, + { + fn new(vec: Vec) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + err: PhantomData, + } + } + } + + impl<'de, E> de::Deserializer<'de> for SeqDeserializer + where + E: de::Error, + { + type Error = E; + + #[inline] + fn deserialize_any(mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let len = self.iter.len(); + if len == 0 { + visitor.visit_unit() + } else { + let ret = try!(visitor.visit_seq(&mut self)); + let remaining = self.iter.len(); + if remaining == 0 { + Ok(ret) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in array")) + } + } + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } + } + + impl<'de, E> de::SeqAccess<'de> for SeqDeserializer + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => { + seed.deserialize(ContentDeserializer::new(value)) + .map(Some) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + struct MapDeserializer + where + E: de::Error, + { + iter: as IntoIterator>::IntoIter, + value: Option, + err: PhantomData, + } + + impl MapDeserializer + where + E: de::Error, + { + fn new(map: Vec<(Content, Content)>) -> Self { + MapDeserializer { + iter: map.into_iter(), + value: None, + err: PhantomData, + } + } + } + + impl<'de, E> de::MapAccess<'de> for MapDeserializer + where + E: de::Error, + { + type Error = E; + + fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, value)) => { + self.value = Some(value); + seed.deserialize(ContentDeserializer::new(key)).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value.take() { + Some(value) => seed.deserialize(ContentDeserializer::new(value)), + None => Err(de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + impl<'de, E> de::Deserializer<'de> for MapDeserializer + where + E: de::Error, + { + type Error = E; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_map(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } + } + + /// Not public API. + pub struct ContentRefDeserializer<'a, E> { + content: &'a Content, + err: PhantomData, + } + + /// Used when deserializing an untagged enum because the content may need to be + /// used more than once. + impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match *self.content { + Content::Bool(v) => visitor.visit_bool(v), + Content::U8(v) => visitor.visit_u8(v), + Content::U16(v) => visitor.visit_u16(v), + Content::U32(v) => visitor.visit_u32(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I8(v) => visitor.visit_i8(v), + Content::I16(v) => visitor.visit_i16(v), + Content::I32(v) => visitor.visit_i32(v), + Content::I64(v) => visitor.visit_i64(v), + Content::F32(v) => visitor.visit_f32(v), + Content::F64(v) => visitor.visit_f64(v), + Content::Char(v) => visitor.visit_char(v), + Content::String(ref v) => visitor.visit_str(v), + Content::Unit => visitor.visit_unit(), + Content::None => visitor.visit_none(), + Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), + Content::Newtype(ref v) => { + visitor.visit_newtype_struct(ContentRefDeserializer::new(v)) + } + Content::Seq(ref v) => { + let seq = v.into_iter().map(ContentRefDeserializer::new); + let mut seq_visitor = de::value::SeqDeserializer::new(seq); + let value = try!(visitor.visit_seq(&mut seq_visitor)); + try!(seq_visitor.end()); + Ok(value) + } + Content::Map(ref v) => { + let map = v.into_iter() + .map( + |&(ref k, ref v)| { + (ContentRefDeserializer::new(k), ContentRefDeserializer::new(v)) + }, + ); + let mut map_visitor = de::value::MapDeserializer::new(map); + let value = try!(visitor.visit_map(&mut map_visitor)); + try!(map_visitor.end()); + Ok(value) + } + Content::Bytes(ref v) => visitor.visit_bytes(v), + } + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match *self.content { + Content::None => visitor.visit_none(), + Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), + Content::Unit => visitor.visit_unit(), + _ => visitor.visit_some(self), + } + } + + fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let (variant, value) = match *self.content { + Content::Map(ref value) => { + let mut iter = value.into_iter(); + let &(ref variant, ref value) = match iter.next() { + Some(v) => v, + None => { + return Err( + de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + ), + ); + } + }; + // enums are encoded in json as maps with a single key:value pair + if iter.next().is_some() { + return Err( + de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + ), + ); + } + (variant, Some(value)) + } + ref s @ Content::String(_) => (s, None), + ref other => { + return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),); + } + }; + + visitor.visit_enum( + EnumRefDeserializer { + variant: variant, + value: value, + err: PhantomData, + }, + ) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf unit unit_struct seq tuple tuple_struct map struct + identifier ignored_any + } + } + + impl<'a, E> ContentRefDeserializer<'a, E> { + /// private API, don't use + pub fn new(content: &'a Content) -> Self { + ContentRefDeserializer { + content: content, + err: PhantomData, + } + } + } + + struct EnumRefDeserializer<'a, E> + where + E: de::Error, + { + variant: &'a Content, + value: Option<&'a Content>, + err: PhantomData, + } + + impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + type Variant = VariantRefDeserializer<'a, Self::Error>; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + let visitor = VariantRefDeserializer { + value: self.value, + err: PhantomData, + }; + seed.deserialize(ContentRefDeserializer::new(self.variant)) + .map(|v| (v, visitor)) + } + } + + struct VariantRefDeserializer<'a, E> + where + E: de::Error, + { + value: Option<&'a Content>, + err: PhantomData, + } + + impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + + fn unit_variant(self) -> Result<(), E> { + match self.value { + Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)), + None => Ok(()), + } + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), + None => { + Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),) + } + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(&Content::Seq(ref v)) => { + de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) + } + Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),), + None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),), + } + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self.value { + Some(&Content::Map(ref v)) => { + de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) + } + Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),), + _ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),), + } + } + } + + struct SeqRefDeserializer<'a, E> + where + E: de::Error, + { + iter: <&'a [Content] as IntoIterator>::IntoIter, + err: PhantomData, + } + + impl<'a, E> SeqRefDeserializer<'a, E> + where + E: de::Error, + { + fn new(vec: &'a [Content]) -> Self { + SeqRefDeserializer { + iter: vec.into_iter(), + err: PhantomData, + } + } + } + + impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + + #[inline] + fn deserialize_any(mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let len = self.iter.len(); + if len == 0 { + visitor.visit_unit() + } else { + let ret = try!(visitor.visit_seq(&mut self)); + let remaining = self.iter.len(); + if remaining == 0 { + Ok(ret) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in array")) + } + } + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } + } + + impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => { + seed.deserialize(ContentRefDeserializer::new(value)) + .map(Some) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + struct MapRefDeserializer<'a, E> + where + E: de::Error, + { + iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter, + value: Option<&'a Content>, + err: PhantomData, + } + + impl<'a, E> MapRefDeserializer<'a, E> + where + E: de::Error, + { + fn new(map: &'a [(Content, Content)]) -> Self { + MapRefDeserializer { + iter: map.into_iter(), + value: None, + err: PhantomData, + } + } + } + + impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + + fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(&(ref key, ref value)) => { + self.value = Some(value); + seed.deserialize(ContentRefDeserializer::new(key)) + .map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + match self.value.take() { + Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), + None => Err(de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> + where + E: de::Error, + { + type Error = E; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_map(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } + } + + impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer + where + E: de::Error, + { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } + } + + impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, E> + where + E: de::Error, + { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } + } + + /// Visitor for deserializing an internally tagged unit variant. + /// + /// Not public API. + pub struct InternallyTaggedUnitVisitor<'a> { + type_name: &'a str, + variant_name: &'a str, + } + + impl<'a> InternallyTaggedUnitVisitor<'a> { + /// Not public API. + pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { + InternallyTaggedUnitVisitor { + type_name: type_name, + variant_name: variant_name, + } + } + } + + impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name) + } + + fn visit_map(self, _: V) -> Result<(), V::Error> + where + V: MapAccess<'de>, + { + Ok(()) + } + } + + /// Visitor for deserializing an untagged unit variant. + /// + /// Not public API. + pub struct UntaggedUnitVisitor<'a> { + type_name: &'a str, + variant_name: &'a str, + } + + impl<'a> UntaggedUnitVisitor<'a> { + /// Not public API. + pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { + UntaggedUnitVisitor { + type_name: type_name, + variant_name: variant_name, + } + } + } + + impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name) + } + + fn visit_unit(self) -> Result<(), E> + where + E: de::Error, + { + Ok(()) + } + } +} + +//////////////////////////////////////////////////////////////////////////////// + +// Like `IntoDeserializer` but also implemented for `&[u8]`. This is used for +// the newtype fallthrough case of `field_identifier`. +// +// #[derive(Deserialize)] +// #[serde(field_identifier)] +// enum F { +// A, +// B, +// Other(String), // deserialized using IdentifierDeserializer +// } +pub trait IdentifierDeserializer<'de, E: Error> { + type Deserializer: Deserializer<'de, Error = E>; + + fn from(self) -> Self::Deserializer; +} + +impl<'de, E> IdentifierDeserializer<'de, E> for u32 +where + E: Error, +{ + type Deserializer = >::Deserializer; + + fn from(self) -> Self::Deserializer { + self.into_deserializer() + } +} + +pub struct StrDeserializer<'a, E> { + value: &'a str, + marker: PhantomData, +} + +impl<'a, E> IdentifierDeserializer<'a, E> for &'a str +where + E: Error, +{ + type Deserializer = StrDeserializer<'a, E>; + + fn from(self) -> Self::Deserializer { + StrDeserializer { + value: self, + marker: PhantomData, + } + } +} + +impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> +where + E: Error, +{ + type Error = E; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_str(self.value) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum identifier ignored_any + } +} + +pub struct BytesDeserializer<'a, E> { + value: &'a [u8], + marker: PhantomData, +} + +impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8] +where + E: Error, +{ + type Deserializer = BytesDeserializer<'a, E>; + + fn from(self) -> Self::Deserializer { + BytesDeserializer { + value: self, + marker: PhantomData, + } + } +} + +impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> +where + E: Error, +{ + type Error = E; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_bytes(self.value) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum identifier ignored_any + } +} diff --git a/serde/src/private/macros.rs b/serde/src/private/macros.rs new file mode 100644 index 00000000..04676138 --- /dev/null +++ b/serde/src/private/macros.rs @@ -0,0 +1,148 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[doc(hidden)] +#[macro_export] +macro_rules! __private_serialize { + () => { + trait Serialize { + fn serialize(&self, serializer: S) -> Result + where + S: $crate::Serializer; + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __private_deserialize { + () => { + trait Deserialize<'de>: Sized { + fn deserialize(deserializer: D) -> Result + where + D: $crate::Deserializer<'de>; + } + }; +} + +/// Used only by Serde doc tests. Not public API. +#[doc(hidden)] +#[macro_export] +macro_rules! __serialize_unimplemented { + ($($func:ident)*) => { + $( + __serialize_unimplemented_helper!($func); + )* + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __serialize_unimplemented_method { + ($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => { + fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::export::Result { + unimplemented!() + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __serialize_unimplemented_helper { + (bool) => { + __serialize_unimplemented_method!(serialize_bool(bool) -> Ok); + }; + (i8) => { + __serialize_unimplemented_method!(serialize_i8(i8) -> Ok); + }; + (i16) => { + __serialize_unimplemented_method!(serialize_i16(i16) -> Ok); + }; + (i32) => { + __serialize_unimplemented_method!(serialize_i32(i32) -> Ok); + }; + (i64) => { + __serialize_unimplemented_method!(serialize_i64(i64) -> Ok); + }; + (u8) => { + __serialize_unimplemented_method!(serialize_u8(u8) -> Ok); + }; + (u16) => { + __serialize_unimplemented_method!(serialize_u16(u16) -> Ok); + }; + (u32) => { + __serialize_unimplemented_method!(serialize_u32(u32) -> Ok); + }; + (u64) => { + __serialize_unimplemented_method!(serialize_u64(u64) -> Ok); + }; + (f32) => { + __serialize_unimplemented_method!(serialize_f32(f32) -> Ok); + }; + (f64) => { + __serialize_unimplemented_method!(serialize_f64(f64) -> Ok); + }; + (char) => { + __serialize_unimplemented_method!(serialize_char(char) -> Ok); + }; + (str) => { + __serialize_unimplemented_method!(serialize_str(&str) -> Ok); + }; + (bytes) => { + __serialize_unimplemented_method!(serialize_bytes(&[u8]) -> Ok); + }; + (none) => { + __serialize_unimplemented_method!(serialize_none() -> Ok); + }; + (some) => { + __serialize_unimplemented_method!(serialize_some(&T) -> Ok); + }; + (unit) => { + __serialize_unimplemented_method!(serialize_unit() -> Ok); + }; + (unit_struct) => { + __serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok); + }; + (unit_variant) => { + __serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok); + }; + (newtype_struct) => { + __serialize_unimplemented_method!(serialize_newtype_struct(&str, &T) -> Ok); + }; + (newtype_variant) => { + __serialize_unimplemented_method!(serialize_newtype_variant(&str, u32, &str, &T) -> Ok); + }; + (seq) => { + type SerializeSeq = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_seq(Option) -> SerializeSeq); + }; + (tuple) => { + type SerializeTuple = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_tuple(usize) -> SerializeTuple); + }; + (tuple_struct) => { + type SerializeTupleStruct = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_tuple_struct(&str, usize) -> SerializeTupleStruct); + }; + (tuple_variant) => { + type SerializeTupleVariant = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_tuple_variant(&str, u32, &str, usize) -> SerializeTupleVariant); + }; + (map) => { + type SerializeMap = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_map(Option) -> SerializeMap); + }; + (struct) => { + type SerializeStruct = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_struct(&str, usize) -> SerializeStruct); + }; + (struct_variant) => { + type SerializeStructVariant = $crate::ser::Impossible; + __serialize_unimplemented_method!(serialize_struct_variant(&str, u32, &str, usize) -> SerializeStructVariant); + }; +} diff --git a/serde/src/private/mod.rs b/serde/src/private/mod.rs new file mode 100644 index 00000000..98307c97 --- /dev/null +++ b/serde/src/private/mod.rs @@ -0,0 +1,12 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod macros; + +pub mod ser; +pub mod de; diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs new file mode 100644 index 00000000..8cb26d95 --- /dev/null +++ b/serde/src/private/ser.rs @@ -0,0 +1,1019 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use lib::*; + +use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible}; + +#[cfg(any(feature = "std", feature = "collections"))] +use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue}; + +/// Used to check that serde(getter) attributes return the expected type. +/// Not public API. +pub fn constrain(t: &T) -> &T { + t +} + +/// Not public API. +pub fn serialize_tagged_newtype( + serializer: S, + type_ident: &'static str, + variant_ident: &'static str, + tag: &'static str, + variant_name: &'static str, + value: &T, +) -> Result +where + S: Serializer, + T: Serialize, +{ + value.serialize( + TaggedSerializer { + type_ident: type_ident, + variant_ident: variant_ident, + tag: tag, + variant_name: variant_name, + delegate: serializer, + }, + ) +} + +struct TaggedSerializer { + type_ident: &'static str, + variant_ident: &'static str, + tag: &'static str, + variant_name: &'static str, + delegate: S, +} + +enum Unsupported { + Boolean, + Integer, + Float, + Char, + String, + ByteArray, + Optional, + Unit, + UnitStruct, + Sequence, + Tuple, + TupleStruct, + #[cfg(not(any(feature = "std", feature = "collections")))] + Enum, +} + +impl Display for Unsupported { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match *self { + Unsupported::Boolean => formatter.write_str("a boolean"), + Unsupported::Integer => formatter.write_str("an integer"), + Unsupported::Float => formatter.write_str("a float"), + Unsupported::Char => formatter.write_str("a char"), + Unsupported::String => formatter.write_str("a string"), + Unsupported::ByteArray => formatter.write_str("a byte array"), + Unsupported::Optional => formatter.write_str("an optional"), + Unsupported::Unit => formatter.write_str("unit"), + Unsupported::UnitStruct => formatter.write_str("a unit struct"), + Unsupported::Sequence => formatter.write_str("a sequence"), + Unsupported::Tuple => formatter.write_str("a tuple"), + Unsupported::TupleStruct => formatter.write_str("a tuple struct"), + #[cfg(not(any(feature = "std", feature = "collections")))] + Unsupported::Enum => formatter.write_str("an enum"), + } + } +} + +impl TaggedSerializer +where + S: Serializer, +{ + fn bad_type(self, what: Unsupported) -> S::Error { + ser::Error::custom( + format_args!( + "cannot serialize tagged newtype variant {}::{} containing {}", + self.type_ident, + self.variant_ident, + what), + ) + } +} + +impl Serializer for TaggedSerializer +where + S: Serializer, +{ + type Ok = S::Ok; + type Error = S::Error; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeMap = S::SerializeMap; + type SerializeStruct = S::SerializeStruct; + + #[cfg(not(any(feature = "std", feature = "collections")))] + type SerializeTupleVariant = Impossible; + #[cfg(any(feature = "std", feature = "collections"))] + type SerializeTupleVariant = SerializeTupleVariantAsMapValue; + + #[cfg(not(any(feature = "std", feature = "collections")))] + type SerializeStructVariant = Impossible; + #[cfg(any(feature = "std", feature = "collections"))] + type SerializeStructVariant = SerializeStructVariantAsMapValue; + + fn serialize_bool(self, _: bool) -> Result { + Err(self.bad_type(Unsupported::Boolean)) + } + + fn serialize_i8(self, _: i8) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_i16(self, _: i16) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_i32(self, _: i32) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_i64(self, _: i64) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u8(self, _: u8) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u16(self, _: u16) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u32(self, _: u32) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u64(self, _: u64) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_f32(self, _: f32) -> Result { + Err(self.bad_type(Unsupported::Float)) + } + + fn serialize_f64(self, _: f64) -> Result { + Err(self.bad_type(Unsupported::Float)) + } + + fn serialize_char(self, _: char) -> Result { + Err(self.bad_type(Unsupported::Char)) + } + + fn serialize_str(self, _: &str) -> Result { + Err(self.bad_type(Unsupported::String)) + } + + fn serialize_bytes(self, _: &[u8]) -> Result { + Err(self.bad_type(Unsupported::ByteArray)) + } + + fn serialize_none(self) -> Result { + Err(self.bad_type(Unsupported::Optional)) + } + + fn serialize_some(self, _: &T) -> Result + where + T: Serialize, + { + Err(self.bad_type(Unsupported::Optional)) + } + + fn serialize_unit(self) -> Result { + Err(self.bad_type(Unsupported::Unit)) + } + + fn serialize_unit_struct(self, _: &'static str) -> Result { + Err(self.bad_type(Unsupported::UnitStruct)) + } + + fn serialize_unit_variant( + self, + _: &'static str, + _: u32, + inner_variant: &'static str, + ) -> Result { + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_entry(inner_variant, &())); + map.end() + } + + fn serialize_newtype_struct( + self, + _: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _: &'static str, + _: u32, + inner_variant: &'static str, + inner_value: &T, + ) -> Result + where + T: Serialize, + { + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_entry(inner_variant, inner_value)); + map.end() + } + + fn serialize_seq(self, _: Option) -> Result { + Err(self.bad_type(Unsupported::Sequence)) + } + + fn serialize_tuple(self, _: usize) -> Result { + Err(self.bad_type(Unsupported::Tuple)) + } + + fn serialize_tuple_struct( + self, + _: &'static str, + _: usize, + ) -> Result { + Err(self.bad_type(Unsupported::TupleStruct)) + } + + #[cfg(not(any(feature = "std", feature = "collections")))] + fn serialize_tuple_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: usize, + ) -> Result { + // Lack of push-based serialization means we need to buffer the content + // of the tuple variant, so it requires std. + Err(self.bad_type(Unsupported::Enum)) + } + + #[cfg(any(feature = "std", feature = "collections"))] + fn serialize_tuple_variant( + self, + _: &'static str, + _: u32, + inner_variant: &'static str, + len: usize, + ) -> Result { + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_key(inner_variant)); + Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len),) + } + + fn serialize_map(self, len: Option) -> Result { + let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1))); + try!(map.serialize_entry(self.tag, self.variant_name)); + Ok(map) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + let mut state = try!(self.delegate.serialize_struct(name, len + 1)); + try!(state.serialize_field(self.tag, self.variant_name)); + Ok(state) + } + + #[cfg(not(any(feature = "std", feature = "collections")))] + fn serialize_struct_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: usize, + ) -> Result { + // Lack of push-based serialization means we need to buffer the content + // of the struct variant, so it requires std. + Err(self.bad_type(Unsupported::Enum)) + } + + #[cfg(any(feature = "std", feature = "collections"))] + fn serialize_struct_variant( + self, + _: &'static str, + _: u32, + inner_variant: &'static str, + len: usize, + ) -> Result { + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_key(inner_variant)); + Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),) + } + + #[cfg(not(any(feature = "std", feature = "collections")))] + fn collect_str(self, _: &T) -> Result + where + T: Display, + { + Err(self.bad_type(Unsupported::String)) + } +} + +/// Used only by Serde doc tests. Not public API. +#[doc(hidden)] +#[derive(Debug)] +pub struct Error; + +impl ser::Error for Error { + fn custom(_: T) -> Self + where + T: Display, + { + unimplemented!() + } +} + +#[cfg(feature = "std")] +impl error::Error for Error { + fn description(&self) -> &str { + unimplemented!() + } +} + +impl Display for Error { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } +} + +#[cfg(any(feature = "std", feature = "collections"))] +mod content { + use lib::*; + + use ser::{self, Serialize, Serializer}; + + pub struct SerializeTupleVariantAsMapValue { + map: M, + name: &'static str, + fields: Vec, + } + + impl SerializeTupleVariantAsMapValue { + pub fn new(map: M, name: &'static str, len: usize) -> Self { + SerializeTupleVariantAsMapValue { + map: map, + name: name, + fields: Vec::with_capacity(len), + } + } + } + + impl ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue + where + M: ser::SerializeMap, + { + type Ok = M::Ok; + type Error = M::Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(mut self) -> Result { + try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields))); + self.map.end() + } + } + + pub struct SerializeStructVariantAsMapValue { + map: M, + name: &'static str, + fields: Vec<(&'static str, Content)>, + } + + impl SerializeStructVariantAsMapValue { + pub fn new(map: M, name: &'static str, len: usize) -> Self { + SerializeStructVariantAsMapValue { + map: map, + name: name, + fields: Vec::with_capacity(len), + } + } + } + + impl ser::SerializeStructVariant for SerializeStructVariantAsMapValue + where + M: ser::SerializeMap, + { + type Ok = M::Ok; + type Error = M::Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), M::Error> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push((key, value)); + Ok(()) + } + + fn end(mut self) -> Result { + try!(self.map.serialize_value(&Content::Struct(self.name, self.fields))); + self.map.end() + } + } + + #[derive(Debug)] + enum Content { + Bool(bool), + + U8(u8), + U16(u16), + U32(u32), + U64(u64), + + I8(i8), + I16(i16), + I32(i32), + I64(i64), + + F32(f32), + F64(f64), + + Char(char), + String(String), + Bytes(Vec), + + None, + Some(Box), + + Unit, + UnitStruct(&'static str), + UnitVariant(&'static str, u32, &'static str), + NewtypeStruct(&'static str, Box), + NewtypeVariant(&'static str, u32, &'static str, Box), + + Seq(Vec), + Tuple(Vec), + TupleStruct(&'static str, Vec), + TupleVariant(&'static str, u32, &'static str, Vec), + Map(Vec<(Content, Content)>), + Struct(&'static str, Vec<(&'static str, Content)>), + StructVariant(&'static str, u32, &'static str, Vec<(&'static str, Content)>), + } + + impl Serialize for Content { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + Content::Bool(b) => serializer.serialize_bool(b), + Content::U8(u) => serializer.serialize_u8(u), + Content::U16(u) => serializer.serialize_u16(u), + Content::U32(u) => serializer.serialize_u32(u), + Content::U64(u) => serializer.serialize_u64(u), + Content::I8(i) => serializer.serialize_i8(i), + Content::I16(i) => serializer.serialize_i16(i), + Content::I32(i) => serializer.serialize_i32(i), + Content::I64(i) => serializer.serialize_i64(i), + Content::F32(f) => serializer.serialize_f32(f), + Content::F64(f) => serializer.serialize_f64(f), + Content::Char(c) => serializer.serialize_char(c), + Content::String(ref s) => serializer.serialize_str(s), + Content::Bytes(ref b) => serializer.serialize_bytes(b), + Content::None => serializer.serialize_none(), + Content::Some(ref c) => serializer.serialize_some(&**c), + Content::Unit => serializer.serialize_unit(), + Content::UnitStruct(n) => serializer.serialize_unit_struct(n), + Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v), + Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c), + Content::NewtypeVariant(n, i, v, ref c) => { + serializer.serialize_newtype_variant(n, i, v, &**c) + } + Content::Seq(ref elements) => elements.serialize(serializer), + Content::Tuple(ref elements) => { + use ser::SerializeTuple; + let mut tuple = try!(serializer.serialize_tuple(elements.len())); + for e in elements { + try!(tuple.serialize_element(e)); + } + tuple.end() + } + Content::TupleStruct(n, ref fields) => { + use ser::SerializeTupleStruct; + let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len())); + for f in fields { + try!(ts.serialize_field(f)); + } + ts.end() + } + Content::TupleVariant(n, i, v, ref fields) => { + use ser::SerializeTupleVariant; + let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len())); + for f in fields { + try!(tv.serialize_field(f)); + } + tv.end() + } + Content::Map(ref entries) => { + use ser::SerializeMap; + let mut map = try!(serializer.serialize_map(Some(entries.len()))); + for &(ref k, ref v) in entries { + try!(map.serialize_entry(k, v)); + } + map.end() + } + Content::Struct(n, ref fields) => { + use ser::SerializeStruct; + let mut s = try!(serializer.serialize_struct(n, fields.len())); + for &(k, ref v) in fields { + try!(s.serialize_field(k, v)); + } + s.end() + } + Content::StructVariant(n, i, v, ref fields) => { + use ser::SerializeStructVariant; + let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len())); + for &(k, ref v) in fields { + try!(sv.serialize_field(k, v)); + } + sv.end() + } + } + } + } + + struct ContentSerializer { + error: PhantomData, + } + + impl ContentSerializer { + fn new() -> Self { + ContentSerializer { error: PhantomData } + } + } + + impl Serializer for ContentSerializer + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + type SerializeSeq = SerializeSeq; + type SerializeTuple = SerializeTuple; + type SerializeTupleStruct = SerializeTupleStruct; + type SerializeTupleVariant = SerializeTupleVariant; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeStruct; + type SerializeStructVariant = SerializeStructVariant; + + fn serialize_bool(self, v: bool) -> Result { + Ok(Content::Bool(v)) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(Content::I8(v)) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(Content::I16(v)) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(Content::I32(v)) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(Content::I64(v)) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(Content::U8(v)) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(Content::U16(v)) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(Content::U32(v)) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(Content::U64(v)) + } + + fn serialize_f32(self, v: f32) -> Result { + Ok(Content::F32(v)) + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(Content::F64(v)) + } + + fn serialize_char(self, v: char) -> Result { + Ok(Content::Char(v)) + } + + fn serialize_str(self, value: &str) -> Result { + Ok(Content::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result { + Ok(Content::Bytes(value.to_owned())) + } + + fn serialize_none(self) -> Result { + Ok(Content::None) + } + + fn serialize_some(self, value: &T) -> Result + where + T: Serialize, + { + Ok(Content::Some(Box::new(try!(value.serialize(self))))) + } + + fn serialize_unit(self) -> Result { + Ok(Content::Unit) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result { + Ok(Content::UnitStruct(name)) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(Content::UnitVariant(name, variant_index, variant)) + } + + fn serialize_newtype_struct( + self, + name: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))),) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + Ok( + Content::NewtypeVariant( + name, + variant_index, + variant, + Box::new(try!(value.serialize(self))), + ), + ) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok( + SerializeSeq { + elements: Vec::with_capacity(len.unwrap_or(0)), + error: PhantomData, + }, + ) + } + + fn serialize_tuple(self, len: usize) -> Result { + Ok( + SerializeTuple { + elements: Vec::with_capacity(len), + error: PhantomData, + }, + ) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + Ok( + SerializeTupleStruct { + name: name, + fields: Vec::with_capacity(len), + error: PhantomData, + }, + ) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok( + SerializeTupleVariant { + name: name, + variant_index: variant_index, + variant: variant, + fields: Vec::with_capacity(len), + error: PhantomData, + }, + ) + } + + fn serialize_map(self, len: Option) -> Result { + Ok( + SerializeMap { + entries: Vec::with_capacity(len.unwrap_or(0)), + key: None, + error: PhantomData, + }, + ) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + Ok( + SerializeStruct { + name: name, + fields: Vec::with_capacity(len), + error: PhantomData, + }, + ) + } + + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok( + SerializeStructVariant { + name: name, + variant_index: variant_index, + variant: variant, + fields: Vec::with_capacity(len), + error: PhantomData, + }, + ) + } + } + + struct SerializeSeq { + elements: Vec, + error: PhantomData, + } + + impl ser::SerializeSeq for SerializeSeq + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_element(&mut self, value: &T) -> Result<(), E> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Seq(self.elements)) + } + } + + struct SerializeTuple { + elements: Vec, + error: PhantomData, + } + + impl ser::SerializeTuple for SerializeTuple + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_element(&mut self, value: &T) -> Result<(), E> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Tuple(self.elements)) + } + } + + struct SerializeTupleStruct { + name: &'static str, + fields: Vec, + error: PhantomData, + } + + impl ser::SerializeTupleStruct for SerializeTupleStruct + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, value: &T) -> Result<(), E> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::TupleStruct(self.name, self.fields)) + } + } + + struct SerializeTupleVariant { + name: &'static str, + variant_index: u32, + variant: &'static str, + fields: Vec, + error: PhantomData, + } + + impl ser::SerializeTupleVariant for SerializeTupleVariant + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, value: &T) -> Result<(), E> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields),) + } + } + + struct SerializeMap { + entries: Vec<(Content, Content)>, + key: Option, + error: PhantomData, + } + + impl ser::SerializeMap for SerializeMap + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_key(&mut self, key: &T) -> Result<(), E> + where + T: Serialize, + { + let key = try!(key.serialize(ContentSerializer::::new())); + self.key = Some(key); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), E> + where + T: Serialize, + { + let key = self.key + .take() + .expect("serialize_value called before serialize_key"); + let value = try!(value.serialize(ContentSerializer::::new())); + self.entries.push((key, value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Map(self.entries)) + } + + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> + where + K: Serialize, + V: Serialize, + { + let key = try!(key.serialize(ContentSerializer::::new())); + let value = try!(value.serialize(ContentSerializer::::new())); + self.entries.push((key, value)); + Ok(()) + } + } + + struct SerializeStruct { + name: &'static str, + fields: Vec<(&'static str, Content)>, + error: PhantomData, + } + + impl ser::SerializeStruct for SerializeStruct + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push((key, value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Struct(self.name, self.fields)) + } + } + + struct SerializeStructVariant { + name: &'static str, + variant_index: u32, + variant: &'static str, + fields: Vec<(&'static str, Content)>, + error: PhantomData, + } + + impl ser::SerializeStructVariant for SerializeStructVariant + where + E: ser::Error, + { + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> + where + T: Serialize, + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push((key, value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields),) + } + } +} diff --git a/serde/src/ser/content.rs b/serde/src/ser/content.rs deleted file mode 100644 index 75482b02..00000000 --- a/serde/src/ser/content.rs +++ /dev/null @@ -1,607 +0,0 @@ -use core::marker::PhantomData; - -#[cfg(all(not(feature = "std"), feature = "collections"))] -use collections::{String, Vec}; - -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::boxed::Box; - -#[cfg(feature = "collections")] -use collections::borrow::ToOwned; - -use ser::{self, Serialize, Serializer}; - -pub struct SerializeTupleVariantAsMapValue { - map: M, - name: &'static str, - fields: Vec, -} - -impl SerializeTupleVariantAsMapValue { - pub fn new(map: M, name: &'static str, len: usize) -> Self { - SerializeTupleVariantAsMapValue { - map: map, - name: name, - fields: Vec::with_capacity(len), - } - } -} - -impl ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue - where M: ser::SerializeMap -{ - type Ok = M::Ok; - type Error = M::Error; - - fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.fields.push(value); - Ok(()) - } - - fn end(mut self) -> Result { - try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields))); - self.map.end() - } -} - -pub struct SerializeStructVariantAsMapValue { - map: M, - name: &'static str, - fields: Vec<(&'static str, Content)>, -} - -impl SerializeStructVariantAsMapValue { - pub fn new(map: M, name: &'static str, len: usize) -> Self { - SerializeStructVariantAsMapValue { - map: map, - name: name, - fields: Vec::with_capacity(len), - } - } -} - -impl ser::SerializeStructVariant for SerializeStructVariantAsMapValue - where M: ser::SerializeMap -{ - type Ok = M::Ok; - type Error = M::Error; - - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), M::Error> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.fields.push((key, value)); - Ok(()) - } - - fn end(mut self) -> Result { - try!(self.map.serialize_value(&Content::Struct(self.name, self.fields))); - self.map.end() - } -} - -#[derive(Debug)] -enum Content { - Bool(bool), - - U8(u8), - U16(u16), - U32(u32), - U64(u64), - - I8(i8), - I16(i16), - I32(i32), - I64(i64), - - F32(f32), - F64(f64), - - Char(char), - String(String), - Bytes(Vec), - - None, - Some(Box), - - Unit, - UnitStruct(&'static str), - UnitVariant(&'static str, usize, &'static str), - NewtypeStruct(&'static str, Box), - NewtypeVariant(&'static str, usize, &'static str, Box), - - Seq(Vec), - SeqFixedSize(Vec), - Tuple(Vec), - TupleStruct(&'static str, Vec), - TupleVariant(&'static str, usize, &'static str, Vec), - Map(Vec<(Content, Content)>), - Struct(&'static str, Vec<(&'static str, Content)>), - StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>), -} - -impl Serialize for Content { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - match *self { - Content::Bool(b) => serializer.serialize_bool(b), - Content::U8(u) => serializer.serialize_u8(u), - Content::U16(u) => serializer.serialize_u16(u), - Content::U32(u) => serializer.serialize_u32(u), - Content::U64(u) => serializer.serialize_u64(u), - Content::I8(i) => serializer.serialize_i8(i), - Content::I16(i) => serializer.serialize_i16(i), - Content::I32(i) => serializer.serialize_i32(i), - Content::I64(i) => serializer.serialize_i64(i), - Content::F32(f) => serializer.serialize_f32(f), - Content::F64(f) => serializer.serialize_f64(f), - Content::Char(c) => serializer.serialize_char(c), - Content::String(ref s) => serializer.serialize_str(s), - Content::Bytes(ref b) => serializer.serialize_bytes(b), - Content::None => serializer.serialize_none(), - Content::Some(ref c) => serializer.serialize_some(&**c), - Content::Unit => serializer.serialize_unit(), - Content::UnitStruct(n) => serializer.serialize_unit_struct(n), - Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v), - Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c), - Content::NewtypeVariant(n, i, v, ref c) => { - serializer.serialize_newtype_variant(n, i, v, &**c) - } - Content::Seq(ref elements) => elements.serialize(serializer), - Content::SeqFixedSize(ref elements) => { - use ser::SerializeSeq; - let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len())); - for e in elements { - try!(seq.serialize_element(e)); - } - seq.end() - } - Content::Tuple(ref elements) => { - use ser::SerializeTuple; - let mut tuple = try!(serializer.serialize_tuple(elements.len())); - for e in elements { - try!(tuple.serialize_element(e)); - } - tuple.end() - } - Content::TupleStruct(n, ref fields) => { - use ser::SerializeTupleStruct; - let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len())); - for f in fields { - try!(ts.serialize_field(f)); - } - ts.end() - } - Content::TupleVariant(n, i, v, ref fields) => { - use ser::SerializeTupleVariant; - let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len())); - for f in fields { - try!(tv.serialize_field(f)); - } - tv.end() - } - Content::Map(ref entries) => { - use ser::SerializeMap; - let mut map = try!(serializer.serialize_map(Some(entries.len()))); - for &(ref k, ref v) in entries { - try!(map.serialize_entry(k, v)); - } - map.end() - } - Content::Struct(n, ref fields) => { - use ser::SerializeStruct; - let mut s = try!(serializer.serialize_struct(n, fields.len())); - for &(k, ref v) in fields { - try!(s.serialize_field(k, v)); - } - s.end() - } - Content::StructVariant(n, i, v, ref fields) => { - use ser::SerializeStructVariant; - let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len())); - for &(k, ref v) in fields { - try!(sv.serialize_field(k, v)); - } - sv.end() - } - } - } -} - -struct ContentSerializer { - error: PhantomData, -} - -impl ContentSerializer { - fn new() -> Self { - ContentSerializer { error: PhantomData } - } -} - -impl Serializer for ContentSerializer - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - type SerializeSeq = SerializeSeq; - type SerializeTuple = SerializeTuple; - type SerializeTupleStruct = SerializeTupleStruct; - type SerializeTupleVariant = SerializeTupleVariant; - type SerializeMap = SerializeMap; - type SerializeStruct = SerializeStruct; - type SerializeStructVariant = SerializeStructVariant; - - fn serialize_bool(self, v: bool) -> Result { - Ok(Content::Bool(v)) - } - - fn serialize_i8(self, v: i8) -> Result { - Ok(Content::I8(v)) - } - - fn serialize_i16(self, v: i16) -> Result { - Ok(Content::I16(v)) - } - - fn serialize_i32(self, v: i32) -> Result { - Ok(Content::I32(v)) - } - - fn serialize_i64(self, v: i64) -> Result { - Ok(Content::I64(v)) - } - - fn serialize_u8(self, v: u8) -> Result { - Ok(Content::U8(v)) - } - - fn serialize_u16(self, v: u16) -> Result { - Ok(Content::U16(v)) - } - - fn serialize_u32(self, v: u32) -> Result { - Ok(Content::U32(v)) - } - - fn serialize_u64(self, v: u64) -> Result { - Ok(Content::U64(v)) - } - - fn serialize_f32(self, v: f32) -> Result { - Ok(Content::F32(v)) - } - - fn serialize_f64(self, v: f64) -> Result { - Ok(Content::F64(v)) - } - - fn serialize_char(self, v: char) -> Result { - Ok(Content::Char(v)) - } - - fn serialize_str(self, value: &str) -> Result { - Ok(Content::String(value.to_owned())) - } - - fn serialize_bytes(self, value: &[u8]) -> Result { - Ok(Content::Bytes(value.to_owned())) - } - - fn serialize_none(self) -> Result { - Ok(Content::None) - } - - fn serialize_some(self, value: &T) -> Result { - Ok(Content::Some(Box::new(try!(value.serialize(self))))) - } - - fn serialize_unit(self) -> Result { - Ok(Content::Unit) - } - - fn serialize_unit_struct(self, name: &'static str) -> Result { - Ok(Content::UnitStruct(name)) - } - - fn serialize_unit_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str) - -> Result { - Ok(Content::UnitVariant(name, variant_index, variant)) - } - - fn serialize_newtype_struct(self, - name: &'static str, - value: &T) - -> Result { - Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self))))) - } - - fn serialize_newtype_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str, - value: &T) - -> Result { - Ok(Content::NewtypeVariant(name, - variant_index, - variant, - Box::new(try!(value.serialize(self))))) - } - - fn serialize_seq(self, len: Option) -> Result { - Ok(SerializeSeq { - fixed_size: false, - elements: Vec::with_capacity(len.unwrap_or(0)), - error: PhantomData, - }) - } - - fn serialize_seq_fixed_size(self, size: usize) -> Result { - Ok(SerializeSeq { - fixed_size: true, - elements: Vec::with_capacity(size), - error: PhantomData, - }) - } - - fn serialize_tuple(self, len: usize) -> Result { - Ok(SerializeTuple { - elements: Vec::with_capacity(len), - error: PhantomData, - }) - } - - fn serialize_tuple_struct(self, - name: &'static str, - len: usize) - -> Result { - Ok(SerializeTupleStruct { - name: name, - fields: Vec::with_capacity(len), - error: PhantomData, - }) - } - - fn serialize_tuple_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str, - len: usize) - -> Result { - Ok(SerializeTupleVariant { - name: name, - variant_index: variant_index, - variant: variant, - fields: Vec::with_capacity(len), - error: PhantomData, - }) - } - - fn serialize_map(self, len: Option) -> Result { - Ok(SerializeMap { - entries: Vec::with_capacity(len.unwrap_or(0)), - key: None, - error: PhantomData, - }) - } - - fn serialize_struct(self, name: &'static str, len: usize) -> Result { - Ok(SerializeStruct { - name: name, - fields: Vec::with_capacity(len), - error: PhantomData, - }) - } - - fn serialize_struct_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str, - len: usize) - -> Result { - Ok(SerializeStructVariant { - name: name, - variant_index: variant_index, - variant: variant, - fields: Vec::with_capacity(len), - error: PhantomData, - }) - } -} - -struct SerializeSeq { - fixed_size: bool, - elements: Vec, - error: PhantomData, -} - -impl ser::SerializeSeq for SerializeSeq - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_element(&mut self, value: &T) -> Result<(), E> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.elements.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(if self.fixed_size { - Content::SeqFixedSize(self.elements) - } else { - Content::Seq(self.elements) - }) - } -} - -struct SerializeTuple { - elements: Vec, - error: PhantomData, -} - -impl ser::SerializeTuple for SerializeTuple - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_element(&mut self, value: &T) -> Result<(), E> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.elements.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(Content::Tuple(self.elements)) - } -} - -struct SerializeTupleStruct { - name: &'static str, - fields: Vec, - error: PhantomData, -} - -impl ser::SerializeTupleStruct for SerializeTupleStruct - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_field(&mut self, value: &T) -> Result<(), E> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.fields.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(Content::TupleStruct(self.name, self.fields)) - } -} - -struct SerializeTupleVariant { - name: &'static str, - variant_index: usize, - variant: &'static str, - fields: Vec, - error: PhantomData, -} - -impl ser::SerializeTupleVariant for SerializeTupleVariant - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_field(&mut self, value: &T) -> Result<(), E> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.fields.push(value); - Ok(()) - } - - fn end(self) -> Result { - Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields)) - } -} - -struct SerializeMap { - entries: Vec<(Content, Content)>, - key: Option, - error: PhantomData, -} - -impl ser::SerializeMap for SerializeMap - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_key(&mut self, key: &T) -> Result<(), E> { - let key = try!(key.serialize(ContentSerializer::::new())); - self.key = Some(key); - Ok(()) - } - - fn serialize_value(&mut self, value: &T) -> Result<(), E> { - let key = self.key.take().expect("serialize_value called before serialize_key"); - let value = try!(value.serialize(ContentSerializer::::new())); - self.entries.push((key, value)); - Ok(()) - } - - fn end(self) -> Result { - Ok(Content::Map(self.entries)) - } - - fn serialize_entry(&mut self, - key: &K, - value: &V) - -> Result<(), E> { - let key = try!(key.serialize(ContentSerializer::::new())); - let value = try!(value.serialize(ContentSerializer::::new())); - self.entries.push((key, value)); - Ok(()) - } -} - -struct SerializeStruct { - name: &'static str, - fields: Vec<(&'static str, Content)>, - error: PhantomData, -} - -impl ser::SerializeStruct for SerializeStruct - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), E> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.fields.push((key, value)); - Ok(()) - } - - fn end(self) -> Result { - Ok(Content::Struct(self.name, self.fields)) - } -} - -struct SerializeStructVariant { - name: &'static str, - variant_index: usize, - variant: &'static str, - fields: Vec<(&'static str, Content)>, - error: PhantomData, -} - -impl ser::SerializeStructVariant for SerializeStructVariant - where E: ser::Error -{ - type Ok = Content; - type Error = E; - - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), E> { - let value = try!(value.serialize(ContentSerializer::::new())); - self.fields.push((key, value)); - Ok(()) - } - - fn end(self) -> Result { - Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields)) - } -} diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 0afaf97f..4adfd24a 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -1,63 +1,27 @@ -#[cfg(feature = "std")] -use std::borrow::Cow; -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::borrow::Cow; +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use lib::*; + +use ser::{Serialize, SerializeTuple, Serializer}; #[cfg(feature = "std")] -use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, HashMap, HashSet, VecDeque}; -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, String, Vec}; +use ser::Error; -#[cfg(feature = "collections")] -use collections::borrow::ToOwned; +//////////////////////////////////////////////////////////////////////////////// -#[cfg(feature = "std")] -use core::hash::{Hash, BuildHasher}; -#[cfg(feature = "std")] -use std::net; -#[cfg(any(feature = "std", feature = "unstable"))] -use core::ops; -#[cfg(feature = "std")] -use std::path; -#[cfg(feature = "std")] -use std::ffi::{CString, CStr, OsString, OsStr}; -#[cfg(feature = "std")] -use std::rc::Rc; -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::rc::Rc; -#[cfg(feature = "std")] -use std::time::Duration; - -#[cfg(feature = "std")] -use std::sync::Arc; -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::arc::Arc; - -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::boxed::Box; - -use core::cell::{Cell, RefCell}; - -#[cfg(feature = "std")] -use std::sync::{Mutex, RwLock}; - -use core::marker::PhantomData; - -#[cfg(feature = "unstable")] -use core::nonzero::{NonZero, Zeroable}; - -use super::{Serialize, SerializeSeq, SerializeTuple, Serializer}; -#[cfg(feature = "std")] -use super::Error; - -/////////////////////////////////////////////////////////////////////////////// - -macro_rules! impl_visit { - ($ty:ty, $method:ident $($cast:tt)*) => { +macro_rules! primitive_impl { + ($ty:ident, $method:ident $($cast:tt)*) => { impl Serialize for $ty { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { serializer.$method(*self $($cast)*) } @@ -65,27 +29,28 @@ macro_rules! impl_visit { } } -impl_visit!(bool, serialize_bool); -impl_visit!(isize, serialize_i64 as i64); -impl_visit!(i8, serialize_i8); -impl_visit!(i16, serialize_i16); -impl_visit!(i32, serialize_i32); -impl_visit!(i64, serialize_i64); -impl_visit!(usize, serialize_u64 as u64); -impl_visit!(u8, serialize_u8); -impl_visit!(u16, serialize_u16); -impl_visit!(u32, serialize_u32); -impl_visit!(u64, serialize_u64); -impl_visit!(f32, serialize_f32); -impl_visit!(f64, serialize_f64); -impl_visit!(char, serialize_char); +primitive_impl!(bool, serialize_bool); +primitive_impl!(isize, serialize_i64 as i64); +primitive_impl!(i8, serialize_i8); +primitive_impl!(i16, serialize_i16); +primitive_impl!(i32, serialize_i32); +primitive_impl!(i64, serialize_i64); +primitive_impl!(usize, serialize_u64 as u64); +primitive_impl!(u8, serialize_u8); +primitive_impl!(u16, serialize_u16); +primitive_impl!(u32, serialize_u32); +primitive_impl!(u64, serialize_u64); +primitive_impl!(f32, serialize_f32); +primitive_impl!(f64, serialize_f64); +primitive_impl!(char, serialize_char); -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// impl Serialize for str { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { serializer.serialize_str(self) } @@ -95,19 +60,21 @@ impl Serialize for str { impl Serialize for String { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { - (&self[..]).serialize(serializer) + serializer.serialize_str(self) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] impl Serialize for CStr { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { serializer.serialize_bytes(self.to_bytes()) } @@ -117,20 +84,23 @@ impl Serialize for CStr { impl Serialize for CString { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { serializer.serialize_bytes(self.to_bytes()) } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// impl Serialize for Option - where T: Serialize +where + T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match *self { Some(ref value) => serializer.serialize_some(value), @@ -139,138 +109,120 @@ impl Serialize for Option } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// impl Serialize for PhantomData { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { serializer.serialize_unit_struct("PhantomData") } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// Does not require T: Serialize. +impl Serialize for [T; 0] { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + try!(serializer.serialize_tuple(0)).end() + } +} macro_rules! array_impls { - ($len:expr) => { - impl Serialize for [T; $len] where T: Serialize { + ($($len:tt)+) => { + $( + impl Serialize for [T; $len] + where + T: Serialize, + { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = try!(serializer.serialize_tuple($len)); + for e in self { + try!(seq.serialize_element(e)); + } + seq.end() + } + } + )+ + } +} + +array_impls!(01 02 03 04 05 06 07 08 09 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32); + +//////////////////////////////////////////////////////////////////////////////// + +impl Serialize for [T] +where + T: Serialize, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq(self) + } +} + +macro_rules! seq_impl { + ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { + impl Serialize for $ty + where + T: Serialize $(+ $tbound1 $(+ $tbound2)*)*, + $($typaram: $bound,)* + { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { - let mut seq = try!(serializer.serialize_seq_fixed_size($len)); - for e in self { - try!(seq.serialize_element(e)); - } - seq.end() + serializer.collect_seq(self) } } } } -array_impls!(0); -array_impls!(1); -array_impls!(2); -array_impls!(3); -array_impls!(4); -array_impls!(5); -array_impls!(6); -array_impls!(7); -array_impls!(8); -array_impls!(9); -array_impls!(10); -array_impls!(11); -array_impls!(12); -array_impls!(13); -array_impls!(14); -array_impls!(15); -array_impls!(16); -array_impls!(17); -array_impls!(18); -array_impls!(19); -array_impls!(20); -array_impls!(21); -array_impls!(22); -array_impls!(23); -array_impls!(24); -array_impls!(25); -array_impls!(26); -array_impls!(27); -array_impls!(28); -array_impls!(29); -array_impls!(30); -array_impls!(31); -array_impls!(32); - -/////////////////////////////////////////////////////////////////////////////// - -macro_rules! serialize_seq { - () => { - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer, - { - serializer.collect_seq(self) - } - } -} - -impl Serialize for [T] - where T: Serialize -{ - serialize_seq!(); -} +#[cfg(any(feature = "std", feature = "collections"))] +seq_impl!(BinaryHeap); #[cfg(any(feature = "std", feature = "collections"))] -impl Serialize for BinaryHeap - where T: Serialize + Ord -{ - serialize_seq!(); -} - -#[cfg(any(feature = "std", feature = "collections"))] -impl Serialize for BTreeSet - where T: Serialize + Ord -{ - serialize_seq!(); -} +seq_impl!(BTreeSet); #[cfg(feature = "std")] -impl Serialize for HashSet - where T: Serialize + Eq + Hash, - H: BuildHasher -{ - serialize_seq!(); -} +seq_impl!(HashSet); #[cfg(any(feature = "std", feature = "collections"))] -impl Serialize for LinkedList - where T: Serialize -{ - serialize_seq!(); -} +seq_impl!(LinkedList); #[cfg(any(feature = "std", feature = "collections"))] -impl Serialize for Vec - where T: Serialize -{ - serialize_seq!(); -} +seq_impl!(Vec); #[cfg(any(feature = "std", feature = "collections"))] -impl Serialize for VecDeque - where T: Serialize -{ - serialize_seq!(); -} +seq_impl!(VecDeque); -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] -impl Serialize for ops::Range { +impl Serialize for ops::Range +where + Idx: Serialize, +{ fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { use super::SerializeStruct; let mut state = try!(serializer.serialize_struct("Range", 2)); @@ -280,36 +232,35 @@ impl Serialize for ops::Range { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// impl Serialize for () { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { serializer.serialize_unit() } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// macro_rules! tuple_impls { - ($( - $TupleVisitor:ident ($len:expr, $($T:ident),+) { - $($state:pat => $idx:tt,)+ - } - )+) => { + ($($len:expr => ($($n:tt $name:ident)+))+) => { $( - impl<$($T),+> Serialize for ($($T,)+) - where $($T: Serialize),+ + impl<$($name),+> Serialize for ($($name,)+) + where + $($name: Serialize,)+ { #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer, + where + S: Serializer, { let mut tuple = try!(serializer.serialize_tuple($len)); $( - try!(tuple.serialize_element(&self.$idx)); + try!(tuple.serialize_element(&self.$n)); )+ tuple.end() } @@ -319,295 +270,106 @@ macro_rules! tuple_impls { } tuple_impls! { - TupleVisitor1 (1, T0) { - 0 => 0, - } - TupleVisitor2 (2, T0, T1) { - 0 => 0, - 1 => 1, - } - TupleVisitor3 (3, T0, T1, T2) { - 0 => 0, - 1 => 1, - 2 => 2, - } - TupleVisitor4 (4, T0, T1, T2, T3) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - } - TupleVisitor5 (5, T0, T1, T2, T3, T4) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - } - TupleVisitor6 (6, T0, T1, T2, T3, T4, T5) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - } - TupleVisitor7 (7, T0, T1, T2, T3, T4, T5, T6) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - } - TupleVisitor8 (8, T0, T1, T2, T3, T4, T5, T6, T7) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - } - TupleVisitor9 (9, T0, T1, T2, T3, T4, T5, T6, T7, T8) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - } - TupleVisitor10 (10, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - } - TupleVisitor11 (11, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - } - TupleVisitor12 (12, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - } - TupleVisitor13 (13, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - } - TupleVisitor14 (14, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - 13 => 13, - } - TupleVisitor15 (15, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - 13 => 13, - 14 => 14, - } - TupleVisitor16 (16, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) { - 0 => 0, - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - 13 => 13, - 14 => 14, - 15 => 15, - } + 1 => (0 T0) + 2 => (0 T0 1 T1) + 3 => (0 T0 1 T1 2 T2) + 4 => (0 T0 1 T1 2 T2 3 T3) + 5 => (0 T0 1 T1 2 T2 3 T3 4 T4) + 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) + 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) + 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) + 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) + 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) + 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) + 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) + 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) + 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) + 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) + 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -macro_rules! serialize_map { - () => { - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer, +macro_rules! map_impl { + ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { + impl Serialize for $ty + where + K: Serialize $(+ $kbound1 $(+ $kbound2)*)*, + V: Serialize, + $($typaram: $bound,)* { - serializer.collect_map(self) + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_map(self) + } } } } #[cfg(any(feature = "std", feature = "collections"))] -impl Serialize for BTreeMap - where K: Serialize + Ord, - V: Serialize -{ - serialize_map!(); -} +map_impl!(BTreeMap); #[cfg(feature = "std")] -impl Serialize for HashMap - where K: Serialize + Eq + Hash, - V: Serialize, - H: BuildHasher -{ - serialize_map!(); +map_impl!(HashMap); + +//////////////////////////////////////////////////////////////////////////////// + +macro_rules! deref_impl { + ($($desc:tt)+) => { + impl $($desc)+ { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (**self).serialize(serializer) + } + } + }; } -/////////////////////////////////////////////////////////////////////////////// - -impl<'a, T: ?Sized> Serialize for &'a T - where T: Serialize -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} - -impl<'a, T: ?Sized> Serialize for &'a mut T - where T: Serialize -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} +deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize); +deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize); #[cfg(any(feature = "std", feature = "alloc"))] -impl Serialize for Box - where T: Serialize -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} +deref_impl!( Serialize for Box where T: Serialize); -#[cfg(any(feature = "std", feature = "alloc"))] -impl Serialize for Rc - where T: Serialize -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +deref_impl!( Serialize for Rc where T: Serialize); -#[cfg(any(feature = "std", feature = "alloc"))] -impl Serialize for Arc - where T: Serialize -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +deref_impl!( Serialize for Arc where T: Serialize); #[cfg(any(feature = "std", feature = "collections"))] -impl<'a, T: ?Sized> Serialize for Cow<'a, T> - where T: Serialize + ToOwned -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} +deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned); + +#[cfg(feature = "unstable")] +deref_impl!( Serialize for NonZero where T: Serialize + Zeroable); + +//////////////////////////////////////////////////////////////////////////////// impl Serialize for Cell - where T: Serialize + Copy +where + T: Serialize + Copy, { - #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { self.get().serialize(serializer) } } impl Serialize for RefCell - where T: Serialize +where + T: Serialize, { - #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { self.borrow().serialize(serializer) } @@ -615,11 +377,12 @@ impl Serialize for RefCell #[cfg(feature = "std")] impl Serialize for Mutex - where T: Serialize +where + T: Serialize, { - #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match self.lock() { Ok(locked) => locked.serialize(serializer), @@ -630,11 +393,12 @@ impl Serialize for Mutex #[cfg(feature = "std")] impl Serialize for RwLock - where T: Serialize +where + T: Serialize, { - #[inline] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match self.read() { Ok(locked) => locked.serialize(serializer), @@ -643,14 +407,16 @@ impl Serialize for RwLock } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// impl Serialize for Result - where T: Serialize, - E: Serialize +where + T: Serialize, + E: Serialize, { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match *self { Result::Ok(ref value) => serializer.serialize_newtype_variant("Result", 0, "Ok", value), @@ -661,12 +427,13 @@ impl Serialize for Result } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] impl Serialize for Duration { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { use super::SerializeStruct; let mut state = try!(serializer.serialize_struct("Duration", 2)); @@ -676,12 +443,39 @@ impl Serialize for Duration { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/// Serialize a value that implements `Display` as a string, when that string is +/// statically known to never have more than a constant `MAX_LEN` bytes. +/// +/// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes. +#[cfg(feature = "std")] +macro_rules! serialize_display_bounded_length { + ($value:expr, $max:expr, $serializer:expr) => {{ + let mut buffer: [u8; $max] = unsafe { mem::uninitialized() }; + let remaining_len = { + let mut remaining = &mut buffer[..]; + write!(remaining, "{}", $value).unwrap(); + remaining.len() + }; + let written_len = buffer.len() - remaining_len; + let written = &buffer[..written_len]; + + // write! only provides fmt::Formatter to Display implementations, which + // has methods write_str and write_char but no method to write arbitrary + // bytes. Therefore `written` must be valid UTF-8. + let written_str = unsafe { + str::from_utf8_unchecked(written) + }; + $serializer.serialize_str(written_str) + }} +} #[cfg(feature = "std")] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match *self { net::IpAddr::V4(ref a) => a.serialize(serializer), @@ -693,7 +487,8 @@ impl Serialize for net::IpAddr { #[cfg(feature = "std")] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { /// "101.102.103.104".len() const MAX_LEN: usize = 15; @@ -704,7 +499,8 @@ impl Serialize for net::Ipv4Addr { #[cfg(feature = "std")] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { /// "1000:1002:1003:1004:1005:1006:1007:1008".len() const MAX_LEN: usize = 39; @@ -712,12 +508,11 @@ impl Serialize for net::Ipv6Addr { } } -/////////////////////////////////////////////////////////////////////////////// - #[cfg(feature = "std")] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match *self { net::SocketAddr::V4(ref addr) => addr.serialize(serializer), @@ -729,7 +524,8 @@ impl Serialize for net::SocketAddr { #[cfg(feature = "std")] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { /// "101.102.103.104:65000".len() const MAX_LEN: usize = 21; @@ -740,7 +536,8 @@ impl Serialize for net::SocketAddrV4 { #[cfg(feature = "std")] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { /// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len() const MAX_LEN: usize = 47; @@ -748,12 +545,13 @@ impl Serialize for net::SocketAddrV6 { } } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] -impl Serialize for path::Path { +impl Serialize for Path { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { match self.to_str() { Some(s) => s.serialize(serializer), @@ -763,9 +561,10 @@ impl Serialize for path::Path { } #[cfg(feature = "std")] -impl Serialize for path::PathBuf { +impl Serialize for PathBuf { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { self.as_path().serialize(serializer) } @@ -775,44 +574,30 @@ impl Serialize for path::PathBuf { impl Serialize for OsStr { #[cfg(unix)] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { use std::os::unix::ffi::OsStrExt; - serializer.serialize_newtype_variant("OsString", - 0, - "Unix", - self.as_bytes()) + serializer.serialize_newtype_variant("OsString", 0, "Unix", self.as_bytes()) } + #[cfg(windows)] fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { use std::os::windows::ffi::OsStrExt; let val = self.encode_wide().collect::>(); - serializer.serialize_newtype_variant("OsString", - 1, - "Windows", - &val) + serializer.serialize_newtype_variant("OsString", 1, "Windows", &val) } } #[cfg(all(feature = "std", any(unix, windows)))] -#[cfg(feature = "std")] impl Serialize for OsString { fn serialize(&self, serializer: S) -> Result - where S: Serializer + where + S: Serializer, { self.as_os_str().serialize(serializer) } } - -#[cfg(feature = "unstable")] -impl Serialize for NonZero - where T: Serialize + Zeroable -{ - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - (**self).serialize(serializer) - } -} diff --git a/serde/src/ser/impossible.rs b/serde/src/ser/impossible.rs index 6b8e7c28..f72748f6 100644 --- a/serde/src/ser/impossible.rs +++ b/serde/src/ser/impossible.rs @@ -1,6 +1,14 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! This module contains `Impossible` serializer and its implementations. -use core::marker::PhantomData; +use lib::*; use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant}; @@ -9,11 +17,19 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, /// serializing one of the compound types. /// /// This type cannot be instantiated, but implements every one of the traits -/// corresponding to the `Serializer` compound types: `SerializeSeq`, -/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`, -/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`. +/// corresponding to the [`Serializer`] compound types: [`SerializeSeq`], +/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`], +/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`]. /// -/// ```rust,ignore +/// ```rust +/// # #[macro_use] +/// # extern crate serde; +/// # +/// # use serde::ser::{Serializer, Impossible}; +/// # use serde::private::ser::Error; +/// # +/// # struct MySerializer; +/// # /// impl Serializer for MySerializer { /// type Ok = (); /// type Error = Error; @@ -27,130 +43,185 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, /// -> Result { /// // Given Impossible cannot be instantiated, the only /// // thing we can do here is to return an error. +/// # stringify! { /// Err(...) +/// # }; +/// # unimplemented!() /// } /// /// /* other Serializer methods */ +/// # __serialize_unimplemented! { +/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some +/// # unit unit_struct unit_variant newtype_struct newtype_variant +/// # tuple tuple_struct tuple_variant map struct struct_variant +/// # } /// } +/// # +/// # fn main() {} /// ``` -pub struct Impossible { +/// +/// [`Serializer`]: trait.Serializer.html +/// [`SerializeSeq`]: trait.SerializeSeq.html +/// [`SerializeTuple`]: trait.SerializeTuple.html +/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html +/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html +/// [`SerializeMap`]: trait.SerializeMap.html +/// [`SerializeStruct`]: trait.SerializeStruct.html +/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html +pub struct Impossible { void: Void, - _marker: PhantomData<(Ok, E)>, + ok: PhantomData, + error: PhantomData, } enum Void {} -impl SerializeSeq for Impossible - where E: ser::Error +impl SerializeSeq for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_element(&mut self, _value: &T) -> Result<(), E> { + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } -impl SerializeTuple for Impossible - where E: ser::Error +impl SerializeTuple for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_element(&mut self, _value: &T) -> Result<(), E> { + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } -impl SerializeTupleStruct for Impossible - where E: ser::Error +impl SerializeTupleStruct for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_field(&mut self, _value: &T) -> Result<(), E> { + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } -impl SerializeTupleVariant for Impossible - where E: ser::Error +impl SerializeTupleVariant for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_field(&mut self, _value: &T) -> Result<(), E> { + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } -impl SerializeMap for Impossible - where E: ser::Error +impl SerializeMap for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_key(&mut self, _key: &T) -> Result<(), E> { + fn serialize_key(&mut self, key: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = key; match self.void {} } - fn serialize_value(&mut self, _value: &T) -> Result<(), E> { + fn serialize_value(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } -impl SerializeStruct for Impossible - where E: ser::Error +impl SerializeStruct for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_field(&mut self, - _key: &'static str, - _value: &T) - -> Result<(), E> { + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = key; + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } -impl SerializeStructVariant for Impossible - where E: ser::Error +impl SerializeStructVariant for Impossible +where + Error: ser::Error, { type Ok = Ok; - type Error = E; + type Error = Error; - fn serialize_field(&mut self, - _key: &'static str, - _value: &T) - -> Result<(), E> { + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let _ = key; + let _ = value; match self.void {} } - fn end(self) -> Result { + fn end(self) -> Result { match self.void {} } } diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 460b6877..565236ef 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -1,7 +1,15 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! Generic data structure serialization framework. //! -//! The two most important traits in this module are `Serialize` and -//! `Serializer`. +//! The two most important traits in this module are [`Serialize`] and +//! [`Serializer`]. //! //! - **A type that implements `Serialize` is a data structure** that can be //! serialized to any data format supported by Serde, and conversely @@ -10,39 +18,38 @@ //! //! # The Serialize trait //! -//! Serde provides `Serialize` implementations for many Rust primitive and +//! Serde provides [`Serialize`] implementations for many Rust primitive and //! standard library types. The complete list is below. All of these can be //! serialized using Serde out of the box. //! -//! Additionally, Serde provides a procedural macro called `serde_derive` to -//! automatically generate `Serialize` implementations for structs and enums in -//! your program. See the [codegen section of the manual][codegen] for how to -//! use this. +//! Additionally, Serde provides a procedural macro called [`serde_derive`] to +//! automatically generate [`Serialize`] implementations for structs and enums +//! in your program. See the [codegen section of the manual] for how to use +//! this. //! -//! In rare cases it may be necessary to implement `Serialize` manually for some -//! type in your program. See the [Implementing `Serialize`][impl-serialize] -//! section of the manual for more about this. +//! In rare cases it may be necessary to implement [`Serialize`] manually for +//! some type in your program. See the [Implementing `Serialize`] section of the +//! manual for more about this. //! -//! Third-party crates may provide `Serialize` implementations for types that -//! they expose. For example the `linked-hash-map` crate provides a -//! `LinkedHashMap` type that is serializable by Serde because the crate -//! provides an implementation of `Serialize` for it. +//! Third-party crates may provide [`Serialize`] implementations for types that +//! they expose. For example the [`linked-hash-map`] crate provides a +//! [`LinkedHashMap`] type that is serializable by Serde because the crate +//! provides an implementation of [`Serialize`] for it. //! //! # The Serializer trait //! -//! `Serializer` implementations are provided by third-party crates, for example -//! [`serde_json`][serde_json], [`serde_yaml`][serde_yaml] and -//! [`bincode`][bincode]. +//! [`Serializer`] implementations are provided by third-party crates, for +//! example [`serde_json`], [`serde_yaml`] and [`bincode`]. //! //! A partial list of well-maintained formats is given on the [Serde -//! website][data-formats]. +//! website][data formats]. //! //! # Implementations of Serialize provided by Serde //! //! - **Primitive types**: //! - bool -//! - isize, i8, i16, i32, i64 -//! - usize, u8, u16, u32, u64 +//! - i8, i16, i32, i64, isize +//! - u8, u16, u32, u64, usize //! - f32, f64 //! - char //! - str @@ -75,6 +82,11 @@ //! - VecDeque\ //! - Vec\ //! - EnumSet\ (unstable) +//! - **FFI types**: +//! - CStr +//! - CString +//! - OsStr +//! - OsString //! - **Miscellaneous standard library types**: //! - Duration //! - Path @@ -89,68 +101,81 @@ //! - SocketAddrV4 //! - SocketAddrV6 //! -//! [codegen]: https://serde.rs/codegen.html -//! [impl-serialize]: https://serde.rs/impl-serialize.html -//! [serde_json]: https://github.com/serde-rs/json -//! [serde_yaml]: https://github.com/dtolnay/serde-yaml -//! [bincode]: https://github.com/TyOverby/bincode -//! [data-formats]: https://serde.rs/#data-formats +//! [Implementing `Serialize`]: https://serde.rs/impl-serialize.html +//! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html +//! [`Serialize`]: ../trait.Serialize.html +//! [`Serializer`]: ../trait.Serializer.html +//! [`bincode`]: https://github.com/TyOverby/bincode +//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map +//! [`serde_derive`]: https://crates.io/crates/serde_derive +//! [`serde_json`]: https://github.com/serde-rs/json +//! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml +//! [codegen section of the manual]: https://serde.rs/codegen.html +//! [data formats]: https://serde.rs/#data-formats -#[cfg(feature = "std")] -use std::error; -#[cfg(not(feature = "std"))] -use error; - -#[cfg(all(feature = "collections", not(feature = "std")))] -use collections::string::String; -use core::fmt::Display; -#[cfg(any(feature = "std", feature = "collections"))] -use core::fmt::Write; -use core::iter::IntoIterator; +use lib::*; mod impls; mod impossible; -// Helpers used by generated code. Not public API. -#[doc(hidden)] -pub mod private; -#[cfg(any(feature = "std", feature = "collections"))] -mod content; - 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:ident)::+)*) => { + /// Trait used by `Serialize` implementations to generically construct + /// errors belonging to the `Serializer` against which they are + /// currently running. + pub trait Error: Sized $(+ $($supertrait)::+)* { + /// Used when a [`Serialize`] implementation encounters any 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 + /// # struct Path; + /// # + /// # impl Path { + /// # fn to_str(&self) -> Option<&str> { + /// # unimplemented!() + /// # } + /// # } + /// # + /// use serde::ser::{self, Serialize, Serializer}; + /// + /// impl Serialize for Path { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match self.to_str() { + /// Some(s) => serializer.serialize_str(s), + /// None => Err(ser::Error::custom("path contains invalid UTF-8 characters")), + /// } + /// } + /// } + /// ``` + /// + /// [`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html + /// [`Serialize`]: ../trait.Serialize.html + fn custom(msg: T) -> Self + where + T: Display; + } + } } -/////////////////////////////////////////////////////////////////////////////// +#[cfg(feature = "std")] +declare_error_trait!(Error: Sized + error::Error); + +#[cfg(not(feature = "std"))] +declare_error_trait!(Error: Sized + Debug + Display); + +//////////////////////////////////////////////////////////////////////////////// /// A **data structure** that can be serialized into any data format supported /// by Serde. @@ -159,39 +184,66 @@ pub trait Error: Sized + error::Error { /// standard library types. The complete list is [here][ser]. All of these can /// be serialized using Serde out of the box. /// -/// Additionally, Serde provides a procedural macro called `serde_derive` to +/// Additionally, Serde provides a procedural macro called [`serde_derive`] to /// automatically generate `Serialize` implementations for structs and enums in -/// your program. See the [codegen section of the manual][codegen] for how to -/// use this. +/// your program. See the [codegen section of the manual] for how to use this. /// /// In rare cases it may be necessary to implement `Serialize` manually for some -/// type in your program. See the [Implementing `Serialize`][impl-serialize] -/// section of the manual for more about this. +/// type in your program. See the [Implementing `Serialize`] section of the +/// manual for more about this. /// /// Third-party crates may provide `Serialize` implementations for types that -/// they expose. For example the `linked-hash-map` crate provides a -/// `LinkedHashMap` type that is serializable by Serde because the crate +/// they expose. For example the [`linked-hash-map`] crate provides a +/// [`LinkedHashMap`] type that is serializable by Serde because the crate /// provides an implementation of `Serialize` for it. /// +/// [Implementing `Serialize`]: https://serde.rs/impl-serialize.html +/// [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html +/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map +/// [`serde_derive`]: https://crates.io/crates/serde_derive +/// [codegen section of the manual]: https://serde.rs/codegen.html /// [ser]: https://docs.serde.rs/serde/ser/index.html -/// [codegen]: https://serde.rs/codegen.html -/// [impl-serialize]: https://serde.rs/impl-serialize.html pub trait Serialize { /// Serialize this value into the given Serde serializer. /// - /// See the [Implementing `Serialize`][impl-serialize] section of the manual - /// for more information about how to implement this method. + /// See the [Implementing `Serialize`] section of the manual for more + /// information about how to implement this method. /// - /// [impl-serialize]: https://serde.rs/impl-serialize.html - fn serialize(&self, serializer: S) -> Result where S: Serializer; + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeStruct}; + /// + /// struct Person { + /// name: String, + /// age: u8, + /// phones: Vec, + /// } + /// + /// // This is what #[derive(Serialize)] would generate. + /// impl Serialize for Person { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut s = serializer.serialize_struct("Person", 3)?; + /// s.serialize_field("name", &self.name)?; + /// s.serialize_field("age", &self.age)?; + /// s.serialize_field("phones", &self.phones)?; + /// s.end() + /// } + /// } + /// ``` + /// + /// [Implementing `Serialize`]: https://serde.rs/impl-serialize.html + fn serialize(&self, serializer: S) -> Result + where + S: Serializer; } -/////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// /// A **data format** that can serialize any data structure supported by Serde. /// /// The role of this trait is to define the serialization half of the Serde data -/// model, which is a way to categorize every Rust data structure into one of 28 +/// model, which is a way to categorize every Rust data structure into one of 27 /// possible types. Each method of the `Serializer` trait corresponds to one of /// the types of the data model. /// @@ -200,47 +252,54 @@ pub trait Serialize { /// /// The types that make up the Serde data model are: /// -/// - 12 primitive types: +/// - **12 primitive types** /// - bool /// - i8, i16, i32, i64 /// - u8, u16, u32, u64 /// - f32, f64 /// - char -/// - string -/// - byte array - [u8] -/// - option -/// - either none or some value -/// - unit -/// - unit is the type of () in Rust -/// - unit_struct -/// - for example `struct Unit` or `PhantomData` -/// - unit_variant -/// - the `E::A` and `E::B` in `enum E { A, B }` -/// - newtype_struct -/// - for example `struct Millimeters(u8)` -/// - newtype_variant -/// - the `E::N` in `enum E { N(u8) }` -/// - seq -/// - a dynamically sized sequence of values, for example `Vec` or -/// `HashSet` -/// - seq_fixed_size -/// - a statically sized sequence of values for which the size will be known -/// at deserialization time without looking at the serialized data, for -/// example `[u64; 10]` -/// - tuple -/// - for example `(u8,)` or `(String, u64, Vec)` -/// - tuple_struct -/// - for example `struct Rgb(u8, u8, u8)` -/// - tuple_variant -/// - the `E::T` in `enum E { T(u8, u8) }` -/// - map -/// - for example `BTreeMap` -/// - struct -/// - a key-value pairing in which the keys will be known at deserialization -/// time without looking at the serialized data, for example `struct S { r: -/// u8, g: u8, b: u8 }` -/// - struct_variant -/// - the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }` +/// - **string** +/// - UTF-8 bytes with a length and no null terminator. +/// - When serializing, all strings are handled equally. When deserializing, +/// there are three flavors of strings: transient, owned, and borrowed. +/// - **byte array** - [u8] +/// - Similar to strings, during deserialization byte arrays can be transient, +/// owned, or borrowed. +/// - **option** +/// - Either none or some value. +/// - **unit** +/// - The type of `()` in Rust. It represents an anonymous value containing no +/// data. +/// - **unit_struct** +/// - For example `struct Unit` or `PhantomData`. It represents a named value +/// containing no data. +/// - **unit_variant** +/// - For example the `E::A` and `E::B` in `enum E { A, B }`. +/// - **newtype_struct** +/// - For example `struct Millimeters(u8)`. +/// - **newtype_variant** +/// - For example the `E::N` in `enum E { N(u8) }`. +/// - **seq** +/// - A variably sized heterogeneous sequence of values, for example `Vec` or +/// `HashSet`. When serializing, the length may or may not be known before +/// iterating through all the data. When deserializing, the length is determined +/// by looking at the serialized data. +/// - **tuple** +/// - A statically sized heterogeneous sequence of values for which the length +/// will be known at deserialization time without looking at the serialized +/// data, for example `(u8,)` or `(String, u64, Vec)` or `[u64; 10]`. +/// - **tuple_struct** +/// - A named tuple, for example `struct Rgb(u8, u8, u8)`. +/// - **tuple_variant** +/// - For example the `E::T` in `enum E { T(u8, u8) }`. +/// - **map** +/// - A heterogeneous key-value pairing, for example `BTreeMap`. +/// - **struct** +/// - A heterogeneous key-value pairing in which the keys are strings and will be +/// known at deserialization time without looking at the serialized data, for +/// example `struct S { r: u8, g: u8, b: u8 }`. +/// - **struct_variant** +/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// /// Many Serde serializers produce text or binary data as output, for example /// JSON or Bincode. This is not a requirement of the `Serializer` trait, and @@ -251,44 +310,79 @@ pub trait Serialize { pub trait Serializer: Sized { /// The output type produced by this `Serializer` during successful /// serialization. Most serializers that produce text or binary output - /// should set `Ok = ()` and serialize into an `io::Write` or buffer + /// should set `Ok = ()` and serialize into an [`io::Write`] or buffer /// contained within the `Serializer` instance. Serializers that build /// in-memory data structures may be simplified by using `Ok` to propagate /// the data structure around. + /// + /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html type Ok; /// The error type when some error occurs during serialization. type Error: Error; - /// Type returned from `serialize_seq` and `serialize_seq_fixed_size` for - /// serializing the content of the sequence. + /// Type returned from [`serialize_seq`] for serializing the content of the + /// sequence. + /// + /// [`serialize_seq`]: #tymethod.serialize_seq type SerializeSeq: SerializeSeq; - /// Type returned from `serialize_tuple` for serializing the content of the - /// tuple. + /// Type returned from [`serialize_tuple`] for serializing the content of + /// the tuple. + /// + /// [`serialize_tuple`]: #tymethod.serialize_tuple type SerializeTuple: SerializeTuple; - /// Type returned from `serialize_tuple_struct` for serializing the content - /// of the tuple struct. + /// Type returned from [`serialize_tuple_struct`] for serializing the + /// content of the tuple struct. + /// + /// [`serialize_tuple_struct`]: #tymethod.serialize_tuple_struct type SerializeTupleStruct: SerializeTupleStruct; - /// Type returned from `serialize_tuple_variant` for serializing the content - /// of the tuple variant. + /// Type returned from [`serialize_tuple_variant`] for serializing the + /// content of the tuple variant. + /// + /// [`serialize_tuple_variant`]: #tymethod.serialize_tuple_variant type SerializeTupleVariant: SerializeTupleVariant; - /// Type returned from `serialize_map` for serializing the content of the + /// Type returned from [`serialize_map`] for serializing the content of the /// map. + /// + /// [`serialize_map`]: #tymethod.serialize_map type SerializeMap: SerializeMap; - /// Type returned from `serialize_struct` for serializing the content of the - /// struct. + /// Type returned from [`serialize_struct`] for serializing the content of + /// the struct. + /// + /// [`serialize_struct`]: #tymethod.serialize_struct type SerializeStruct: SerializeStruct; - /// Type returned from `serialize_struct_variant` for serializing the + /// Type returned from [`serialize_struct_variant`] for serializing the /// content of the struct variant. + /// + /// [`serialize_struct_variant`]: #tymethod.serialize_struct_variant type SerializeStructVariant: SerializeStructVariant; /// Serialize a `bool` value. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for bool { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_bool(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_bool(self, v: bool) -> Result; /// Serialize an `i8` value. @@ -296,6 +390,25 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `i8` and `i64`, a /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for i8 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_i8(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_i8(self, v: i8) -> Result; /// Serialize an `i16` value. @@ -303,6 +416,25 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `i16` and `i64`, a /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for i16 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_i16(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_i16(self, v: i16) -> Result; /// Serialize an `i32` value. @@ -310,9 +442,47 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `i32` and `i64`, a /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for i32 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_i32(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_i32(self, v: i32) -> Result; /// Serialize an `i64` value. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for i64 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_i64(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_i64(self, v: i64) -> Result; /// Serialize a `u8` value. @@ -320,6 +490,25 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `u8` and `u64`, a /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for u8 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_u8(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_u8(self, v: u8) -> Result; /// Serialize a `u16` value. @@ -327,6 +516,25 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `u16` and `u64`, a /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for u16 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_u16(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_u16(self, v: u16) -> Result; /// Serialize a `u32` value. @@ -334,9 +542,47 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `u32` and `u64`, a /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for u32 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_u32(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_u32(self, v: u32) -> Result; /// Serialize a `u64` value. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for u64 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_u64(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_u64(self, v: u64) -> Result; /// Serialize an `f32` value. @@ -344,18 +590,94 @@ pub trait Serializer: Sized { /// If the format does not differentiate between `f32` and `f64`, a /// reasonable implementation would be to cast the value to `f64` and /// forward to `serialize_f64`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for f32 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_f32(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_f32(self, v: f32) -> Result; /// Serialize an `f64` value. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for f64 { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_f64(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_f64(self, v: f64) -> Result; /// Serialize a character. /// /// If the format does not support characters, it is reasonable to serialize /// it as a single element `str` or a `u32`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for char { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_char(*self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_char(self, v: char) -> Result; /// Serialize a `&str`. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for str { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_str(self) + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_str(self, value: &str) -> Result; /// Serialize a chunk of raw byte data. @@ -366,27 +688,145 @@ pub trait Serializer: Sized { /// `serialize_seq`. If forwarded, the implementation looks usually just /// like this: /// - /// ```rust,ignore - /// let mut seq = self.serialize_seq(Some(value.len()))?; - /// for b in value { - /// seq.serialize_element(b)?; + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::ser::{Serializer, SerializeSeq}; + /// # use serde::private::ser::Error; + /// # + /// # struct MySerializer; + /// # + /// # impl Serializer for MySerializer { + /// # type Ok = (); + /// # type Error = Error; + /// # + /// fn serialize_bytes(self, value: &[u8]) -> Result { + /// let mut seq = self.serialize_seq(Some(value.len()))?; + /// for b in value { + /// seq.serialize_element(b)?; + /// } + /// seq.end() /// } - /// seq.end() + /// # + /// # __serialize_unimplemented! { + /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str none some + /// # unit unit_struct unit_variant newtype_struct newtype_variant + /// # seq tuple tuple_struct tuple_variant map struct struct_variant + /// # } + /// # } + /// # + /// # fn main() {} /// ``` fn serialize_bytes(self, value: &[u8]) -> Result; - /// Serialize a `None` value. + /// Serialize a [`None`] value. + /// + /// ```rust + /// # extern crate serde; + /// # + /// # use serde::{Serialize, Serializer}; + /// # + /// # enum Option { + /// # Some(T), + /// # None, + /// # } + /// # + /// # use Option::{Some, None}; + /// # + /// impl Serialize for Option + /// where T: Serialize + /// { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match *self { + /// Some(ref value) => serializer.serialize_some(value), + /// None => serializer.serialize_none(), + /// } + /// } + /// } + /// # + /// # fn main() {} + /// ``` + /// + /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None fn serialize_none(self) -> Result; - /// Serialize a `Some(T)` value. - fn serialize_some(self, value: &T) -> Result; + /// Serialize a [`Some(T)`] value. + /// + /// ```rust + /// # extern crate serde; + /// # + /// # use serde::{Serialize, Serializer}; + /// # + /// # enum Option { + /// # Some(T), + /// # None, + /// # } + /// # + /// # use Option::{Some, None}; + /// # + /// impl Serialize for Option + /// where T: Serialize + /// { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match *self { + /// Some(ref value) => serializer.serialize_some(value), + /// None => serializer.serialize_none(), + /// } + /// } + /// } + /// # + /// # fn main() {} + /// ``` + /// + /// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some + fn serialize_some(self, value: &T) -> Result + where + T: Serialize; /// Serialize a `()` value. + /// + /// ```rust + /// # #[macro_use] + /// # extern crate serde; + /// # + /// # use serde::Serializer; + /// # + /// # __private_serialize!(); + /// # + /// impl Serialize for () { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_unit() + /// } + /// } + /// # + /// # fn main() {} + /// ``` fn serialize_unit(self) -> Result; /// Serialize a unit struct like `struct Unit` or `PhantomData`. /// /// A reasonable implementation would be to forward to `serialize_unit`. + /// + /// ```rust + /// use serde::{Serialize, Serializer}; + /// + /// struct Nothing; + /// + /// impl Serialize for Nothing { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_unit_struct("Nothing") + /// } + /// } + /// ``` fn serialize_unit_struct(self, name: &'static str) -> Result; /// Serialize a unit variant like `E::A` in `enum E { A, B }`. @@ -395,19 +835,31 @@ pub trait Serializer: Sized { /// this variant within the enum, and the `variant` is the name of the /// variant. /// - /// A reasonable implementation would be to forward to `serialize_unit`. + /// ```rust + /// use serde::{Serialize, Serializer}; /// - /// ```rust,ignore - /// match *self { - /// E::A => serializer.serialize_unit_variant("E", 0, "A"), - /// E::B => serializer.serialize_unit_variant("E", 1, "B"), + /// enum E { + /// A, + /// B, + /// } + /// + /// impl Serialize for E { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match *self { + /// E::A => serializer.serialize_unit_variant("E", 0, "A"), + /// E::B => serializer.serialize_unit_variant("E", 1, "B"), + /// } + /// } /// } /// ``` - fn serialize_unit_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str) - -> Result; + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result; /// Serialize a newtype struct like `struct Millimeters(u8)`. /// @@ -415,13 +867,26 @@ pub trait Serializer: Sized { /// wrappers around the data they contain. A reasonable implementation would /// be to forward to `value.serialize(self)`. /// - /// ```rust,ignore - /// serializer.serialize_newtype_struct("Millimeters", &self.0) + /// ```rust + /// use serde::{Serialize, Serializer}; + /// + /// struct Millimeters(u8); + /// + /// impl Serialize for Millimeters { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.serialize_newtype_struct("Millimeters", &self.0) + /// } + /// } /// ``` - fn serialize_newtype_struct(self, - name: &'static str, - value: &T) - -> Result; + fn serialize_newtype_struct( + self, + name: &'static str, + value: &T, + ) -> Result + where + T: Serialize; /// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`. /// @@ -429,19 +894,36 @@ pub trait Serializer: Sized { /// this variant within the enum, and the `variant` is the name of the /// variant. The `value` is the data contained within this newtype variant. /// - /// ```rust,ignore - /// match *self { - /// E::N(ref n) => serializer.serialize_newtype_variant("E", 0, "N", n), + /// ```rust + /// use serde::{Serialize, Serializer}; + /// + /// enum E { + /// M(String), + /// N(u8), + /// } + /// + /// impl Serialize for E { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match *self { + /// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s), + /// E::N(n) => serializer.serialize_newtype_variant("E", 1, "N", &n), + /// } + /// } /// } /// ``` - fn serialize_newtype_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str, - value: &T) - -> Result; + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize; - /// Begin to serialize a dynamically sized sequence. This call must be + /// Begin to serialize a variably sized sequence. This call must be /// followed by zero or more calls to `serialize_element`, then a call to /// `end`. /// @@ -449,12 +931,41 @@ pub trait Serializer: Sized { /// not be computable before the sequence is iterated. Some serializers only /// support sequences whose length is known up front. /// - /// ```rust,ignore - /// let mut seq = serializer.serialize_seq(Some(self.len()))?; - /// for element in self { - /// seq.serialize_element(element)?; + /// ```rust + /// # use std::marker::PhantomData; + /// # + /// # struct Vec(PhantomData); + /// # + /// # impl Vec { + /// # fn len(&self) -> usize { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # impl<'a, T> IntoIterator for &'a Vec { + /// # type Item = &'a T; + /// # type IntoIter = Box>; + /// # + /// # fn into_iter(self) -> Self::IntoIter { + /// # unimplemented!() + /// # } + /// # } + /// # + /// use serde::ser::{Serialize, Serializer, SerializeSeq}; + /// + /// impl Serialize for Vec + /// where T: Serialize + /// { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut seq = serializer.serialize_seq(Some(self.len()))?; + /// for element in self { + /// seq.serialize_element(element)?; + /// } + /// seq.end() + /// } /// } - /// seq.end() /// ``` fn serialize_seq(self, len: Option) -> Result; @@ -463,24 +974,51 @@ pub trait Serializer: Sized { /// This call must be followed by zero or more calls to `serialize_element`, /// then a call to `end`. /// - /// ```rust,ignore - /// let mut seq = serializer.serialize_seq_fixed_size(self.len())?; - /// for element in self { - /// seq.serialize_element(element)?; - /// } - /// seq.end() - /// ``` - fn serialize_seq_fixed_size(self, size: usize) -> Result; - - /// Begin to serialize a tuple. This call must be followed by zero or more - /// calls to `serialize_element`, then a call to `end`. + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// - /// ```rust,ignore - /// let mut tup = serializer.serialize_tuple(3)?; - /// tup.serialize_element(&self.0)?; - /// tup.serialize_element(&self.1)?; - /// tup.serialize_element(&self.2)?; - /// tup.end() + /// # mod fool { + /// # trait Serialize {} + /// impl Serialize for (A, B, C) + /// # {} + /// # } + /// # + /// # struct Tuple3(A, B, C); + /// # + /// # impl Serialize for Tuple3 + /// where A: Serialize, + /// B: Serialize, + /// C: Serialize + /// { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut tup = serializer.serialize_tuple(3)?; + /// tup.serialize_element(&self.0)?; + /// tup.serialize_element(&self.1)?; + /// tup.serialize_element(&self.2)?; + /// tup.end() + /// } + /// } + /// ``` + /// + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeTuple}; + /// + /// const VRAM_SIZE: usize = 386; + /// struct Vram([u16; VRAM_SIZE]); + /// + /// impl Serialize for Vram { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?; + /// for element in &self.0[..] { + /// seq.serialize_element(element)?; + /// } + /// seq.end() + /// } + /// } /// ``` fn serialize_tuple(self, len: usize) -> Result; @@ -491,17 +1029,28 @@ pub trait Serializer: Sized { /// The `name` is the name of the tuple struct and the `len` is the number /// of data fields that will be serialized. /// - /// ```rust,ignore - /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; - /// ts.serialize_field(&self.0)?; - /// ts.serialize_field(&self.1)?; - /// ts.serialize_field(&self.2)?; - /// ts.end() + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeTupleStruct}; + /// + /// struct Rgb(u8, u8, u8); + /// + /// impl Serialize for Rgb { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; + /// ts.serialize_field(&self.0)?; + /// ts.serialize_field(&self.1)?; + /// ts.serialize_field(&self.2)?; + /// ts.end() + /// } + /// } /// ``` - fn serialize_tuple_struct(self, - name: &'static str, - len: usize) - -> Result; + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result; /// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8) /// }`. This call must be followed by zero or more calls to @@ -511,22 +1060,43 @@ pub trait Serializer: Sized { /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// - /// ```rust,ignore - /// match *self { - /// E::T(ref a, ref b) => { - /// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; - /// tv.serialize_field(a)?; - /// tv.serialize_field(b)?; - /// tv.end() + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeTupleVariant}; + /// + /// enum E { + /// T(u8, u8), + /// U(String, u32, u32), + /// } + /// + /// impl Serialize for E { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match *self { + /// E::T(ref a, ref b) => { + /// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; + /// tv.serialize_field(a)?; + /// tv.serialize_field(b)?; + /// tv.end() + /// } + /// E::U(ref a, ref b, ref c) => { + /// let mut tv = serializer.serialize_tuple_variant("E", 1, "U", 3)?; + /// tv.serialize_field(a)?; + /// tv.serialize_field(b)?; + /// tv.serialize_field(c)?; + /// tv.end() + /// } + /// } /// } /// } /// ``` - fn serialize_tuple_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str, - len: usize) - -> Result; + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result; /// Begin to serialize a map. This call must be followed by zero or more /// calls to `serialize_key` and `serialize_value`, then a call to `end`. @@ -535,12 +1105,42 @@ pub trait Serializer: Sized { /// be computable before the map is iterated. Some serializers only support /// maps whose length is known up front. /// - /// ```rust,ignore - /// let mut map = serializer.serialize_map(Some(self.len()))?; - /// for (k, v) in self { - /// map.serialize_entry(k, v)?; + /// ```rust + /// # use std::marker::PhantomData; + /// # + /// # struct HashMap(PhantomData, PhantomData); + /// # + /// # impl HashMap { + /// # fn len(&self) -> usize { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # impl<'a, K, V> IntoIterator for &'a HashMap { + /// # type Item = (&'a K, &'a V); + /// # type IntoIter = Box>; + /// # + /// # fn into_iter(self) -> Self::IntoIter { + /// # unimplemented!() + /// # } + /// # } + /// # + /// use serde::ser::{Serialize, Serializer, SerializeMap}; + /// + /// impl Serialize for HashMap + /// where K: Serialize, + /// V: Serialize + /// { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut map = serializer.serialize_map(Some(self.len()))?; + /// for (k, v) in self { + /// map.serialize_entry(k, v)?; + /// } + /// map.end() + /// } /// } - /// map.end() /// ``` fn serialize_map(self, len: Option) -> Result; @@ -551,17 +1151,32 @@ pub trait Serializer: Sized { /// The `name` is the name of the struct and the `len` is the number of /// data fields that will be serialized. /// - /// ```rust,ignore - /// let mut struc = serializer.serialize_struct("Rgb", 3)?; - /// struc.serialize_field("r", &self.r)?; - /// struc.serialize_field("g", &self.g)?; - /// struc.serialize_field("b", &self.b)?; - /// struc.end() + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeStruct}; + /// + /// struct Rgb { + /// r: u8, + /// g: u8, + /// b: u8, + /// } + /// + /// impl Serialize for Rgb { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// let mut rgb = serializer.serialize_struct("Rgb", 3)?; + /// rgb.serialize_field("r", &self.r)?; + /// rgb.serialize_field("g", &self.g)?; + /// rgb.serialize_field("b", &self.b)?; + /// rgb.end() + /// } + /// } /// ``` - fn serialize_struct(self, - name: &'static str, - len: usize) - -> Result; + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result; /// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8, /// g: u8, b: u8 } }`. This call must be followed by zero or more calls to @@ -571,32 +1186,64 @@ pub trait Serializer: Sized { /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// - /// ```rust,ignore - /// match *self { - /// E::S { ref r, ref g, ref b } => { - /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; - /// sv.serialize_field("r", r)?; - /// sv.serialize_field("g", g)?; - /// sv.serialize_field("b", b)?; - /// sv.end() + /// ```rust + /// use serde::ser::{Serialize, Serializer, SerializeStructVariant}; + /// + /// enum E { + /// S { r: u8, g: u8, b: u8 } + /// } + /// + /// impl Serialize for E { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match *self { + /// E::S { ref r, ref g, ref b } => { + /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; + /// sv.serialize_field("r", r)?; + /// sv.serialize_field("g", g)?; + /// sv.serialize_field("b", b)?; + /// sv.end() + /// } + /// } /// } /// } /// ``` - fn serialize_struct_variant(self, - name: &'static str, - variant_index: usize, - variant: &'static str, - len: usize) - -> Result; + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result; /// Collect an iterator as a sequence. /// /// The default implementation serializes each item yielded by the iterator - /// using `Self::SerializeSeq`. Implementors should not need to override - /// this method. + /// using [`serialize_seq`]. Implementors should not need to override this + /// method. + /// + /// ```rust + /// use serde::{Serialize, Serializer}; + /// + /// struct SecretlyOneHigher { + /// data: Vec, + /// } + /// + /// impl Serialize for SecretlyOneHigher { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.collect_seq(self.data.iter().map(|x| x + 1)) + /// } + /// } + /// ``` + /// + /// [`serialize_seq`]: #tymethod.serialize_seq fn collect_seq(self, iter: I) -> Result - where I: IntoIterator, - ::Item: Serialize + where + I: IntoIterator, + ::Item: Serialize, { let iter = iter.into_iter(); let mut serializer = try!(self.serialize_seq(iter.len_hint())); @@ -609,12 +1256,33 @@ pub trait Serializer: Sized { /// Collect an iterator as a map. /// /// The default implementation serializes each pair yielded by the iterator - /// using `Self::SerializeMap`. Implementors should not need to override - /// this method. + /// using [`serialize_map`]. Implementors should not need to override this + /// method. + /// + /// ```rust + /// use std::collections::BTreeSet; + /// use serde::{Serialize, Serializer}; + /// + /// struct MapToUnit { + /// keys: BTreeSet, + /// } + /// + /// // Serializes as a map in which the values are all unit. + /// impl Serialize for MapToUnit { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// serializer.collect_map(self.keys.iter().map(|k| (k, ()))) + /// } + /// } + /// ``` + /// + /// [`serialize_map`]: #tymethod.serialize_map fn collect_map(self, iter: I) -> Result - where K: Serialize, - V: Serialize, - I: IntoIterator + where + K: Serialize, + V: Serialize, + I: IntoIterator, { let iter = iter.into_iter(); let mut serializer = try!(self.serialize_map(iter.len_hint())); @@ -626,17 +1294,20 @@ pub trait Serializer: Sized { /// Serialize a string produced by an implementation of `Display`. /// - /// The default implementation builds a heap-allocated `String` and - /// delegates to `serialize_str`. Serializers are encouraged to provide a + /// The default implementation builds a heap-allocated [`String`] and + /// delegates to [`serialize_str`]. Serializers are encouraged to provide a /// more efficient implementation if possible. /// /// ```rust - /// # use serde::{Serialize, Serializer}; /// # struct DateTime; + /// # /// # impl DateTime { /// # fn naive_local(&self) -> () { () } /// # fn offset(&self) -> () { () } /// # } + /// # + /// use serde::{Serialize, Serializer}; + /// /// impl Serialize for DateTime { /// fn serialize(&self, serializer: S) -> Result /// where S: Serializer @@ -647,10 +1318,15 @@ pub trait Serializer: Sized { /// } /// } /// ``` + /// + /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html + /// [`serialize_str`]: #tymethod.serialize_str #[cfg(any(feature = "std", feature = "collections"))] fn collect_str(self, value: &T) -> Result - where T: Display + where + T: Display, { + use lib::fmt::Write; let mut string = String::new(); write!(string, "{}", value).unwrap(); self.serialize_str(&string) @@ -658,16 +1334,20 @@ pub trait Serializer: Sized { /// Serialize a string produced by an implementation of `Display`. /// - /// The default implementation returns an error unconditionally when - /// compiled with `no_std`. + /// Serializers that use `no_std` are required to provide an implementation + /// of this method. If no more sensible behavior is possible, the + /// implementation is expected to return an error. /// /// ```rust - /// # use serde::{Serialize, Serializer}; /// # struct DateTime; + /// # /// # impl DateTime { /// # fn naive_local(&self) -> () { () } /// # fn offset(&self) -> () { () } /// # } + /// # + /// use serde::{Serialize, Serializer}; + /// /// impl Serialize for DateTime { /// fn serialize(&self, serializer: S) -> Result /// where S: Serializer @@ -680,24 +1360,46 @@ pub trait Serializer: Sized { /// ``` #[cfg(not(any(feature = "std", feature = "collections")))] fn collect_str(self, value: &T) -> Result - where T: Display - { - // TODO https://github.com/serde-rs/serde/issues/805 - // Remove this impl and force no_std formats to implement collect_str. - let _ = value; - Err(Error::custom("this no_std format does not support serializing strings with collect_str")) - } + where + T: Display; } -/// Returned from `Serializer::serialize_seq` and -/// `Serializer::serialize_seq_fixed_size`. +/// Returned from `Serializer::serialize_seq`. /// -/// ```rust,ignore -/// let mut seq = serializer.serialize_seq(Some(self.len()))?; -/// for element in self { -/// seq.serialize_element(element)?; +/// ```rust +/// # use std::marker::PhantomData; +/// # +/// # struct Vec(PhantomData); +/// # +/// # impl Vec { +/// # fn len(&self) -> usize { +/// # unimplemented!() +/// # } +/// # } +/// # +/// # impl<'a, T> IntoIterator for &'a Vec { +/// # type Item = &'a T; +/// # type IntoIter = Box>; +/// # fn into_iter(self) -> Self::IntoIter { +/// # unimplemented!() +/// # } +/// # } +/// # +/// use serde::ser::{Serialize, Serializer, SerializeSeq}; +/// +/// impl Serialize for Vec +/// where T: Serialize +/// { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// let mut seq = serializer.serialize_seq(Some(self.len()))?; +/// for element in self { +/// seq.serialize_element(element)?; +/// } +/// seq.end() +/// } /// } -/// seq.end() /// ``` pub trait SerializeSeq { /// Must match the `Ok` type of our `Serializer`. @@ -707,7 +1409,9 @@ pub trait SerializeSeq { type Error: Error; /// Serialize a sequence element. - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error>; + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize; /// Finish serializing a sequence. fn end(self) -> Result; @@ -715,12 +1419,74 @@ pub trait SerializeSeq { /// Returned from `Serializer::serialize_tuple`. /// -/// ```rust,ignore -/// let mut tup = serializer.serialize_tuple(3)?; -/// tup.serialize_element(&self.0)?; -/// tup.serialize_element(&self.1)?; -/// tup.serialize_element(&self.2)?; -/// tup.end() +/// ```rust +/// use serde::ser::{Serialize, Serializer, SerializeTuple}; +/// +/// # mod fool { +/// # trait Serialize {} +/// impl Serialize for (A, B, C) +/// # {} +/// # } +/// # +/// # struct Tuple3(A, B, C); +/// # +/// # impl Serialize for Tuple3 +/// where A: Serialize, +/// B: Serialize, +/// C: Serialize +/// { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// let mut tup = serializer.serialize_tuple(3)?; +/// tup.serialize_element(&self.0)?; +/// tup.serialize_element(&self.1)?; +/// tup.serialize_element(&self.2)?; +/// tup.end() +/// } +/// } +/// ``` +/// +/// ```rust +/// # use std::marker::PhantomData; +/// # +/// # struct Array(PhantomData); +/// # +/// # impl Array { +/// # fn len(&self) -> usize { +/// # unimplemented!() +/// # } +/// # } +/// # +/// # impl<'a, T> IntoIterator for &'a Array { +/// # type Item = &'a T; +/// # type IntoIter = Box>; +/// # fn into_iter(self) -> Self::IntoIter { +/// # unimplemented!() +/// # } +/// # } +/// # +/// use serde::ser::{Serialize, Serializer, SerializeTuple}; +/// +/// # mod fool { +/// # trait Serialize {} +/// impl Serialize for [T; 16] +/// # {} +/// # } +/// # +/// # impl Serialize for Array +/// where T: Serialize +/// { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// let mut seq = serializer.serialize_tuple(16)?; +/// for element in self { +/// seq.serialize_element(element)?; +/// } +/// seq.end() +/// } +/// } /// ``` pub trait SerializeTuple { /// Must match the `Ok` type of our `Serializer`. @@ -730,7 +1496,9 @@ pub trait SerializeTuple { type Error: Error; /// Serialize a tuple element. - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error>; + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize; /// Finish serializing a tuple. fn end(self) -> Result; @@ -738,12 +1506,22 @@ pub trait SerializeTuple { /// Returned from `Serializer::serialize_tuple_struct`. /// -/// ```rust,ignore -/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; -/// ts.serialize_field(&self.0)?; -/// ts.serialize_field(&self.1)?; -/// ts.serialize_field(&self.2)?; -/// ts.end() +/// ```rust +/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct}; +/// +/// struct Rgb(u8, u8, u8); +/// +/// impl Serialize for Rgb { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; +/// ts.serialize_field(&self.0)?; +/// ts.serialize_field(&self.1)?; +/// ts.serialize_field(&self.2)?; +/// ts.end() +/// } +/// } /// ``` pub trait SerializeTupleStruct { /// Must match the `Ok` type of our `Serializer`. @@ -753,7 +1531,9 @@ pub trait SerializeTupleStruct { type Error: Error; /// Serialize a tuple struct field. - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error>; + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize; /// Finish serializing a tuple struct. fn end(self) -> Result; @@ -761,13 +1541,33 @@ pub trait SerializeTupleStruct { /// Returned from `Serializer::serialize_tuple_variant`. /// -/// ```rust,ignore -/// match *self { -/// E::T(ref a, ref b) => { -/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; -/// tv.serialize_field(a)?; -/// tv.serialize_field(b)?; -/// tv.end() +/// ```rust +/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant}; +/// +/// enum E { +/// T(u8, u8), +/// U(String, u32, u32), +/// } +/// +/// impl Serialize for E { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// match *self { +/// E::T(ref a, ref b) => { +/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; +/// tv.serialize_field(a)?; +/// tv.serialize_field(b)?; +/// tv.end() +/// } +/// E::U(ref a, ref b, ref c) => { +/// let mut tv = serializer.serialize_tuple_variant("E", 1, "U", 3)?; +/// tv.serialize_field(a)?; +/// tv.serialize_field(b)?; +/// tv.serialize_field(c)?; +/// tv.end() +/// } +/// } /// } /// } /// ``` @@ -779,7 +1579,9 @@ pub trait SerializeTupleVariant { type Error: Error; /// Serialize a tuple variant field. - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error>; + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize; /// Finish serializing a tuple variant. fn end(self) -> Result; @@ -787,12 +1589,42 @@ pub trait SerializeTupleVariant { /// Returned from `Serializer::serialize_map`. /// -/// ```rust,ignore -/// let mut map = serializer.serialize_map(Some(self.len()))?; -/// for (k, v) in self { -/// map.serialize_entry(k, v)?; +/// ```rust +/// # use std::marker::PhantomData; +/// # +/// # struct HashMap(PhantomData, PhantomData); +/// # +/// # impl HashMap { +/// # fn len(&self) -> usize { +/// # unimplemented!() +/// # } +/// # } +/// # +/// # impl<'a, K, V> IntoIterator for &'a HashMap { +/// # type Item = (&'a K, &'a V); +/// # type IntoIter = Box>; +/// # +/// # fn into_iter(self) -> Self::IntoIter { +/// # unimplemented!() +/// # } +/// # } +/// # +/// use serde::ser::{Serialize, Serializer, SerializeMap}; +/// +/// impl Serialize for HashMap +/// where K: Serialize, +/// V: Serialize +/// { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// let mut map = serializer.serialize_map(Some(self.len()))?; +/// for (k, v) in self { +/// map.serialize_entry(k, v)?; +/// } +/// map.end() +/// } /// } -/// map.end() /// ``` pub trait SerializeMap { /// Must match the `Ok` type of our `Serializer`. @@ -802,28 +1634,41 @@ pub trait SerializeMap { type Error: Error; /// Serialize a map key. - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error>; + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: Serialize; /// Serialize a map value. - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error>; + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize; /// Serialize a map entry consisting of a key and a value. /// - /// Some `Serialize` types are not able to hold a key and value in memory at - /// the same time so `SerializeMap` implementations are required to support - /// `serialize_key` and `serialize_value` individually. The + /// Some [`Serialize`] types are not able to hold a key and value in memory + /// at the same time so `SerializeMap` implementations are required to + /// support [`serialize_key`] and [`serialize_value`] individually. The /// `serialize_entry` method allows serializers to optimize for the case - /// where key and value are both available. `Serialize` implementations are - /// encouraged to use `serialize_entry` if possible. + /// where key and value are both available. [`Serialize`] implementations + /// are encouraged to use `serialize_entry` if possible. /// - /// The default implementation delegates to `serialize_key` and - /// `serialize_value`. This is appropriate for serializers that do not care - /// about performance or are not able to optimize `serialize_entry` any + /// The default implementation delegates to [`serialize_key`] and + /// [`serialize_value`]. This is appropriate for serializers that do not + /// care about performance or are not able to optimize `serialize_entry` any /// better than this. - fn serialize_entry(&mut self, - key: &K, - value: &V) - -> Result<(), Self::Error> { + /// + /// [`Serialize`]: ../trait.Serialize.html + /// [`serialize_key`]: #tymethod.serialize_key + /// [`serialize_value`]: #tymethod.serialize_value + fn serialize_entry( + &mut self, + key: &K, + value: &V, + ) -> Result<(), Self::Error> + where + K: Serialize, + V: Serialize, + { try!(self.serialize_key(key)); self.serialize_value(value) } @@ -834,12 +1679,26 @@ pub trait SerializeMap { /// Returned from `Serializer::serialize_struct`. /// -/// ```rust,ignore -/// let mut struc = serializer.serialize_struct("Rgb", 3)?; -/// struc.serialize_field("r", &self.r)?; -/// struc.serialize_field("g", &self.g)?; -/// struc.serialize_field("b", &self.b)?; -/// struc.end() +/// ```rust +/// use serde::ser::{Serialize, Serializer, SerializeStruct}; +/// +/// struct Rgb { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// +/// impl Serialize for Rgb { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// let mut rgb = serializer.serialize_struct("Rgb", 3)?; +/// rgb.serialize_field("r", &self.r)?; +/// rgb.serialize_field("g", &self.g)?; +/// rgb.serialize_field("b", &self.b)?; +/// rgb.end() +/// } +/// } /// ``` pub trait SerializeStruct { /// Must match the `Ok` type of our `Serializer`. @@ -849,10 +1708,13 @@ pub trait SerializeStruct { type Error: Error; /// Serialize a struct field. - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), Self::Error>; + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize; /// Finish serializing a struct. fn end(self) -> Result; @@ -860,14 +1722,26 @@ pub trait SerializeStruct { /// Returned from `Serializer::serialize_struct_variant`. /// -/// ```rust,ignore -/// match *self { -/// E::S { ref r, ref g, ref b } => { -/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; -/// sv.serialize_field("r", r)?; -/// sv.serialize_field("g", g)?; -/// sv.serialize_field("b", b)?; -/// sv.end() +/// ```rust +/// use serde::ser::{Serialize, Serializer, SerializeStructVariant}; +/// +/// enum E { +/// S { r: u8, g: u8, b: u8 } +/// } +/// +/// impl Serialize for E { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer +/// { +/// match *self { +/// E::S { ref r, ref g, ref b } => { +/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; +/// sv.serialize_field("r", r)?; +/// sv.serialize_field("g", g)?; +/// sv.serialize_field("b", b)?; +/// sv.end() +/// } +/// } /// } /// } /// ``` @@ -879,10 +1753,13 @@ pub trait SerializeStructVariant { type Error: Error; /// Serialize a struct variant field. - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), Self::Error>; + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize; /// Finish serializing a struct variant. fn end(self) -> Result; @@ -892,7 +1769,10 @@ trait LenHint: Iterator { fn len_hint(&self) -> Option; } -impl LenHint for I { +impl LenHint for I +where + I: Iterator, +{ #[cfg(not(feature = "unstable"))] fn len_hint(&self) -> Option { iterator_len_hint(self) @@ -905,13 +1785,19 @@ impl LenHint for I { } #[cfg(feature = "unstable")] -impl LenHint for I { +impl LenHint for I +where + I: ExactSizeIterator, +{ fn len_hint(&self) -> Option { Some(self.len()) } } -fn iterator_len_hint(iter: &I) -> Option { +fn iterator_len_hint(iter: &I) -> Option +where + I: Iterator, +{ match iter.size_hint() { (lo, Some(hi)) if lo == hi => Some(lo), _ => None, diff --git a/serde/src/ser/private.rs b/serde/src/ser/private.rs deleted file mode 100644 index 0297c8ac..00000000 --- a/serde/src/ser/private.rs +++ /dev/null @@ -1,315 +0,0 @@ -use core::fmt::{self, Display}; - -use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible}; - -#[cfg(any(feature = "std", feature = "collections"))] -use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue}; - -/// Not public API. -pub fn serialize_tagged_newtype(serializer: S, - type_ident: &'static str, - variant_ident: &'static str, - tag: &'static str, - variant_name: &'static str, - value: &T) - -> Result - where S: Serializer, - T: Serialize -{ - value.serialize(TaggedSerializer { - type_ident: type_ident, - variant_ident: variant_ident, - tag: tag, - variant_name: variant_name, - delegate: serializer, - }) -} - -struct TaggedSerializer { - type_ident: &'static str, - variant_ident: &'static str, - tag: &'static str, - variant_name: &'static str, - delegate: S, -} - -enum Unsupported { - Boolean, - Integer, - Float, - Char, - String, - ByteArray, - Optional, - Unit, - UnitStruct, - Sequence, - Tuple, - TupleStruct, - #[cfg(not(any(feature = "std", feature = "collections")))] - Enum, -} - -impl Display for Unsupported { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match *self { - Unsupported::Boolean => formatter.write_str("a boolean"), - Unsupported::Integer => formatter.write_str("an integer"), - Unsupported::Float => formatter.write_str("a float"), - Unsupported::Char => formatter.write_str("a char"), - Unsupported::String => formatter.write_str("a string"), - Unsupported::ByteArray => formatter.write_str("a byte array"), - Unsupported::Optional => formatter.write_str("an optional"), - Unsupported::Unit => formatter.write_str("unit"), - Unsupported::UnitStruct => formatter.write_str("a unit struct"), - Unsupported::Sequence => formatter.write_str("a sequence"), - Unsupported::Tuple => formatter.write_str("a tuple"), - Unsupported::TupleStruct => formatter.write_str("a tuple struct"), - #[cfg(not(any(feature = "std", feature = "collections")))] - Unsupported::Enum => formatter.write_str("an enum"), - } - } -} - -struct Error { - type_ident: &'static str, - variant_ident: &'static str, - ty: Unsupported, -} - -impl Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, - "cannot serialize tagged newtype variant {}::{} containing {}", - self.type_ident, - self.variant_ident, - self.ty) - } -} - -impl TaggedSerializer - where S: Serializer -{ - fn bad_type(self, what: Unsupported) -> S::Error { - ser::Error::custom(Error { - type_ident: self.type_ident, - variant_ident: self.variant_ident, - ty: what, - }) - } -} - -impl Serializer for TaggedSerializer - where S: Serializer -{ - type Ok = S::Ok; - type Error = S::Error; - - type SerializeSeq = Impossible; - type SerializeTuple = Impossible; - type SerializeTupleStruct = Impossible; - type SerializeMap = S::SerializeMap; - type SerializeStruct = S::SerializeStruct; - - #[cfg(not(any(feature = "std", feature = "collections")))] - type SerializeTupleVariant = Impossible; - #[cfg(any(feature = "std", feature = "collections"))] - type SerializeTupleVariant = SerializeTupleVariantAsMapValue; - - #[cfg(not(any(feature = "std", feature = "collections")))] - type SerializeStructVariant = Impossible; - #[cfg(any(feature = "std", feature = "collections"))] - type SerializeStructVariant = SerializeStructVariantAsMapValue; - - fn serialize_bool(self, _: bool) -> Result { - Err(self.bad_type(Unsupported::Boolean)) - } - - fn serialize_i8(self, _: i8) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_i16(self, _: i16) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_i32(self, _: i32) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_i64(self, _: i64) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_u8(self, _: u8) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_u16(self, _: u16) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_u32(self, _: u32) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_u64(self, _: u64) -> Result { - Err(self.bad_type(Unsupported::Integer)) - } - - fn serialize_f32(self, _: f32) -> Result { - Err(self.bad_type(Unsupported::Float)) - } - - fn serialize_f64(self, _: f64) -> Result { - Err(self.bad_type(Unsupported::Float)) - } - - fn serialize_char(self, _: char) -> Result { - Err(self.bad_type(Unsupported::Char)) - } - - fn serialize_str(self, _: &str) -> Result { - Err(self.bad_type(Unsupported::String)) - } - - fn serialize_bytes(self, _: &[u8]) -> Result { - Err(self.bad_type(Unsupported::ByteArray)) - } - - fn serialize_none(self) -> Result { - Err(self.bad_type(Unsupported::Optional)) - } - - fn serialize_some(self, _: &T) -> Result - where T: Serialize - { - Err(self.bad_type(Unsupported::Optional)) - } - - fn serialize_unit(self) -> Result { - Err(self.bad_type(Unsupported::Unit)) - } - - fn serialize_unit_struct(self, _: &'static str) -> Result { - Err(self.bad_type(Unsupported::UnitStruct)) - } - - fn serialize_unit_variant(self, - _: &'static str, - _: usize, - inner_variant: &'static str) - -> Result { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_entry(inner_variant, &())); - map.end() - } - - fn serialize_newtype_struct(self, - _: &'static str, - value: &T) - -> Result - where T: Serialize - { - value.serialize(self) - } - - fn serialize_newtype_variant(self, - _: &'static str, - _: usize, - inner_variant: &'static str, - inner_value: &T) - -> Result - where T: Serialize - { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_entry(inner_variant, inner_value)); - map.end() - } - - fn serialize_seq(self, _: Option) -> Result { - Err(self.bad_type(Unsupported::Sequence)) - } - - fn serialize_seq_fixed_size(self, _: usize) -> Result { - Err(self.bad_type(Unsupported::Sequence)) - } - - fn serialize_tuple(self, _: usize) -> Result { - Err(self.bad_type(Unsupported::Tuple)) - } - - fn serialize_tuple_struct(self, - _: &'static str, - _: usize) - -> Result { - Err(self.bad_type(Unsupported::TupleStruct)) - } - - #[cfg(not(any(feature = "std", feature = "collections")))] - fn serialize_tuple_variant(self, - _: &'static str, - _: usize, - _: &'static str, - _: usize) - -> Result { - // Lack of push-based serialization means we need to buffer the content - // of the tuple variant, so it requires std. - Err(self.bad_type(Unsupported::Enum)) - } - - #[cfg(any(feature = "std", feature = "collections"))] - fn serialize_tuple_variant(self, - _: &'static str, - _: usize, - inner_variant: &'static str, - len: usize) - -> Result { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_key(inner_variant)); - Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len)) - } - - fn serialize_map(self, len: Option) -> Result { - let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1))); - try!(map.serialize_entry(self.tag, self.variant_name)); - Ok(map) - } - - fn serialize_struct(self, - name: &'static str, - len: usize) - -> Result { - let mut state = try!(self.delegate.serialize_struct(name, len + 1)); - try!(state.serialize_field(self.tag, self.variant_name)); - Ok(state) - } - - #[cfg(not(any(feature = "std", feature = "collections")))] - fn serialize_struct_variant(self, - _: &'static str, - _: usize, - _: &'static str, - _: usize) - -> Result { - // Lack of push-based serialization means we need to buffer the content - // of the struct variant, so it requires std. - Err(self.bad_type(Unsupported::Enum)) - } - - #[cfg(any(feature = "std", feature = "collections"))] - fn serialize_struct_variant(self, - _: &'static str, - _: usize, - inner_variant: &'static str, - len: usize) - -> Result { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_key(inner_variant)); - Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len)) - } -} diff --git a/serde/src/utils.rs b/serde/src/utils.rs deleted file mode 100644 index 927d1256..00000000 --- a/serde/src/utils.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Private utility functions - -const TAG_CONT: u8 = 0b1000_0000; -const TAG_TWO_B: u8 = 0b1100_0000; -const TAG_THREE_B: u8 = 0b1110_0000; -const TAG_FOUR_B: u8 = 0b1111_0000; -const MAX_ONE_B: u32 = 0x80; -const MAX_TWO_B: u32 = 0x800; -const MAX_THREE_B: u32 = 0x10000; - -#[inline] -pub fn encode_utf8(c: char) -> EncodeUtf8 { - let code = c as u32; - let mut buf = [0; 4]; - let pos = if code < MAX_ONE_B { - buf[3] = code as u8; - 3 - } else if code < MAX_TWO_B { - buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 2 - } else if code < MAX_THREE_B { - buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 1 - } else { - buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; - buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 0 - }; - EncodeUtf8 { - buf: buf, - pos: pos, - } -} - -pub struct EncodeUtf8 { - buf: [u8; 4], - pos: usize, -} - -impl EncodeUtf8 { - // FIXME: use this from_utf8_unchecked, since we know it can never fail - pub fn as_str(&self) -> &str { - ::core::str::from_utf8(&self.buf[self.pos..]).unwrap() - } -} - -#[allow(non_upper_case_globals)] -const Pattern_White_Space_table: &'static [(char, char)] = &[('\u{9}', '\u{d}'), - ('\u{20}', '\u{20}'), - ('\u{85}', '\u{85}'), - ('\u{200e}', '\u{200f}'), - ('\u{2028}', '\u{2029}')]; - -fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool { - use core::cmp::Ordering::{Equal, Less, Greater}; - r.binary_search_by(|&(lo, hi)| if c < lo { - Greater - } else if hi < c { - Less - } else { - Equal - }) - .is_ok() -} - -#[allow(non_snake_case)] -pub fn Pattern_White_Space(c: char) -> bool { - bsearch_range_table(c, Pattern_White_Space_table) -} diff --git a/serde_codegen_internals/src/lib.rs b/serde_codegen_internals/src/lib.rs deleted file mode 100644 index c5e8885c..00000000 --- a/serde_codegen_internals/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -extern crate syn; - -pub mod ast; -pub mod attr; - -mod ctxt; -pub use ctxt::Ctxt; - -mod case; diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 9117ece9..8c8d147f 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.9.14" +version = "0.9.14" # remember to update html_root_url authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -8,11 +8,9 @@ homepage = "https://serde.rs" repository = "https://github.com/serde-rs/serde" documentation = "https://serde.rs/codegen.html" keywords = ["serde", "serialization", "no_std"] -readme = "../README.md" +readme = "README.md" include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] - -[features] -unstable = [] +publish = false # this branch contains breaking changes [badges] travis-ci = { repository = "serde-rs/serde" } @@ -23,5 +21,5 @@ proc-macro = true [dependencies] quote = "0.3.8" -serde_codegen_internals = { version = "=0.14.2", default-features = false, path = "../serde_codegen_internals" } +serde_derive_internals = { version = "=0.14.2", default-features = false, path = "../serde_derive_internals" } syn = { version = "0.11", features = ["visit"] } diff --git a/serde_derive/src/bound.rs b/serde_derive/src/bound.rs index 2fe797a1..f77bede5 100644 --- a/serde_derive/src/bound.rs +++ b/serde_derive/src/bound.rs @@ -1,33 +1,21 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::collections::HashSet; use syn::{self, visit}; -use internals::ast::Item; +use internals::ast::Container; use internals::attr; macro_rules! path { - ($first:ident $(:: $rest:ident)*) => { - syn::Path { - global: false, - segments: vec![ - stringify!($first).into(), - $( - stringify!($rest).into(), - )* - ], - } - }; - - (::$first:ident $(:: $rest:ident)*) => { - syn::Path { - global: true, - segments: vec![ - stringify!($first).into(), - $( - stringify!($rest).into(), - )* - ], - } + ($($path:tt)+) => { + syn::parse_path(stringify!($($path)+)).unwrap() }; } @@ -36,29 +24,43 @@ macro_rules! path { // allowed here". pub fn without_defaults(generics: &syn::Generics) -> syn::Generics { syn::Generics { - ty_params: generics.ty_params + ty_params: generics + .ty_params .iter() - .map(|ty_param| syn::TyParam { default: None, ..ty_param.clone() }) + .map( + |ty_param| { + syn::TyParam { + default: None, + ..ty_param.clone() + } + }, + ) .collect(), ..generics.clone() } } -pub fn with_where_predicates(generics: &syn::Generics, - predicates: &[syn::WherePredicate]) - -> syn::Generics { +pub fn with_where_predicates( + generics: &syn::Generics, + predicates: &[syn::WherePredicate], +) -> syn::Generics { let mut generics = generics.clone(); - generics.where_clause.predicates.extend_from_slice(predicates); + generics + .where_clause + .predicates + .extend_from_slice(predicates); generics } -pub fn with_where_predicates_from_fields(item: &Item, - generics: &syn::Generics, - from_field: F) - -> syn::Generics - where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]> +pub fn with_where_predicates_from_fields( + cont: &Container, + generics: &syn::Generics, + from_field: F, +) -> syn::Generics +where + F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>, { - let predicates = item.body + let predicates = cont.body .all_fields() .flat_map(|field| from_field(&field.attrs)) .flat_map(|predicates| predicates.to_vec()); @@ -79,12 +81,14 @@ pub fn with_where_predicates_from_fields(item: &Item, // #[serde(skip_serializing)] // c: C, // } -pub fn with_bound(item: &Item, - generics: &syn::Generics, - filter: F, - bound: &syn::Path) - -> syn::Generics - where F: Fn(&attr::Field) -> bool +pub fn with_bound( + cont: &Container, + generics: &syn::Generics, + filter: F, + bound: &syn::Path, +) -> syn::Generics +where + F: Fn(&attr::Field) -> bool, { struct FindTyParams { // Set of all generic type parameters on the current struct (A, B, C in @@ -114,12 +118,13 @@ pub fn with_bound(item: &Item, } } - let all_ty_params: HashSet<_> = generics.ty_params + let all_ty_params: HashSet<_> = generics + .ty_params .iter() .map(|ty_param| ty_param.ident.clone()) .collect(); - let relevant_tys = item.body + let relevant_tys = cont.body .all_fields() .filter(|&field| filter(&field.attrs)) .map(|field| &field.ty); @@ -132,58 +137,66 @@ pub fn with_bound(item: &Item, visit::walk_ty(&mut visitor, ty); } - let new_predicates = generics.ty_params + let new_predicates = generics + .ty_params .iter() .map(|ty_param| ty_param.ident.clone()) .filter(|id| visitor.relevant_ty_params.contains(id)) - .map(|id| { - syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate { - bound_lifetimes: Vec::new(), - // the type parameter that is being bounded e.g. T - bounded_ty: syn::Ty::Path(None, id.into()), - // the bound e.g. Serialize - bounds: vec![syn::TyParamBound::Trait( - syn::PolyTraitRef { + .map( + |id| { + syn::WherePredicate::BoundPredicate( + syn::WhereBoundPredicate { bound_lifetimes: Vec::new(), - trait_ref: bound.clone(), + // the type parameter that is being bounded e.g. T + bounded_ty: syn::Ty::Path(None, id.into()), + // the bound e.g. Serialize + bounds: vec![ + syn::TyParamBound::Trait( + syn::PolyTraitRef { + bound_lifetimes: Vec::new(), + trait_ref: bound.clone(), + }, + syn::TraitBoundModifier::None, + ), + ], }, - syn::TraitBoundModifier::None - )], - }) - }); + ) + }, + ); let mut generics = generics.clone(); generics.where_clause.predicates.extend(new_predicates); generics } -pub fn with_self_bound(item: &Item, - generics: &syn::Generics, - bound: &syn::Path) - -> syn::Generics -{ +pub fn with_self_bound(cont: &Container, generics: &syn::Generics, bound: &syn::Path) -> syn::Generics { let mut generics = generics.clone(); - generics.where_clause.predicates.push( - syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate { - bound_lifetimes: Vec::new(), - // the type that is being bounded e.g. MyStruct<'a, T> - bounded_ty: type_of_item(item), - // the bound e.g. Default - bounds: vec![syn::TyParamBound::Trait( - syn::PolyTraitRef { + generics + .where_clause + .predicates + .push( + syn::WherePredicate::BoundPredicate( + syn::WhereBoundPredicate { bound_lifetimes: Vec::new(), - trait_ref: bound.clone(), + // the type that is being bounded e.g. MyStruct<'a, T> + bounded_ty: type_of_item(cont), + // the bound e.g. Default + bounds: vec![ + syn::TyParamBound::Trait( + syn::PolyTraitRef { + bound_lifetimes: Vec::new(), + trait_ref: bound.clone(), + }, + syn::TraitBoundModifier::None, + ), + ], }, - syn::TraitBoundModifier::None - )], - }) - ); + ), + ); generics } -pub fn with_lifetime_bound(generics: &syn::Generics, - lifetime: &str) - -> syn::Generics { +pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics { let mut generics = generics.clone(); for lifetime_def in &mut generics.lifetimes { @@ -191,38 +204,49 @@ pub fn with_lifetime_bound(generics: &syn::Generics, } for ty_param in &mut generics.ty_params { - ty_param.bounds.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime))); + ty_param + .bounds + .push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime))); } - generics.lifetimes.push(syn::LifetimeDef { - attrs: Vec::new(), - lifetime: syn::Lifetime::new(lifetime), - bounds: Vec::new(), - }); + generics + .lifetimes + .push( + syn::LifetimeDef { + attrs: Vec::new(), + lifetime: syn::Lifetime::new(lifetime), + bounds: Vec::new(), + }, + ); generics } -fn type_of_item(item: &Item) -> syn::Ty { - syn::Ty::Path(None, syn::Path { - global: false, - segments: vec![ - syn::PathSegment { - ident: item.ident.clone(), - parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData { - lifetimes: item.generics - .lifetimes - .iter() - .map(|def| def.lifetime.clone()) - .collect(), - types: item.generics +fn type_of_item(cont: &Container) -> syn::Ty { + syn::Ty::Path( + None, + syn::Path { + global: false, + segments: vec![ + syn::PathSegment { + ident: cont.ident.clone(), + parameters: syn::PathParameters::AngleBracketed( + syn::AngleBracketedParameterData { + lifetimes: cont.generics + .lifetimes + .iter() + .map(|def| def.lifetime.clone()) + .collect(), + types: cont.generics .ty_params .iter() .map(|param| syn::Ty::Path(None, param.ident.clone().into())) .collect(), - bindings: Vec::new(), - }), - } - ] - }) + bindings: Vec::new(), + }, + ), + }, + ], + }, + ) } diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 637efb51..c0b32f36 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1,71 +1,156 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use syn::{self, Ident}; -use quote::{self, Tokens}; +use quote::{self, Tokens, ToTokens}; use bound; use fragment::{Fragment, Expr, Stmts, Match}; -use internals::ast::{Body, Field, Item, Style, Variant}; +use internals::ast::{Body, Container, Field, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_deserialize(item: &syn::DeriveInput) -> Result { - let item = { - let ctxt = internals::Ctxt::new(); - let item = Item::from_ast(&ctxt, item); - check_no_str(&ctxt, &item); - try!(ctxt.check()); - item - }; +use std::collections::BTreeSet; - let ident = &item.ident; - let generics = build_generics(&item); - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result { + let ctxt = internals::Ctxt::new(); + let cont = Container::from_ast(&ctxt, input); + try!(ctxt.check()); + + let ident = &cont.ident; + let params = Parameters::new(&cont); let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident)); - let body = Stmts(deserialize_body(&item, &generics)); + let body = Stmts(deserialize_body(&cont, ¶ms)); - Ok(quote! { - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const #dummy_const: () = { - extern crate serde as _serde; - #[automatically_derived] - impl #impl_generics _serde::Deserialize for #ident #ty_generics #where_clause { - fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result - where __D: _serde::Deserializer + let impl_block = if let Some(remote) = cont.attrs.remote() { + let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl(); + let de_lifetime = params.de_lifetime_def(); + quote! { + impl #impl_generics #ident #ty_generics #where_clause { + fn deserialize<#de_lifetime, __D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error> + where __D: _serde::Deserializer<'de> { #body } } + } + } else { + let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms); + quote! { + #[automatically_derived] + impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause { + fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result + where __D: _serde::Deserializer<'de> + { + #body + } + } + } + }; + + Ok( + quote! { + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + const #dummy_const: () = { + extern crate serde as _serde; + #impl_block }; - }) + }, + ) +} + +struct Parameters { + /// Name of the type the `derive` is on. + local: syn::Ident, + + /// Path to the type the impl is for. Either a single `Ident` for local + /// types or `some::remote::Ident` for remote types. Does not include + /// generic parameters. + this: syn::Path, + + /// Generics including any explicit and inferred bounds for the impl. + generics: syn::Generics, + + /// Lifetimes borrowed from the deserializer. These will become bounds on + /// the `'de` lifetime of the deserializer. + borrowed: BTreeSet, + + /// At least one field has a serde(getter) attribute, implying that the + /// remote type has a private field. + has_getter: bool, +} + +impl Parameters { + fn new(cont: &Container) -> Self { + let local = cont.ident.clone(); + let this = match cont.attrs.remote() { + Some(remote) => remote.clone(), + None => cont.ident.clone().into(), + }; + let generics = build_generics(cont); + let borrowed = borrowed_lifetimes(cont); + let has_getter = cont.body.has_getter(); + + Parameters { + local: local, + this: this, + generics: generics, + borrowed: borrowed, + has_getter: has_getter, + } + } + + /// Type name to use in error messages and `&'static str` arguments to + /// various Deserializer methods. + fn type_name(&self) -> &str { + self.this.segments.last().unwrap().ident.as_ref() + } + + fn de_lifetime_def(&self) -> syn::LifetimeDef { + syn::LifetimeDef { + attrs: Vec::new(), + lifetime: syn::Lifetime::new("'de"), + bounds: self.borrowed.iter().cloned().collect(), + } + } } // All the generics in the input, plus a bound `T: Deserialize` for each generic // field type that will be deserialized by us, plus a bound `T: Default` for // each generic field type that will be set to a default value. -fn build_generics(item: &Item) -> syn::Generics { - let generics = bound::without_defaults(item.generics); +fn build_generics(cont: &Container) -> syn::Generics { + let generics = bound::without_defaults(cont.generics); - let generics = - bound::with_where_predicates_from_fields(item, &generics, attr::Field::de_bound); + let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::de_bound); - match item.attrs.de_bound() { + match cont.attrs.de_bound() { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => { - let generics = match *item.attrs.default() { + let generics = match *cont.attrs.default() { attr::Default::Default => { - bound::with_self_bound(item, &generics, &path!(_serde::export::Default)) + bound::with_self_bound(cont, &generics, &path!(_serde::export::Default)) } - attr::Default::None | attr::Default::Path(_) => generics, + attr::Default::None | + attr::Default::Path(_) => generics, }; - let generics = - bound::with_bound(item, - &generics, - needs_deserialize_bound, - &path!(_serde::Deserialize)); + let generics = bound::with_bound( + cont, + &generics, + needs_deserialize_bound, + &path!(_serde::Deserialize<'de>), + ); - bound::with_bound(item, - &generics, - requires_default, - &path!(_serde::export::Default)) + bound::with_bound( + cont, + &generics, + requires_default, + &path!(_serde::export::Default), + ) } } } @@ -84,38 +169,47 @@ fn requires_default(attrs: &attr::Field) -> bool { attrs.default() == &attr::Default::Default } -fn deserialize_body(item: &Item, generics: &syn::Generics) -> Fragment { - if let Some(from_type) = item.attrs.from_type() { +// The union of lifetimes borrowed by each field of the container. +// +// These turn into bounds on the `'de` lifetime of the Deserialize impl. If +// lifetimes `'a` and `'b` are borrowed but `'c` is not, the impl is: +// +// impl<'de: 'a + 'b, 'a, 'b, 'c> Deserialize<'de> for S<'a, 'b, 'c> +fn borrowed_lifetimes(cont: &Container) -> BTreeSet { + let mut lifetimes = BTreeSet::new(); + for field in cont.body.all_fields() { + lifetimes.extend(field.attrs.borrowed_lifetimes().iter().cloned()); + } + lifetimes +} + +fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { + if let Some(from_type) = cont.attrs.from_type() { deserialize_from(from_type) - } else { - match item.body { - Body::Enum(ref variants) => { - deserialize_item_enum(&item.ident, generics, variants, &item.attrs) - } + } else if let attr::Identifier::No = cont.attrs.identifier() { + match cont.body { + Body::Enum(ref variants) => deserialize_enum(params, variants, &cont.attrs), Body::Struct(Style::Struct, ref fields) => { if fields.iter().any(|field| field.ident.is_none()) { panic!("struct has unnamed fields"); } - deserialize_struct(&item.ident, - None, - generics, - fields, - &item.attrs, - None) + deserialize_struct(None, params, fields, &cont.attrs, None) } Body::Struct(Style::Tuple, ref fields) | Body::Struct(Style::Newtype, ref fields) => { if fields.iter().any(|field| field.ident.is_some()) { panic!("tuple struct has named fields"); } - deserialize_tuple(&item.ident, - None, - generics, - fields, - &item.attrs, - None) + deserialize_tuple(None, params, fields, &cont.attrs, None) } - Body::Struct(Style::Unit, _) => deserialize_unit_struct(&item.ident, &item.attrs), + Body::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs), + } + } else { + match cont.body { + Body::Enum(ref variants) => { + deserialize_custom_identifier(params, variants, &cont.attrs) + } + Body::Struct(_, _) => unreachable!("checked in serde_derive_internals"), } } } @@ -128,33 +222,27 @@ fn deserialize_from(from_type: &syn::Ty) -> Fragment { } } -fn deserialize_unit_struct(ident: &syn::Ident, item_attrs: &attr::Item) -> Fragment { - let type_name = item_attrs.name().deserialize_name(); +fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment { + let this = ¶ms.this; + let type_name = cattrs.name().deserialize_name(); - let expecting = format!("unit struct {}", ident); + let expecting = format!("unit struct {}", params.type_name()); quote_block! { struct __Visitor; - impl _serde::de::Visitor for __Visitor { - type Value = #ident; + impl<'de> _serde::de::Visitor<'de> for __Visitor { + type Value = #this; - fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { - _serde::export::fmt::Formatter::write_str(formatter, #expecting) + fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(formatter, #expecting) } #[inline] - fn visit_unit<__E>(self) -> _serde::export::Result<#ident, __E> + fn visit_unit<__E>(self) -> _serde::export::Result where __E: _serde::de::Error { - _serde::export::Ok(#ident) - } - - #[inline] - fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#ident, __V::Error> - where __V: _serde::de::SeqVisitor - { - _serde::export::Ok(#ident) + _serde::export::Ok(#this) } } @@ -162,74 +250,91 @@ fn deserialize_unit_struct(ident: &syn::Ident, item_attrs: &attr::Item) -> Fragm } } -fn deserialize_tuple(ident: &syn::Ident, - variant_ident: Option<&syn::Ident>, - generics: &syn::Generics, - fields: &[Field], - item_attrs: &attr::Item, - deserializer: Option) - -> Fragment { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +fn deserialize_tuple( + variant_ident: Option<&syn::Ident>, + params: &Parameters, + fields: &[Field], + cattrs: &attr::Container, + deserializer: Option, +) -> Fragment { + let this = ¶ms.this; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params,); + + // If there are getters (implying private fields), construct the local type + // and use an `Into` conversion to get the remote type. If there are no + // getters then construct the target type directly. + let construct = if params.has_getter { + let local = ¶ms.local; + quote!(#local) + } else { + quote!(#this) + }; let is_enum = variant_ident.is_some(); let type_path = match variant_ident { - Some(variant_ident) => quote!(#ident::#variant_ident), - None => quote!(#ident), + Some(variant_ident) => quote!(#construct::#variant_ident), + None => construct, }; let expecting = match variant_ident { - Some(variant_ident) => format!("tuple variant {}::{}", ident, variant_ident), - None => format!("tuple struct {}", ident), + Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), + None => format!("tuple struct {}", params.type_name()), }; let nfields = fields.len(); let visit_newtype_struct = if !is_enum && nfields == 1 { - Some(deserialize_newtype_struct(ident, &type_path, generics, &fields[0])) + Some(deserialize_newtype_struct(&type_path, params, &fields[0])) } else { None }; - let visit_seq = Stmts(deserialize_seq(ident, &type_path, generics, fields, false, item_attrs)); + let visit_seq = Stmts(deserialize_seq(&type_path, params, fields, false, cattrs),); let visitor_expr = quote! { - __Visitor { marker: _serde::export::PhantomData::<#ident #ty_generics> } + __Visitor { + marker: _serde::export::PhantomData::<#this #ty_generics>, + lifetime: _serde::export::PhantomData, + } }; let dispatch = if let Some(deserializer) = deserializer { quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) } else if is_enum { - quote!(_serde::de::VariantVisitor::visit_tuple(__visitor, #nfields, #visitor_expr)) + quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) } else if nfields == 1 { - let type_name = item_attrs.name().deserialize_name(); + let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { - let type_name = item_attrs.name().deserialize_name(); + let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); + let all_skipped = fields + .iter() + .all(|field| field.attrs.skip_deserializing()); let visitor_var = if all_skipped { quote!(_) } else { - quote!(mut __visitor) + quote!(mut __seq) }; quote_block! { - struct __Visitor #impl_generics #where_clause { - marker: _serde::export::PhantomData<#ident #ty_generics>, + struct __Visitor #de_impl_generics #where_clause { + marker: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, } - impl #impl_generics _serde::de::Visitor for __Visitor #ty_generics #where_clause { - type Value = #ident #ty_generics; + impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { + type Value = #this #ty_generics; - fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { - _serde::export::fmt::Formatter::write_str(formatter, #expecting) + fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(formatter, #expecting) } #visit_newtype_struct #[inline] - fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result - where __V: _serde::de::SeqVisitor + fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result + where __A: _serde::de::SeqAccess<'de> { #visit_seq } @@ -239,16 +344,17 @@ fn deserialize_tuple(ident: &syn::Ident, } } -fn deserialize_seq(ident: &syn::Ident, - type_path: &Tokens, - generics: &syn::Generics, - fields: &[Field], - is_struct: bool, - item_attrs: &attr::Item) - -> Fragment { +fn deserialize_seq( + type_path: &Tokens, + params: &Parameters, + fields: &[Field], + is_struct: bool, + cattrs: &attr::Container, +) -> Fragment { let vars = (0..fields.len()).map(field_i as fn(_) -> _); - let deserialized_count = fields.iter() + let deserialized_count = fields + .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let expecting = format!("tuple of {} elements", deserialized_count); @@ -257,7 +363,7 @@ fn deserialize_seq(ident: &syn::Ident, let let_values = vars.clone().zip(fields) .map(|(var, field)| { if field.attrs.skip_deserializing() { - let default = Expr(expr_is_missing(&field, item_attrs)); + let default = Expr(expr_is_missing(&field, cattrs)); quote! { let #var = #default; } @@ -265,15 +371,15 @@ fn deserialize_seq(ident: &syn::Ident, let visit = match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; - quote!(try!(_serde::de::SeqVisitor::visit::<#field_ty>(&mut __visitor))) + quote!(try!(_serde::de::SeqAccess::next_element::<#field_ty>(&mut __seq))) } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_with( - ident, generics, field.ty, path); + params, field.ty, path); quote!({ #wrapper _serde::export::Option::map( - try!(_serde::de::SeqVisitor::visit::<#wrapper_ty>(&mut __visitor)), + try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)), |__wrap| __wrap.value) }) } @@ -291,7 +397,7 @@ fn deserialize_seq(ident: &syn::Ident, } }); - let result = if is_struct { + let mut result = if is_struct { let names = fields.iter().map(|f| &f.ident); quote! { #type_path { #( #names: #vars ),* } @@ -302,17 +408,20 @@ fn deserialize_seq(ident: &syn::Ident, } }; + if params.has_getter { + let this = ¶ms.this; + result = quote! { + _serde::export::Into::<#this>::into(#result) + }; + } + quote_block! { #(#let_values)* _serde::export::Ok(#result) } } -fn deserialize_newtype_struct(ident: &syn::Ident, - type_path: &Tokens, - generics: &syn::Generics, - field: &Field) - -> Tokens { +fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &Field) -> Tokens { let value = match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; @@ -321,76 +430,100 @@ fn deserialize_newtype_struct(ident: &syn::Ident, } } Some(path) => { - let (wrapper, wrapper_ty) = - wrap_deserialize_with(ident, generics, field.ty, path); + let (wrapper, wrapper_ty) = wrap_deserialize_with(params, field.ty, path); quote!({ #wrapper try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value }) } }; + + let mut result = quote!(#type_path(#value)); + if params.has_getter { + let this = ¶ms.this; + result = quote! { + _serde::export::Into::<#this>::into(#result) + }; + } + quote! { #[inline] fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result - where __E: _serde::Deserializer + where __E: _serde::Deserializer<'de> { - _serde::export::Ok(#type_path(#value)) + _serde::export::Ok(#result) } } } -fn deserialize_struct(ident: &syn::Ident, - variant_ident: Option<&syn::Ident>, - generics: &syn::Generics, - fields: &[Field], - item_attrs: &attr::Item, - deserializer: Option) - -> Fragment { +fn deserialize_struct( + variant_ident: Option<&syn::Ident>, + params: &Parameters, + fields: &[Field], + cattrs: &attr::Container, + deserializer: Option, +) -> Fragment { let is_enum = variant_ident.is_some(); let is_untagged = deserializer.is_some(); - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let this = ¶ms.this; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params,); + + // If there are getters (implying private fields), construct the local type + // and use an `Into` conversion to get the remote type. If there are no + // getters then construct the target type directly. + let construct = if params.has_getter { + let local = ¶ms.local; + quote!(#local) + } else { + quote!(#this) + }; let type_path = match variant_ident { - Some(variant_ident) => quote!(#ident::#variant_ident), - None => quote!(#ident), + Some(variant_ident) => quote!(#construct::#variant_ident), + None => construct, }; let expecting = match variant_ident { - Some(variant_ident) => format!("struct variant {}::{}", ident, variant_ident), - None => format!("struct {}", ident), + Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident), + None => format!("struct {}", params.type_name()), }; - let visit_seq = Stmts(deserialize_seq(ident, &type_path, generics, fields, true, item_attrs)); + let visit_seq = Stmts(deserialize_seq(&type_path, params, fields, true, cattrs),); let (field_visitor, fields_stmt, visit_map) = - deserialize_struct_visitor(ident, type_path, generics, fields, item_attrs); + deserialize_struct_visitor(type_path, params, fields, cattrs); let field_visitor = Stmts(field_visitor); let fields_stmt = Stmts(fields_stmt); let visit_map = Stmts(visit_map); let visitor_expr = quote! { - __Visitor { marker: _serde::export::PhantomData::<#ident #ty_generics> } + __Visitor { + marker: _serde::export::PhantomData::<#this #ty_generics>, + lifetime: _serde::export::PhantomData, + } }; let dispatch = if let Some(deserializer) = deserializer { quote! { - _serde::Deserializer::deserialize(#deserializer, #visitor_expr) + _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) } } else if is_enum { quote! { - _serde::de::VariantVisitor::visit_struct(__visitor, FIELDS, #visitor_expr) + _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) } } else { - let type_name = item_attrs.name().deserialize_name(); + let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); + let all_skipped = fields + .iter() + .all(|field| field.attrs.skip_deserializing()); let visitor_var = if all_skipped { quote!(_) } else { - quote!(mut __visitor) + quote!(mut __seq) }; let visit_seq = if is_untagged { @@ -399,8 +532,8 @@ fn deserialize_struct(ident: &syn::Ident, } else { Some(quote! { #[inline] - fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result - where __V: _serde::de::SeqVisitor + fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result + where __A: _serde::de::SeqAccess<'de> { #visit_seq } @@ -410,22 +543,23 @@ fn deserialize_struct(ident: &syn::Ident, quote_block! { #field_visitor - struct __Visitor #impl_generics #where_clause { - marker: _serde::export::PhantomData<#ident #ty_generics>, + struct __Visitor #de_impl_generics #where_clause { + marker: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, } - impl #generics _serde::de::Visitor for __Visitor #ty_generics #where_clause { - type Value = #ident #ty_generics; + impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { + type Value = #this #ty_generics; - fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { - _serde::export::fmt::Formatter::write_str(formatter, #expecting) + fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(formatter, #expecting) } #visit_seq #[inline] - fn visit_map<__V>(self, mut __visitor: __V) -> _serde::export::Result - where __V: _serde::de::MapVisitor + fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result + where __A: _serde::de::MapAccess<'de> { #visit_map } @@ -437,51 +571,41 @@ fn deserialize_struct(ident: &syn::Ident, } } -fn deserialize_item_enum(ident: &syn::Ident, - generics: &syn::Generics, - variants: &[Variant], - item_attrs: &attr::Item) - -> Fragment { - match *item_attrs.tag() { - attr::EnumTag::External => { - deserialize_externally_tagged_enum(ident, generics, variants, item_attrs) - } +fn deserialize_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, +) -> Fragment { + match *cattrs.tag() { + attr::EnumTag::External => deserialize_externally_tagged_enum(params, variants, cattrs), attr::EnumTag::Internal { ref tag } => { - deserialize_internally_tagged_enum(ident, - generics, - variants, - item_attrs, - tag) - } - attr::EnumTag::Adjacent { ref tag, ref content } => { - deserialize_adjacently_tagged_enum(ident, - generics, - variants, - item_attrs, - tag, - content) - } - attr::EnumTag::None => { - deserialize_untagged_enum(ident, generics, variants, item_attrs) + deserialize_internally_tagged_enum(params, variants, cattrs, tag) } + attr::EnumTag::Adjacent { + ref tag, + ref content, + } => deserialize_adjacently_tagged_enum(params, variants, cattrs, tag, content), + attr::EnumTag::None => deserialize_untagged_enum(params, variants, cattrs), } } -fn deserialize_externally_tagged_enum(ident: &syn::Ident, - generics: &syn::Generics, - variants: &[Variant], - item_attrs: &attr::Item) - -> Fragment { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +fn deserialize_externally_tagged_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, +) -> Fragment { + let this = ¶ms.this; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params,); - let type_name = item_attrs.name().deserialize_name(); + let type_name = cattrs.name().deserialize_name(); - let expecting = format!("enum {}", ident); + let expecting = format!("enum {}", params.type_name()); - let variant_names_idents: Vec<_> = variants.iter() + 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))) + .map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)),) .collect(); let variants_stmt = { @@ -491,40 +615,44 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident, } }; - let variant_visitor = Stmts(deserialize_field_visitor(variant_names_idents, item_attrs, true)); + let variant_visitor = Stmts(deserialize_generated_identifier(variant_names_idents, cattrs, true),); // Match arms to extract a variant from a string - let variant_arms = variants.iter() - .enumerate() - .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) - .map(|(i, variant)| { - let variant_name = field_i(i); + let variant_arms = + variants + .iter() + .enumerate() + .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) + .map( + |(i, variant)| { + let variant_name = field_i(i); - let block = Match(deserialize_externally_tagged_variant(ident, - generics, - variant, - item_attrs)); + let block = + Match(deserialize_externally_tagged_variant(params, variant, cattrs),); - quote! { - (__Field::#variant_name, __visitor) => #block + quote! { + (__Field::#variant_name, __variant) => #block } - }); + }, + ); - let all_skipped = variants.iter().all(|variant| variant.attrs.skip_deserializing()); + let all_skipped = variants + .iter() + .all(|variant| variant.attrs.skip_deserializing()); let match_variant = if all_skipped { // This is an empty enum like `enum Impossible {}` or an enum in which // all variants have `#[serde(skip_deserializing)]`. quote! { // FIXME: Once we drop support for Rust 1.15: - // let _serde::export::Err(__err) = _serde::de::EnumVisitor::visit_variant::<__Field>(__visitor); + // let _serde::export::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data); // _serde::export::Err(__err) _serde::export::Result::map( - _serde::de::EnumVisitor::visit_variant::<__Field>(__visitor), + _serde::de::EnumAccess::variant::<__Field>(__data), |(__impossible, _)| match __impossible {}) } } else { quote! { - match try!(_serde::de::EnumVisitor::visit_variant(__visitor)) { + match try!(_serde::de::EnumAccess::variant(__data)) { #(#variant_arms)* } } @@ -533,19 +661,20 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident, quote_block! { #variant_visitor - struct __Visitor #impl_generics #where_clause { - marker: _serde::export::PhantomData<#ident #ty_generics>, + struct __Visitor #de_impl_generics #where_clause { + marker: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, } - impl #generics _serde::de::Visitor for __Visitor #ty_generics #where_clause { - type Value = #ident #ty_generics; + impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { + type Value = #this #ty_generics; - fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { - _serde::export::fmt::Formatter::write_str(formatter, #expecting) + fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(formatter, #expecting) } - fn visit_enum<__V>(self, __visitor: __V) -> _serde::export::Result - where __V: _serde::de::EnumVisitor + fn visit_enum<__A>(self, __data: __A) -> _serde::export::Result + where __A: _serde::de::EnumAccess<'de> { #match_variant } @@ -555,21 +684,23 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident, _serde::Deserializer::deserialize_enum(__deserializer, #type_name, VARIANTS, __Visitor { - marker: _serde::export::PhantomData::<#ident #ty_generics>, + marker: _serde::export::PhantomData::<#this #ty_generics>, + lifetime: _serde::export::PhantomData, }) } } -fn deserialize_internally_tagged_enum(ident: &syn::Ident, - generics: &syn::Generics, - variants: &[Variant], - item_attrs: &attr::Item, - tag: &str) - -> Fragment { - let variant_names_idents: Vec<_> = variants.iter() +fn deserialize_internally_tagged_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, + tag: &str, +) -> Fragment { + 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))) + .map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)),) .collect(); let variants_stmt = { @@ -579,7 +710,7 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident, } }; - let variant_visitor = Stmts(deserialize_field_visitor(variant_names_idents, item_attrs, true)); + let variant_visitor = Stmts(deserialize_generated_identifier(variant_names_idents, cattrs, true),); // Match arms to extract a variant from a string let variant_arms = variants.iter() @@ -589,11 +720,10 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident, let variant_name = field_i(i); let block = Match(deserialize_internally_tagged_variant( - ident, - generics, + params, variant, - item_attrs, - quote!(_serde::de::private::ContentDeserializer::<__D::Error>::new(__tagged.content)), + cattrs, + quote!(_serde::private::de::ContentDeserializer::<__D::Error>::new(__tagged.content)), )); quote! { @@ -606,9 +736,9 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident, #variants_stmt - let __tagged = try!(_serde::Deserializer::deserialize( + let __tagged = try!(_serde::Deserializer::deserialize_any( __deserializer, - _serde::de::private::TaggedContentVisitor::<__Field>::new(#tag))); + _serde::private::de::TaggedContentVisitor::<__Field>::new(#tag))); match __tagged.tag { #(#variant_arms)* @@ -616,19 +746,21 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident, } } -fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, - generics: &syn::Generics, - variants: &[Variant], - item_attrs: &attr::Item, - tag: &str, - content: &str) - -> Fragment { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +fn deserialize_adjacently_tagged_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, + tag: &str, + content: &str, +) -> Fragment { + let this = ¶ms.this; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params,); - let variant_names_idents: Vec<_> = variants.iter() + 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))) + .map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)),) .collect(); let variants_stmt = { @@ -638,33 +770,37 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, } }; - let variant_visitor = Stmts(deserialize_field_visitor(variant_names_idents, item_attrs, true)); + let variant_visitor = Stmts(deserialize_generated_identifier(variant_names_idents, cattrs, true),); - let ref variant_arms: Vec<_> = variants.iter() + let ref variant_arms: Vec<_> = variants + .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) - .map(|(i, variant)| { - let variant_index = field_i(i); + .map( + |(i, variant)| { + let variant_index = field_i(i); - let block = Match(deserialize_untagged_variant( - ident, - generics, - variant, - item_attrs, - quote!(__deserializer), - )); + let block = Match( + deserialize_untagged_variant( + params, + variant, + cattrs, + quote!(__deserializer), + ), + ); - quote! { + quote! { __Field::#variant_index => #block } - }) + }, + ) .collect(); - let expecting = format!("adjacently tagged enum {}", ident); - let type_name = item_attrs.name().deserialize_name(); + let expecting = format!("adjacently tagged enum {}", params.type_name()); + let type_name = cattrs.name().deserialize_name(); let tag_or_content = quote! { - _serde::de::private::TagOrContentFieldVisitor { + _serde::private::de::TagOrContentFieldVisitor { tag: #tag, content: #content, } @@ -678,26 +814,31 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, } let mut missing_content = quote! { - _serde::export::Err(<__V::Error as _serde::de::Error>::missing_field(#content)) + _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) }; if variants.iter().any(is_unit) { let fallthrough = if variants.iter().all(is_unit) { None } else { - Some(quote! { - _ => #missing_content - }) - }; - let arms = variants.iter() - .enumerate() - .filter(|&(_, variant)| !variant.attrs.skip_deserializing() && is_unit(variant)) - .map(|(i, variant)| { - let variant_index = field_i(i); - let variant_ident = &variant.ident; + Some( quote! { - __Field::#variant_index => _serde::export::Ok(#ident::#variant_ident), + _ => #missing_content + }, + ) + }; + let arms = variants + .iter() + .enumerate() + .filter(|&(_, variant)| !variant.attrs.skip_deserializing() && is_unit(variant),) + .map( + |(i, variant)| { + let variant_index = field_i(i); + let variant_ident = &variant.ident; + quote! { + __Field::#variant_index => _serde::export::Ok(#this::#variant_ident), } - }); + }, + ); missing_content = quote! { match __field { #(#arms)* @@ -708,12 +849,12 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, let visit_third_key = quote! { // Visit the third key in the map, hopefully there isn't one. - match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) { - _serde::export::Some(_serde::de::private::TagOrContentField::Tag) => { - _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#tag)) + match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) { + _serde::export::Some(_serde::private::de::TagOrContentField::Tag) => { + _serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag)) } - _serde::export::Some(_serde::de::private::TagOrContentField::Content) => { - _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#content)) + _serde::export::Some(_serde::private::de::TagOrContentField::Content) => { + _serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content)) } _serde::export::None => _serde::export::Ok(__ret), } @@ -724,16 +865,17 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, #variants_stmt - struct __Seed #impl_generics #where_clause { + struct __Seed #de_impl_generics #where_clause { field: __Field, - marker: _serde::export::PhantomData<#ident #ty_generics>, + marker: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, } - impl #impl_generics _serde::de::DeserializeSeed for __Seed #ty_generics #where_clause { - type Value = #ident #ty_generics; + impl #de_impl_generics _serde::de::DeserializeSeed<'de> for __Seed #de_ty_generics #where_clause { + type Value = #this #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::export::Result - where __D: _serde::Deserializer + where __D: _serde::Deserializer<'de> { match self.field { #(#variant_arms)* @@ -741,35 +883,41 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, } } - struct __Visitor #impl_generics #where_clause { - marker: _serde::export::PhantomData<#ident #ty_generics>, + struct __Visitor #de_impl_generics #where_clause { + marker: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, } - impl #impl_generics _serde::de::Visitor for __Visitor #ty_generics #where_clause { - type Value = #ident #ty_generics; + impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { + type Value = #this #ty_generics; - fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { - _serde::export::fmt::Formatter::write_str(formatter, #expecting) + fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(formatter, #expecting) } - fn visit_map<__V>(self, mut __visitor: __V) -> _serde::export::Result - where __V: _serde::de::MapVisitor + fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result + where __A: _serde::de::MapAccess<'de> { // Visit the first key. - match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) { + match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) { // First key is the tag. - _serde::export::Some(_serde::de::private::TagOrContentField::Tag) => { + _serde::export::Some(_serde::private::de::TagOrContentField::Tag) => { // Parse the tag. - let __field = try!(_serde::de::MapVisitor::visit_value(&mut __visitor)); + let __field = try!(_serde::de::MapAccess::next_value(&mut __map)); // Visit the second key. - match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) { + match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) { // Second key is a duplicate of the tag. - _serde::export::Some(_serde::de::private::TagOrContentField::Tag) => { - _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#tag)) + _serde::export::Some(_serde::private::de::TagOrContentField::Tag) => { + _serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag)) } // Second key is the content. - _serde::export::Some(_serde::de::private::TagOrContentField::Content) => { - let __ret = try!(_serde::de::MapVisitor::visit_value_seed(&mut __visitor, __Seed { field: __field, marker: _serde::export::PhantomData })); + _serde::export::Some(_serde::private::de::TagOrContentField::Content) => { + let __ret = try!(_serde::de::MapAccess::next_value_seed(&mut __map, + __Seed { + field: __field, + marker: _serde::export::PhantomData, + lifetime: _serde::export::PhantomData, + })); // Visit the third key, hopefully there isn't one. #visit_third_key } @@ -778,16 +926,16 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, } } // First key is the content. - _serde::export::Some(_serde::de::private::TagOrContentField::Content) => { + _serde::export::Some(_serde::private::de::TagOrContentField::Content) => { // Buffer up the content. - let __content = try!(_serde::de::MapVisitor::visit_value::<_serde::de::private::Content>(&mut __visitor)); + let __content = try!(_serde::de::MapAccess::next_value::<_serde::private::de::Content>(&mut __map)); // Visit the second key. - match try!(_serde::de::MapVisitor::visit_key_seed(&mut __visitor, #tag_or_content)) { + match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) { // Second key is the tag. - _serde::export::Some(_serde::de::private::TagOrContentField::Tag) => { - let __deserializer = _serde::de::private::ContentDeserializer::<__V::Error>::new(__content); + _serde::export::Some(_serde::private::de::TagOrContentField::Tag) => { + let __deserializer = _serde::private::de::ContentDeserializer::<__A::Error>::new(__content); // Parse the tag. - let __ret = try!(match try!(_serde::de::MapVisitor::visit_value(&mut __visitor)) { + let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) { // Deserialize the buffered content now that we know the variant. #(#variant_arms)* }); @@ -795,30 +943,35 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, #visit_third_key } // Second key is a duplicate of the content. - _serde::export::Some(_serde::de::private::TagOrContentField::Content) => { - _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#content)) + _serde::export::Some(_serde::private::de::TagOrContentField::Content) => { + _serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content)) } // There is no second key. _serde::export::None => { - _serde::export::Err(<__V::Error as _serde::de::Error>::missing_field(#tag)) + _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#tag)) } } } // There is no first key. _serde::export::None => { - _serde::export::Err(<__V::Error as _serde::de::Error>::missing_field(#tag)) + _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#tag)) } } } - fn visit_seq<__V>(self, mut __visitor: __V) -> _serde::export::Result - where __V: _serde::de::SeqVisitor + fn visit_seq<__A>(self, mut __seq: __A) -> _serde::export::Result + where __A: _serde::de::SeqAccess<'de> { // Visit the first element - the tag. - match try!(_serde::de::SeqVisitor::visit(&mut __visitor)) { + match try!(_serde::de::SeqAccess::next_element(&mut __seq)) { _serde::export::Some(__field) => { // Visit the second element - the content. - match try!(_serde::de::SeqVisitor::visit_seed(&mut __visitor, __Seed { field: __field, marker: _serde::export::PhantomData })) { + match try!(_serde::de::SeqAccess::next_element_seed(&mut __seq, + __Seed { + field: __field, + marker: _serde::export::PhantomData, + lifetime: _serde::export::PhantomData, + })) { _serde::export::Some(__ret) => _serde::export::Ok(__ret), // There is no second element. _serde::export::None => { @@ -836,26 +989,31 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, const FIELDS: &'static [&'static str] = &[#tag, #content]; _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, - __Visitor { marker: _serde::export::PhantomData::<#ident #ty_generics> }) + __Visitor { + marker: _serde::export::PhantomData::<#this #ty_generics>, + lifetime: _serde::export::PhantomData, + }) } } -fn deserialize_untagged_enum(ident: &syn::Ident, - generics: &syn::Generics, - variants: &[Variant], - item_attrs: &attr::Item) - -> Fragment { - let attempts = variants.iter() +fn deserialize_untagged_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, +) -> Fragment { + let attempts = variants + .iter() .filter(|variant| !variant.attrs.skip_deserializing()) - .map(|variant| { - Expr(deserialize_untagged_variant( - ident, - generics, + .map( + |variant| { + Expr(deserialize_untagged_variant( + params, variant, - item_attrs, - quote!(_serde::de::private::ContentRefDeserializer::<__D::Error>::new(&__content)), + cattrs, + quote!(_serde::private::de::ContentRefDeserializer::<__D::Error>::new(&__content)), )) - }); + }, + ); // TODO this message could be better by saving the errors from the failed // attempts. The heuristic used by TOML was to count the number of fields @@ -863,10 +1021,11 @@ fn deserialize_untagged_enum(ident: &syn::Ident, // largest number of fields. I'm not sure I like that. Maybe it would be // better to save all the errors and combine them into one message that // explains why none of the variants matched. - let fallthrough_msg = format!("data did not match any variant of untagged enum {}", ident); + let fallthrough_msg = + format!("data did not match any variant of untagged enum {}", params.type_name()); quote_block! { - let __content = try!(<_serde::de::private::Content as _serde::Deserialize>::deserialize(__deserializer)); + let __content = try!(<_serde::private::de::Content as _serde::Deserialize>::deserialize(__deserializer)); #( if let _serde::export::Ok(__ok) = #attempts { @@ -878,231 +1037,193 @@ fn deserialize_untagged_enum(ident: &syn::Ident, } } -fn deserialize_externally_tagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - item_attrs: &attr::Item) - -> Fragment { +fn deserialize_externally_tagged_variant( + params: &Parameters, + variant: &Variant, + cattrs: &attr::Container, +) -> Fragment { let variant_ident = &variant.ident; match variant.style { Style::Unit => { + let this = ¶ms.this; quote_block! { - try!(_serde::de::VariantVisitor::visit_unit(__visitor)); - _serde::export::Ok(#ident::#variant_ident) + try!(_serde::de::VariantAccess::unit_variant(__variant)); + _serde::export::Ok(#this::#variant_ident) } } Style::Newtype => { - deserialize_externally_tagged_newtype_variant(ident, - variant_ident, - generics, - &variant.fields[0]) + deserialize_externally_tagged_newtype_variant(variant_ident, params, &variant.fields[0]) } Style::Tuple => { - deserialize_tuple(ident, - Some(variant_ident), - generics, - &variant.fields, - item_attrs, - None) + deserialize_tuple( + Some(variant_ident), + params, + &variant.fields, + cattrs, + None, + ) } Style::Struct => { - deserialize_struct(ident, - Some(variant_ident), - generics, - &variant.fields, - item_attrs, - None) + deserialize_struct( + Some(variant_ident), + params, + &variant.fields, + cattrs, + None, + ) } } } -fn deserialize_internally_tagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - item_attrs: &attr::Item, - deserializer: Tokens) - -> Fragment { +fn deserialize_internally_tagged_variant( + params: &Parameters, + variant: &Variant, + cattrs: &attr::Container, + deserializer: Tokens, +) -> Fragment { let variant_ident = &variant.ident; match variant.style { Style::Unit => { - let type_name = ident.as_ref(); + let this = ¶ms.this; + let type_name = params.type_name(); let variant_name = variant.ident.as_ref(); quote_block! { - try!(_serde::Deserializer::deserialize(#deserializer, _serde::de::private::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))); - _serde::export::Ok(#ident::#variant_ident) + try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))); + _serde::export::Ok(#this::#variant_ident) } } Style::Newtype | Style::Struct => { - deserialize_untagged_variant(ident, - generics, - variant, - item_attrs, - deserializer) + deserialize_untagged_variant(params, variant, cattrs, deserializer) } - Style::Tuple => unreachable!("checked in serde_codegen_internals"), + Style::Tuple => unreachable!("checked in serde_derive_internals"), } } -fn deserialize_untagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - item_attrs: &attr::Item, - deserializer: Tokens) - -> Fragment { +fn deserialize_untagged_variant( + params: &Parameters, + variant: &Variant, + cattrs: &attr::Container, + deserializer: Tokens, +) -> Fragment { let variant_ident = &variant.ident; match variant.style { Style::Unit => { - let type_name = ident.as_ref(); + let this = ¶ms.this; + let type_name = params.type_name(); let variant_name = variant.ident.as_ref(); quote_expr! { _serde::export::Result::map( - _serde::Deserializer::deserialize( + _serde::Deserializer::deserialize_any( #deserializer, - _serde::de::private::UntaggedUnitVisitor::new(#type_name, #variant_name) + _serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name) ), - |()| #ident::#variant_ident) + |()| #this::#variant_ident) } } Style::Newtype => { - deserialize_untagged_newtype_variant(ident, - variant_ident, - generics, - &variant.fields[0], - deserializer) + deserialize_untagged_newtype_variant( + variant_ident, + params, + &variant.fields[0], + deserializer, + ) } Style::Tuple => { - deserialize_tuple(ident, - Some(variant_ident), - generics, - &variant.fields, - item_attrs, - Some(deserializer)) + deserialize_tuple( + Some(variant_ident), + params, + &variant.fields, + cattrs, + Some(deserializer), + ) } Style::Struct => { - deserialize_struct(ident, - Some(variant_ident), - generics, - &variant.fields, - item_attrs, - Some(deserializer)) + deserialize_struct( + Some(variant_ident), + params, + &variant.fields, + cattrs, + Some(deserializer), + ) } } } -fn deserialize_externally_tagged_newtype_variant(ident: &syn::Ident, - variant_ident: &syn::Ident, - generics: &syn::Generics, - field: &Field) - -> Fragment { +fn deserialize_externally_tagged_newtype_variant( + variant_ident: &syn::Ident, + params: &Parameters, + field: &Field, +) -> Fragment { + let this = ¶ms.this; match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; quote_expr! { _serde::export::Result::map( - _serde::de::VariantVisitor::visit_newtype::<#field_ty>(__visitor), - #ident::#variant_ident) + _serde::de::VariantAccess::newtype_variant::<#field_ty>(__variant), + #this::#variant_ident) } } Some(path) => { - let (wrapper, wrapper_ty) = - wrap_deserialize_with(ident, generics, field.ty, path); + let (wrapper, wrapper_ty) = wrap_deserialize_with(params, field.ty, path); quote_block! { #wrapper _serde::export::Result::map( - _serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(__visitor), - |__wrapper| #ident::#variant_ident(__wrapper.value)) + _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), + |__wrapper| #this::#variant_ident(__wrapper.value)) } } } } -fn deserialize_untagged_newtype_variant(ident: &syn::Ident, - variant_ident: &syn::Ident, - generics: &syn::Generics, - field: &Field, - deserializer: Tokens) - -> Fragment { +fn deserialize_untagged_newtype_variant( + variant_ident: &syn::Ident, + params: &Parameters, + field: &Field, + deserializer: Tokens, +) -> Fragment { + let this = ¶ms.this; match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; quote_expr! { _serde::export::Result::map( <#field_ty as _serde::Deserialize>::deserialize(#deserializer), - #ident::#variant_ident) + #this::#variant_ident) } } Some(path) => { - let (wrapper, wrapper_ty) = - wrap_deserialize_with(ident, generics, field.ty, path); + let (wrapper, wrapper_ty) = wrap_deserialize_with(params, field.ty, path); quote_block! { #wrapper _serde::export::Result::map( <#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), - |__wrapper| #ident::#variant_ident(__wrapper.value)) + |__wrapper| #this::#variant_ident(__wrapper.value)) } } } } -fn deserialize_field_visitor(fields: Vec<(String, Ident)>, - item_attrs: &attr::Item, - is_variant: bool) - -> Fragment { - let field_strs = fields.iter().map(|&(ref name, _)| name); - let field_bytes = fields.iter().map(|&(ref name, _)| quote::ByteStr(name)); +fn deserialize_generated_identifier( + fields: Vec<(String, Ident)>, + cattrs: &attr::Container, + is_variant: bool, +) -> Fragment { + let this = quote!(__Field); let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect(); - let ignore_variant = if is_variant || item_attrs.deny_unknown_fields() { - None + let (ignore_variant, fallthrough) = if is_variant || cattrs.deny_unknown_fields() { + (None, None) } else { - Some(quote!(__ignore,)) + let ignore_variant = quote!(__ignore,); + let fallthrough = quote!(_serde::export::Ok(__Field::__ignore)); + (Some(ignore_variant), Some(fallthrough)) }; - let visit_index = if is_variant { - let variant_indices = 0u32..; - let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len()); - Some(quote! { - fn visit_u32<__E>(self, __value: u32) -> _serde::export::Result<__Field, __E> - where __E: _serde::de::Error - { - match __value { - #( - #variant_indices => _serde::export::Ok(__Field::#field_idents), - )* - _ => _serde::export::Err(_serde::de::Error::invalid_value( - _serde::de::Unexpected::Unsigned(__value as u64), - &#fallthrough_msg)) - } - } - }) - } else { - None - }; - - let fallthrough_arm = if is_variant { - quote! { - _serde::export::Err(_serde::de::Error::unknown_variant(__value, VARIANTS)) - } - } else if item_attrs.deny_unknown_fields() { - quote! { - _serde::export::Err(_serde::de::Error::unknown_field(__value, FIELDS)) - } - } else { - quote! { - _serde::export::Ok(__Field::__ignore) - } - }; - - let bytes_to_str = if is_variant || item_attrs.deny_unknown_fields() { - Some(quote! { - let __value = &_serde::export::from_utf8_lossy(__value); - }) - } else { - None - }; + let visitor_impl = Stmts(deserialize_identifier(this, &fields, is_variant, fallthrough)); quote_block! { #[allow(non_camel_case_types)] @@ -1111,64 +1232,215 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>, #ignore_variant } - impl _serde::Deserialize for __Field { + struct __FieldVisitor; + + impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { + type Value = __Field; + + #visitor_impl + } + + impl<'de> _serde::Deserialize<'de> for __Field { #[inline] - fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<__Field, __D::Error> - where __D: _serde::Deserializer + fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result + where __D: _serde::Deserializer<'de> { - struct __FieldVisitor; - - impl _serde::de::Visitor for __FieldVisitor { - type Value = __Field; - - fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { - _serde::export::fmt::Formatter::write_str(formatter, "field name") - } - - #visit_index - - fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<__Field, __E> - where __E: _serde::de::Error - { - match __value { - #( - #field_strs => _serde::export::Ok(__Field::#field_idents), - )* - _ => #fallthrough_arm - } - } - - fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result<__Field, __E> - where __E: _serde::de::Error - { - match __value { - #( - #field_bytes => _serde::export::Ok(__Field::#field_idents), - )* - _ => { - #bytes_to_str - #fallthrough_arm - } - } - } - } - - _serde::Deserializer::deserialize_struct_field(__deserializer, __FieldVisitor) + _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) } } } } -fn deserialize_struct_visitor(ident: &syn::Ident, - struct_path: Tokens, - generics: &syn::Generics, - fields: &[Field], - item_attrs: &attr::Item) - -> (Fragment, Fragment, Fragment) { - let field_names_idents: Vec<_> = fields.iter() +fn deserialize_custom_identifier( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, +) -> Fragment { + let is_variant = match cattrs.identifier() { + attr::Identifier::Variant => true, + attr::Identifier::Field => false, + attr::Identifier::No => unreachable!(), + }; + + let this = ¶ms.this; + let this = quote!(#this); + + let (ordinary, fallthrough) = if let Some(last) = variants.last() { + let last_ident = &last.ident; + if last.attrs.other() { + let ordinary = &variants[..variants.len() - 1]; + let fallthrough = quote!(_serde::export::Ok(#this::#last_ident)); + (ordinary, Some(fallthrough)) + } else if let Style::Newtype = last.style { + let ordinary = &variants[..variants.len() - 1]; + let deserializer = quote!(_serde::private::de::IdentifierDeserializer::from(__value)); + let fallthrough = quote! { + _serde::export::Result::map( + _serde::Deserialize::deserialize(#deserializer), + #this::#last_ident) + }; + (ordinary, Some(fallthrough)) + } else { + (variants, None) + } + } else { + (variants, None) + }; + + let names_idents: Vec<_> = ordinary + .iter() + .map(|variant| (variant.attrs.name().deserialize_name(), variant.ident.clone())) + .collect(); + + let names = names_idents.iter().map(|&(ref name, _)| name); + + let names_const = if fallthrough.is_some() { + None + } else if is_variant { + let variants = quote! { + const VARIANTS: &'static [&'static str] = &[ #(#names),* ]; + }; + Some(variants) + } else { + let fields = quote! { + const FIELDS: &'static [&'static str] = &[ #(#names),* ]; + }; + Some(fields) + }; + + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); + let visitor_impl = Stmts(deserialize_identifier(this.clone(), &names_idents, is_variant, fallthrough)); + + quote_block! { + #names_const + + struct __FieldVisitor #de_impl_generics #where_clause { + marker: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, + } + + impl #de_impl_generics _serde::de::Visitor<'de> for __FieldVisitor #de_ty_generics #where_clause { + type Value = #this #ty_generics; + + #visitor_impl + } + + let __visitor = __FieldVisitor { + marker: _serde::export::PhantomData::<#this #ty_generics>, + lifetime: _serde::export::PhantomData, + }; + _serde::Deserializer::deserialize_identifier(__deserializer, __visitor) + } +} + +fn deserialize_identifier( + this: Tokens, + fields: &[(String, Ident)], + is_variant: bool, + fallthrough: Option, +) -> Fragment { + let field_strs = fields.iter().map(|&(ref name, _)| name); + let field_bytes = fields.iter().map(|&(ref name, _)| quote::ByteStr(name)); + + let constructors: &Vec<_> = &fields + .iter() + .map(|&(_, ref ident)| quote!(#this::#ident)) + .collect(); + + let expecting = if is_variant { + "variant identifier" + } else { + "field identifier" + }; + + let visit_index = if is_variant { + let variant_indices = 0u32..; + let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len()); + let visit_index = quote! { + fn visit_u32<__E>(self, __value: u32) -> _serde::export::Result + where __E: _serde::de::Error + { + match __value { + #( + #variant_indices => _serde::export::Ok(#constructors), + )* + _ => _serde::export::Err(_serde::de::Error::invalid_value( + _serde::de::Unexpected::Unsigned(__value as u64), + &#fallthrough_msg)) + } + } + }; + Some(visit_index) + } else { + None + }; + + let bytes_to_str = if fallthrough.is_some() { + None + } else { + let conversion = quote! { + let __value = &_serde::export::from_utf8_lossy(__value); + }; + Some(conversion) + }; + + let fallthrough_arm = if let Some(fallthrough) = fallthrough { + fallthrough + } else if is_variant { + quote! { + _serde::export::Err(_serde::de::Error::unknown_variant(__value, VARIANTS)) + } + } else { + quote! { + _serde::export::Err(_serde::de::Error::unknown_field(__value, FIELDS)) + } + }; + + quote_block! { + fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result { + _serde::export::Formatter::write_str(formatter, #expecting) + } + + #visit_index + + fn visit_str<__E>(self, __value: &str) -> _serde::export::Result + where __E: _serde::de::Error + { + match __value { + #( + #field_strs => _serde::export::Ok(#constructors), + )* + _ => #fallthrough_arm + } + } + + fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result + where __E: _serde::de::Error + { + match __value { + #( + #field_bytes => _serde::export::Ok(#constructors), + )* + _ => { + #bytes_to_str + #fallthrough_arm + } + } + } + } +} + +fn deserialize_struct_visitor( + struct_path: Tokens, + params: &Parameters, + fields: &[Field], + cattrs: &attr::Container, +) -> (Fragment, Fragment, Fragment) { + 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))) + .map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i)),) .collect(); let fields_stmt = { @@ -1178,34 +1450,38 @@ fn deserialize_struct_visitor(ident: &syn::Ident, } }; - let field_visitor = deserialize_field_visitor(field_names_idents, item_attrs, false); + let field_visitor = deserialize_generated_identifier(field_names_idents, cattrs, false); - let visit_map = deserialize_map(ident, struct_path, generics, fields, item_attrs); + let visit_map = deserialize_map(struct_path, params, fields, cattrs); (field_visitor, fields_stmt, visit_map) } -fn deserialize_map(ident: &syn::Ident, - struct_path: Tokens, - generics: &syn::Generics, - fields: &[Field], - item_attrs: &attr::Item) - -> Fragment { +fn deserialize_map( + struct_path: Tokens, + params: &Parameters, + fields: &[Field], + cattrs: &attr::Container, +) -> Fragment { // Create the field names for the fields. - let fields_names: Vec<_> = fields.iter() + let fields_names: Vec<_> = fields + .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // Declare each field that will be deserialized. - let let_values = fields_names.iter() + let let_values = fields_names + .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) - .map(|&(field, ref name)| { - let field_ty = &field.ty; - quote! { + .map( + |&(field, ref name)| { + let field_ty = &field.ty; + quote! { let mut #name: _serde::export::Option<#field_ty> = _serde::export::None; } - }); + }, + ); // Match arms to extract a value for a field. let value_arms = fields_names.iter() @@ -1217,22 +1493,22 @@ fn deserialize_map(ident: &syn::Ident, None => { let field_ty = &field.ty; quote! { - try!(_serde::de::MapVisitor::visit_value::<#field_ty>(&mut __visitor)) + try!(_serde::de::MapAccess::next_value::<#field_ty>(&mut __map)) } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_with( - ident, generics, field.ty, path); + params, field.ty, path); quote!({ #wrapper - try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut __visitor)).value + try!(_serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map)).value }) } }; quote! { __Field::#name => { if _serde::export::Option::is_some(&#name) { - return _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#deser_name)); + return _serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #name = _serde::export::Some(#visit); } @@ -1240,26 +1516,28 @@ fn deserialize_map(ident: &syn::Ident, }); // Visit ignored values to consume them - let ignored_arm = if item_attrs.deny_unknown_fields() { + let ignored_arm = if cattrs.deny_unknown_fields() { None } else { Some(quote! { - _ => { let _ = try!(_serde::de::MapVisitor::visit_value::<_serde::de::impls::IgnoredAny>(&mut __visitor)); } + _ => { let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); } }) }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let match_keys = if item_attrs.deny_unknown_fields() && all_skipped { + let all_skipped = fields + .iter() + .all(|field| field.attrs.skip_deserializing()); + let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once we drop support for Rust 1.15: - // let _serde::export::None::<__Field> = try!(_serde::de::MapVisitor::visit_key(&mut __visitor)); + // let _serde::export::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map)); _serde::export::Option::map( - try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut __visitor)), + try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)), |__impossible| match __impossible {}); } } else { quote! { - while let _serde::export::Some(__key) = try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut __visitor)) { + while let _serde::export::Some(__key) = try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)) { match __key { #(#value_arms)* #ignored_arm @@ -1268,40 +1546,53 @@ fn deserialize_map(ident: &syn::Ident, } }; - let extract_values = fields_names.iter() + let extract_values = fields_names + .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) - .map(|&(field, ref name)| { - let missing_expr = Match(expr_is_missing(&field, item_attrs)); + .map( + |&(field, ref name)| { + let missing_expr = Match(expr_is_missing(&field, cattrs)); - quote! { + quote! { let #name = match #name { _serde::export::Some(#name) => #name, _serde::export::None => #missing_expr }; } - }); + }, + ); - let result = fields_names.iter() - .map(|&(field, ref name)| { - let ident = field.ident.clone().expect("struct contains unnamed fields"); - if field.attrs.skip_deserializing() { - let value = Expr(expr_is_missing(&field, item_attrs)); - quote!(#ident: #value) - } else { - quote!(#ident: #name) - } - }); + let result = fields_names + .iter() + .map( + |&(field, ref name)| { + let ident = field + .ident + .clone() + .expect("struct contains unnamed fields"); + if field.attrs.skip_deserializing() { + let value = Expr(expr_is_missing(&field, cattrs)); + quote!(#ident: #value) + } else { + quote!(#ident: #name) + } + }, + ); - let let_default = match *item_attrs.default() { + let let_default = match *cattrs.default() { attr::Default::Default => { - Some(quote!( + Some( + quote!( let __default: Self::Value = _serde::export::Default::default(); - )) + ), + ) } attr::Default::Path(ref path) => { - Some(quote!( + Some( + quote!( let __default: Self::Value = #path(); - )) + ), + ) } attr::Default::None => { // We don't need the default value, to prevent an unused variable warning @@ -1310,6 +1601,14 @@ fn deserialize_map(ident: &syn::Ident, } }; + let mut result = quote!(#struct_path { #(#result),* }); + if params.has_getter { + let this = ¶ms.this; + result = quote! { + _serde::export::Into::<#this>::into(#result) + }; + } + quote_block! { #(#let_values)* @@ -1319,7 +1618,7 @@ fn deserialize_map(ident: &syn::Ident, #(#extract_values)* - _serde::export::Ok(#struct_path { #(#result),* }) + _serde::export::Ok(#result) } } @@ -1327,39 +1626,42 @@ fn field_i(i: usize) -> Ident { Ident::new(format!("__field{}", i)) } -/// This function wraps the expression in `#[serde(deserialize_with="...")]` in -/// a trait to prevent it from accessing the internal `Deserialize` state. -fn wrap_deserialize_with(ident: &syn::Ident, - generics: &syn::Generics, - field_ty: &syn::Ty, - deserialize_with: &syn::Path) - -> (Tokens, Tokens) { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +/// This function wraps the expression in `#[serde(deserialize_with = "...")]` +/// in a trait to prevent it from accessing the internal `Deserialize` state. +fn wrap_deserialize_with( + params: &Parameters, + field_ty: &syn::Ty, + deserialize_with: &syn::Path, +) -> (Tokens, Tokens) { + let this = ¶ms.this; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params,); let wrapper = quote! { - struct __DeserializeWith #impl_generics #where_clause { + struct __DeserializeWith #de_impl_generics #where_clause { value: #field_ty, - phantom: _serde::export::PhantomData<#ident #ty_generics>, + phantom: _serde::export::PhantomData<#this #ty_generics>, + lifetime: _serde::export::PhantomData<&'de ()>, } - impl #impl_generics _serde::Deserialize for __DeserializeWith #ty_generics #where_clause { + impl #de_impl_generics _serde::Deserialize<'de> for __DeserializeWith #de_ty_generics #where_clause { fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result - where __D: _serde::Deserializer + where __D: _serde::Deserializer<'de> { _serde::export::Ok(__DeserializeWith { value: try!(#deserialize_with(__deserializer)), phantom: _serde::export::PhantomData, + lifetime: _serde::export::PhantomData, }) } } }; - let wrapper_ty = quote!(__DeserializeWith #ty_generics); + let wrapper_ty = quote!(__DeserializeWith #de_ty_generics); (wrapper, wrapper_ty) } -fn expr_is_missing(field: &Field, item_attrs: &attr::Item) -> Fragment { +fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { match *field.attrs.default() { attr::Default::Default => { return quote_expr!(_serde::export::Default::default()); @@ -1370,8 +1672,9 @@ fn expr_is_missing(field: &Field, item_attrs: &attr::Item) -> Fragment { attr::Default::None => { /* below */ } } - match *item_attrs.default() { - attr::Default::Default | attr::Default::Path(_) => { + match *cattrs.default() { + attr::Default::Default | + attr::Default::Path(_) => { let ident = &field.ident; return quote_expr!(__default.#ident); } @@ -1382,35 +1685,45 @@ fn expr_is_missing(field: &Field, item_attrs: &attr::Item) -> Fragment { match field.attrs.deserialize_with() { None => { quote_expr! { - try!(_serde::de::private::missing_field(#name)) + try!(_serde::private::de::missing_field(#name)) } } Some(_) => { quote_expr! { - return _serde::export::Err(<__V::Error as _serde::de::Error>::missing_field(#name)) + return _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#name)) } } } } -fn check_no_str(cx: &internals::Ctxt, item: &Item) { - let fail = || { - cx.error("Serde does not support deserializing fields of type &str; consider using \ - String instead"); - }; +struct DeImplGenerics<'a>(&'a Parameters); - for field in item.body.all_fields() { - if field.attrs.skip_deserializing() || field.attrs.deserialize_with().is_some() { - continue; - } - - if let syn::Ty::Rptr(_, ref inner) = *field.ty { - if let syn::Ty::Path(_, ref path) = inner.ty { - if path.segments.len() == 1 && path.segments[0].ident == "str" { - fail(); - return; - } - } - } +impl<'a> ToTokens for DeImplGenerics<'a> { + fn to_tokens(&self, tokens: &mut Tokens) { + let mut generics = self.0.generics.clone(); + generics.lifetimes.insert(0, self.0.de_lifetime_def()); + let (impl_generics, _, _) = generics.split_for_impl(); + impl_generics.to_tokens(tokens); } } + +struct DeTyGenerics<'a>(&'a syn::Generics); + +impl<'a> ToTokens for DeTyGenerics<'a> { + fn to_tokens(&self, tokens: &mut Tokens) { + let mut generics = self.0.clone(); + generics + .lifetimes + .insert(0, syn::LifetimeDef::new("'de")); + let (_, ty_generics, _) = generics.split_for_impl(); + ty_generics.to_tokens(tokens); + } +} + +fn split_with_de_lifetime(params: &Parameters,) + -> (DeImplGenerics, DeTyGenerics, syn::TyGenerics, &syn::WhereClause) { + let de_impl_generics = DeImplGenerics(¶ms); + let de_ty_generics = DeTyGenerics(¶ms.generics); + let (_, ty_generics, where_clause) = params.generics.split_for_impl(); + (de_impl_generics, de_ty_generics, ty_generics, where_clause) +} diff --git a/serde_derive/src/fragment.rs b/serde_derive/src/fragment.rs index f35578db..58cf0a2c 100644 --- a/serde_derive/src/fragment.rs +++ b/serde_derive/src/fragment.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use quote::{Tokens, ToTokens}; pub enum Fragment { diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index d58271ad..55cea20e 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![doc(html_root_url = "https://docs.rs/serde_derive/0.9.13")] + #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] #![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))] @@ -8,7 +18,7 @@ extern crate syn; #[macro_use] extern crate quote; -extern crate serde_codegen_internals as internals; +extern crate serde_derive_internals as internals; extern crate proc_macro; use proc_macro::TokenStream; diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index a16f7567..087702a3 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1,26 +1,45 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use syn::{self, Ident}; use quote::Tokens; use bound; use fragment::{Fragment, Stmts, Match}; -use internals::ast::{Body, Field, Item, Style, Variant}; -use internals::{self, attr}; +use internals::ast::{Body, Container, Field, Style, Variant}; +use internals::{attr, Ctxt}; -pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result { - let ctxt = internals::Ctxt::new(); - let item = Item::from_ast(&ctxt, item); +use std::u32; + +pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result { + let ctxt = Ctxt::new(); + let cont = Container::from_ast(&ctxt, input); + precondition(&ctxt, &cont); try!(ctxt.check()); - let ident = &item.ident; - let generics = build_generics(&item); - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let ident = &cont.ident; + let params = Parameters::new(&cont); + let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident)); - let body = Stmts(serialize_body(&item, &generics)); + let body = Stmts(serialize_body(&cont, ¶ms)); - Ok(quote! { - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const #dummy_const: () = { - extern crate serde as _serde; + let impl_block = if let Some(remote) = cont.attrs.remote() { + quote! { + impl #impl_generics #ident #ty_generics #where_clause { + fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> + where __S: _serde::Serializer + { + #body + } + } + } + } else { + quote! { #[automatically_derived] impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> @@ -29,25 +48,97 @@ pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result {} + attr::Identifier::Field => { + cx.error("field identifiers cannot be serialized"); + } + attr::Identifier::Variant => { + cx.error("variant identifiers cannot be serialized"); + } + } +} + +struct Parameters { + /// Variable holding the value being serialized. Either `self` for local + /// types or `__self` for remote types. + self_var: Ident, + + /// Path to the type the impl is for. Either a single `Ident` for local + /// types or `some::remote::Ident` for remote types. Does not include + /// generic parameters. + this: syn::Path, + + /// Generics including any explicit and inferred bounds for the impl. + generics: syn::Generics, + + /// Type has a `serde(remote = "...")` attribute. + is_remote: bool, +} + +impl Parameters { + fn new(cont: &Container) -> Self { + let is_remote = cont.attrs.remote().is_some(); + let self_var = if is_remote { + Ident::new("__self") + } else { + Ident::new("self") + }; + + let this = match cont.attrs.remote() { + Some(remote) => remote.clone(), + None => cont.ident.clone().into(), + }; + + let generics = build_generics(cont); + + Parameters { + self_var: self_var, + this: this, + generics: generics, + is_remote: is_remote, + } + } + + /// Type name to use in error messages and `&'static str` arguments to + /// various Serializer methods. + fn type_name(&self) -> &str { + self.this.segments.last().unwrap().ident.as_ref() + } } // All the generics in the input, plus a bound `T: Serialize` for each generic // field type that will be serialized by us. -fn build_generics(item: &Item) -> syn::Generics { - let generics = bound::without_defaults(item.generics); +fn build_generics(cont: &Container) -> syn::Generics { + let generics = bound::without_defaults(cont.generics); let generics = - bound::with_where_predicates_from_fields(item, &generics, attr::Field::ser_bound); + bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound); - match item.attrs.ser_bound() { + match cont.attrs.ser_bound() { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => { - bound::with_bound(item, - &generics, - needs_serialize_bound, - &path!(_serde::Serialize)) + bound::with_bound( + cont, + &generics, + needs_serialize_bound, + &path!(_serde::Serialize), + ) } } } @@ -60,60 +151,59 @@ fn needs_serialize_bound(attrs: &attr::Field) -> bool { !attrs.skip_serializing() && attrs.serialize_with().is_none() && attrs.ser_bound().is_none() } -fn serialize_body(item: &Item, generics: &syn::Generics) -> Fragment { - if let Some(into_type) = item.attrs.into_type() { - serialize_into(into_type) +fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { + if let Some(into_type) = cont.attrs.into_type() { + serialize_into(params, into_type) } else { - match item.body { - Body::Enum(ref variants) => { - serialize_item_enum(&item.ident, generics, variants, &item.attrs) - } + match cont.body { + Body::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs), Body::Struct(Style::Struct, ref fields) => { if fields.iter().any(|field| field.ident.is_none()) { panic!("struct has unnamed fields"); } - serialize_struct(&item.ident, generics, fields, &item.attrs) + serialize_struct(params, fields, &cont.attrs) } Body::Struct(Style::Tuple, ref fields) => { if fields.iter().any(|field| field.ident.is_some()) { panic!("tuple struct has named fields"); } - serialize_tuple_struct(&item.ident, generics, fields, &item.attrs) + serialize_tuple_struct(params, fields, &cont.attrs) } Body::Struct(Style::Newtype, ref fields) => { - serialize_newtype_struct(&item.ident, generics, &fields[0], &item.attrs) + serialize_newtype_struct(params, &fields[0], &cont.attrs) } - Body::Struct(Style::Unit, _) => serialize_unit_struct(&item.attrs), + Body::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs), } } } -fn serialize_into(into_type: &syn::Ty) -> Fragment { +fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment { + let self_var = ¶ms.self_var; quote_block! { _serde::Serialize::serialize( - &>::into(_serde::export::Clone::clone(self)), + &_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)), __serializer) } } -fn serialize_unit_struct(item_attrs: &attr::Item) -> Fragment { - let type_name = item_attrs.name().serialize_name(); +fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment { + let type_name = cattrs.name().serialize_name(); quote_expr! { _serde::Serializer::serialize_unit_struct(__serializer, #type_name) } } -fn serialize_newtype_struct(ident: &syn::Ident, - generics: &syn::Generics, - field: &Field, - item_attrs: &attr::Item) - -> Fragment { - let type_name = item_attrs.name().serialize_name(); +fn serialize_newtype_struct( + params: &Parameters, + field: &Field, + cattrs: &attr::Container, +) -> Fragment { + let type_name = cattrs.name().serialize_name(); - let mut field_expr = quote!(&self.0); + let mut field_expr = get_field(params, field, 0); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); + field_expr = wrap_serialize_with(params, field.ty, path, field_expr); } quote_expr! { @@ -121,19 +211,19 @@ fn serialize_newtype_struct(ident: &syn::Ident, } } -fn serialize_tuple_struct(ident: &syn::Ident, - generics: &syn::Generics, - fields: &[Field], - item_attrs: &attr::Item) - -> Fragment { - let serialize_stmts = - serialize_tuple_struct_visitor(ident, - fields, - generics, - false, - quote!(_serde::ser::SerializeTupleStruct::serialize_field)); +fn serialize_tuple_struct( + params: &Parameters, + fields: &[Field], + cattrs: &attr::Container, +) -> Fragment { + let serialize_stmts = serialize_tuple_struct_visitor( + fields, + params, + false, + quote!(_serde::ser::SerializeTupleStruct::serialize_field), + ); - let type_name = item_attrs.name().serialize_name(); + let type_name = cattrs.name().serialize_name(); let len = serialize_stmts.len(); let let_mut = mut_if(len > 0); @@ -144,35 +234,36 @@ fn serialize_tuple_struct(ident: &syn::Ident, } } -fn serialize_struct(ident: &syn::Ident, - generics: &syn::Generics, - fields: &[Field], - item_attrs: &attr::Item) - -> Fragment { - let serialize_fields = - serialize_struct_visitor(ident, - fields, - generics, - false, - quote!(_serde::ser::SerializeStruct::serialize_field)); +fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { + assert!(fields.len() as u64 <= u32::MAX as u64); - let type_name = item_attrs.name().serialize_name(); + let serialize_fields = serialize_struct_visitor( + fields, + params, + false, + quote!(_serde::ser::SerializeStruct::serialize_field), + ); - let mut serialized_fields = fields.iter() + let type_name = cattrs.name().serialize_name(); + + let mut serialized_fields = fields + .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); - let len = serialized_fields.map(|field| { - let ident = field.ident.clone().expect("struct has unnamed fields"); - let field_expr = quote!(&self.#ident); - - match field.attrs.skip_serializing_if() { - Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }), + let len = serialized_fields + .map( + |field| match field.attrs.skip_serializing_if() { None => quote!(1), - } - }) + Some(path) => { + let ident = field.ident.clone().expect("struct has unnamed fields"); + let field_expr = get_field(params, field, ident); + quote!(if #path(#field_expr) { 0 } else { 1 }) + } + }, + ) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); quote_block! { @@ -182,106 +273,116 @@ fn serialize_struct(ident: &syn::Ident, } } -fn serialize_item_enum(ident: &syn::Ident, - generics: &syn::Generics, - variants: &[Variant], - item_attrs: &attr::Item) - -> Fragment { - let arms: Vec<_> = variants.iter() +fn serialize_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, +) -> Fragment { + assert!(variants.len() as u64 <= u32::MAX as u64); + + let self_var = ¶ms.self_var; + + let arms: Vec<_> = variants + .iter() .enumerate() - .map(|(variant_index, variant)| { - serialize_variant(ident, - generics, - variant, - variant_index, - item_attrs) - }) + .map( + |(variant_index, variant)| { + serialize_variant(params, variant, variant_index as u32, cattrs) + }, + ) .collect(); quote_expr! { - match *self { + match *#self_var { #(#arms)* } } } -fn serialize_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - variant_index: usize, - item_attrs: &attr::Item) - -> Tokens { +fn serialize_variant( + params: &Parameters, + variant: &Variant, + variant_index: u32, + cattrs: &attr::Container, +) -> Tokens { + let this = ¶ms.this; let variant_ident = variant.ident.clone(); if variant.attrs.skip_serializing() { - let skipped_msg = format!("the enum variant {}::{} cannot be serialized", - ident, variant_ident); + let skipped_msg = format!( + "the enum variant {}::{} cannot be serialized", + params.type_name(), + variant_ident + ); let skipped_err = quote! { _serde::export::Err(_serde::ser::Error::custom(#skipped_msg)) }; let fields_pat = match variant.style { Style::Unit => quote!(), - Style::Newtype | Style::Tuple => quote!( (..) ), - Style::Struct => quote!( {..} ), + Style::Newtype | Style::Tuple => quote!((..)), + Style::Struct => { + quote!( + { + .. + } + ) + } }; quote! { - #ident::#variant_ident #fields_pat => #skipped_err, + #this::#variant_ident #fields_pat => #skipped_err, } } else { // variant wasn't skipped let case = match variant.style { Style::Unit => { quote! { - #ident::#variant_ident + #this::#variant_ident } } Style::Newtype => { quote! { - #ident::#variant_ident(ref __field0) + #this::#variant_ident(ref __field0) } } Style::Tuple => { - let field_names = (0..variant.fields.len()) - .map(|i| Ident::new(format!("__field{}", i))); + let field_names = + (0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i))); quote! { - #ident::#variant_ident(#(ref #field_names),*) + #this::#variant_ident(#(ref #field_names),*) } } Style::Struct => { - let fields = variant.fields + let fields = variant + .fields .iter() - .map(|f| f.ident.clone().expect("struct variant has unnamed fields")); + .map( + |f| { + f.ident + .clone() + .expect("struct variant has unnamed fields") + }, + ); quote! { - #ident::#variant_ident { #(ref #fields),* } + #this::#variant_ident { #(ref #fields),* } } } }; - let body = Match(match *item_attrs.tag() { - attr::EnumTag::External => { - serialize_externally_tagged_variant(ident, - generics, - variant, - variant_index, - item_attrs) - } - attr::EnumTag::Internal { ref tag } => { - serialize_internally_tagged_variant(ident, - generics, - variant, - item_attrs, - tag) - } - attr::EnumTag::Adjacent { ref tag, ref content } => { - serialize_adjacently_tagged_variant(ident, - generics, - variant, - item_attrs, - tag, - content) - } - attr::EnumTag::None => serialize_untagged_variant(ident, generics, variant, item_attrs), - }); + let body = Match( + match *cattrs.tag() { + attr::EnumTag::External => { + serialize_externally_tagged_variant(params, variant, variant_index, cattrs) + } + attr::EnumTag::Internal { ref tag } => { + serialize_internally_tagged_variant(params, variant, cattrs, tag) + } + attr::EnumTag::Adjacent { + ref tag, + ref content, + } => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content), + attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs), + }, + ); quote! { #case => #body @@ -289,13 +390,13 @@ fn serialize_variant(ident: &syn::Ident, } } -fn serialize_externally_tagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - variant_index: usize, - item_attrs: &attr::Item) - -> Fragment { - let type_name = item_attrs.name().serialize_name(); +fn serialize_externally_tagged_variant( + params: &Parameters, + variant: &Variant, + variant_index: u32, + cattrs: &attr::Container, +) -> Fragment { + let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); match variant.style { @@ -313,7 +414,7 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident, let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); + field_expr = wrap_serialize_with(params, field.ty, path, field_expr); } quote_expr! { @@ -327,38 +428,40 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident, } } Style::Tuple => { - serialize_tuple_variant(TupleVariant::ExternallyTagged { - type_name: type_name, - variant_index: variant_index, - variant_name: variant_name, - }, - ident, - generics, - &variant.fields) + serialize_tuple_variant( + TupleVariant::ExternallyTagged { + type_name: type_name, + variant_index: variant_index, + variant_name: variant_name, + }, + params, + &variant.fields, + ) } Style::Struct => { - serialize_struct_variant(StructVariant::ExternallyTagged { - variant_index: variant_index, - variant_name: variant_name, - }, - ident, - generics, - &variant.fields, - &type_name) + serialize_struct_variant( + StructVariant::ExternallyTagged { + variant_index: variant_index, + variant_name: variant_name, + }, + params, + &variant.fields, + &type_name, + ) } } } -fn serialize_internally_tagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - item_attrs: &attr::Item, - tag: &str) - -> Fragment { - let type_name = item_attrs.name().serialize_name(); +fn serialize_internally_tagged_variant( + params: &Parameters, + variant: &Variant, + cattrs: &attr::Container, + tag: &str, +) -> Fragment { + let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); - let enum_ident_str = ident.as_ref(); + let enum_ident_str = params.type_name(); let variant_ident_str = variant.ident.as_ref(); match variant.style { @@ -375,11 +478,11 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident, let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); + field_expr = wrap_serialize_with(params, field.ty, path, field_expr); } quote_expr! { - _serde::ser::private::serialize_tagged_newtype( + _serde::private::ser::serialize_tagged_newtype( __serializer, #enum_ident_str, #variant_ident_str, @@ -390,64 +493,66 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident, } } Style::Struct => { - serialize_struct_variant(StructVariant::InternallyTagged { - tag: tag, - variant_name: variant_name, - }, - ident, - generics, - &variant.fields, - &type_name) + serialize_struct_variant( + StructVariant::InternallyTagged { + tag: tag, + variant_name: variant_name, + }, + params, + &variant.fields, + &type_name, + ) } - Style::Tuple => unreachable!("checked in serde_codegen_internals"), + Style::Tuple => unreachable!("checked in serde_derive_internals"), } } -fn serialize_adjacently_tagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - item_attrs: &attr::Item, - tag: &str, - content: &str) - -> Fragment { - let type_name = item_attrs.name().serialize_name(); +fn serialize_adjacently_tagged_variant( + params: &Parameters, + variant: &Variant, + cattrs: &attr::Container, + tag: &str, + content: &str, +) -> Fragment { + let this = ¶ms.this; + let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); - let inner = Stmts(match variant.style { - Style::Unit => { - return quote_block! { + let inner = Stmts( + match variant.style { + Style::Unit => { + return quote_block! { let mut __struct = try!(_serde::Serializer::serialize_struct( __serializer, #type_name, 1)); try!(_serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #variant_name)); _serde::ser::SerializeStruct::end(__struct) }; - } - Style::Newtype => { - let field = &variant.fields[0]; - let mut field_expr = quote!(__field0); - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); } + Style::Newtype => { + let field = &variant.fields[0]; + let mut field_expr = quote!(__field0); + if let Some(path) = field.attrs.serialize_with() { + field_expr = wrap_serialize_with(params, field.ty, path, field_expr); + } - quote_expr! { + quote_expr! { _serde::Serialize::serialize(#field_expr, __serializer) } - } - Style::Tuple => { - serialize_tuple_variant(TupleVariant::Untagged, - ident, - generics, - &variant.fields) - } - Style::Struct => { - serialize_struct_variant(StructVariant::Untagged, - ident, - generics, - &variant.fields, - &variant_name) - } - }); + } + Style::Tuple => { + serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) + } + Style::Struct => { + serialize_struct_variant( + StructVariant::Untagged, + params, + &variant.fields, + &variant_name, + ) + } + }, + ); let fields_ty = variant.fields.iter().map(|f| &f.ty); let ref fields_ident: Vec<_> = match variant.style { @@ -459,22 +564,29 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident, .collect() } Style::Struct => { - variant.fields + variant + .fields .iter() - .map(|f| f.ident.clone().expect("struct variant has unnamed fields")) + .map( + |f| { + f.ident + .clone() + .expect("struct variant has unnamed fields") + }, + ) .collect() } }; - let (_, ty_generics, where_clause) = generics.split_for_impl(); + let (_, ty_generics, where_clause) = params.generics.split_for_impl(); - let wrapper_generics = bound::with_lifetime_bound(generics, "'__a"); + let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a"); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { struct __AdjacentlyTagged #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), - phantom: _serde::export::PhantomData<#ident #ty_generics>, + phantom: _serde::export::PhantomData<#this #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { @@ -493,17 +605,17 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident, try!(_serde::ser::SerializeStruct::serialize_field( &mut __struct, #content, &__AdjacentlyTagged { data: (#(#fields_ident,)*), - phantom: _serde::export::PhantomData::<#ident #ty_generics>, + phantom: _serde::export::PhantomData::<#this #ty_generics>, })); _serde::ser::SerializeStruct::end(__struct) } } -fn serialize_untagged_variant(ident: &syn::Ident, - generics: &syn::Generics, - variant: &Variant, - item_attrs: &attr::Item) - -> Fragment { +fn serialize_untagged_variant( + params: &Parameters, + variant: &Variant, + cattrs: &attr::Container, +) -> Fragment { match variant.style { Style::Unit => { quote_expr! { @@ -514,23 +626,17 @@ fn serialize_untagged_variant(ident: &syn::Ident, let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); + field_expr = wrap_serialize_with(params, field.ty, path, field_expr); } quote_expr! { _serde::Serialize::serialize(#field_expr, __serializer) } } - Style::Tuple => { - serialize_tuple_variant(TupleVariant::Untagged, ident, generics, &variant.fields) - } + Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), Style::Struct => { - let type_name = item_attrs.name().serialize_name(); - serialize_struct_variant(StructVariant::Untagged, - ident, - generics, - &variant.fields, - &type_name) + let type_name = cattrs.name().serialize_name(); + serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name) } } } @@ -538,17 +644,17 @@ fn serialize_untagged_variant(ident: &syn::Ident, enum TupleVariant { ExternallyTagged { type_name: String, - variant_index: usize, + variant_index: u32, variant_name: String, }, Untagged, } -fn serialize_tuple_variant(context: TupleVariant, - ident: &syn::Ident, - generics: &syn::Generics, - fields: &[Field]) - -> Fragment { +fn serialize_tuple_variant( + context: TupleVariant, + params: &Parameters, + fields: &[Field], +) -> Fragment { let method = match context { TupleVariant::ExternallyTagged { .. } => { quote!(_serde::ser::SerializeTupleVariant::serialize_field) @@ -556,14 +662,17 @@ fn serialize_tuple_variant(context: TupleVariant, TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element), }; - let serialize_stmts = - serialize_tuple_struct_visitor(ident, fields, generics, true, method); + let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, method); let len = serialize_stmts.len(); let let_mut = mut_if(len > 0); match context { - TupleVariant::ExternallyTagged { type_name, variant_index, variant_name } => { + TupleVariant::ExternallyTagged { + type_name, + variant_index, + variant_name, + } => { quote_block! { let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant( __serializer, @@ -589,19 +698,19 @@ fn serialize_tuple_variant(context: TupleVariant, enum StructVariant<'a> { ExternallyTagged { - variant_index: usize, + variant_index: u32, variant_name: String, }, InternallyTagged { tag: &'a str, variant_name: String }, Untagged, } -fn serialize_struct_variant<'a>(context: StructVariant<'a>, - ident: &syn::Ident, - generics: &syn::Generics, - fields: &[Field], - name: &str) - -> Fragment { +fn serialize_struct_variant<'a>( + context: StructVariant<'a>, + params: &Parameters, + fields: &[Field], + name: &str, +) -> Fragment { let method = match context { StructVariant::ExternallyTagged { .. } => { quote!(_serde::ser::SerializeStructVariant::serialize_field) @@ -610,26 +719,33 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>, StructVariant::Untagged => quote!(_serde::ser::SerializeStruct::serialize_field), }; - let serialize_fields = serialize_struct_visitor(ident, fields, generics, true, method); + let serialize_fields = serialize_struct_visitor(fields, params, true, method); - let mut serialized_fields = fields.iter() + let mut serialized_fields = fields + .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); - let len = serialized_fields.map(|field| { - let ident = field.ident.clone().expect("struct has unnamed fields"); + let len = serialized_fields + .map( + |field| { + let ident = field.ident.clone().expect("struct has unnamed fields"); - match field.attrs.skip_serializing_if() { - Some(path) => quote!(if #path(#ident) { 0 } else { 1 }), - None => quote!(1), - } - }) + match field.attrs.skip_serializing_if() { + Some(path) => quote!(if #path(#ident) { 0 } else { 1 }), + None => quote!(1), + } + }, + ) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); match context { - StructVariant::ExternallyTagged { variant_index, variant_name } => { + StructVariant::ExternallyTagged { + variant_index, + variant_name, + } => { quote_block! { let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant( __serializer, @@ -672,98 +788,104 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>, } } -fn serialize_tuple_struct_visitor(ident: &syn::Ident, - fields: &[Field], - generics: &syn::Generics, - is_enum: bool, - func: Tokens) - -> Vec { - fields.iter() +fn serialize_tuple_struct_visitor( + fields: &[Field], + params: &Parameters, + is_enum: bool, + func: Tokens, +) -> Vec { + fields + .iter() .enumerate() - .map(|(i, field)| { - let mut field_expr = if is_enum { - let id = Ident::new(format!("__field{}", i)); - quote!(#id) - } else { - let i = Ident::new(i); - quote!(&self.#i) - }; + .map( + |(i, field)| { + let mut field_expr = if is_enum { + let id = Ident::new(format!("__field{}", i)); + quote!(#id) + } else { + get_field(params, field, i) + }; - let skip = field.attrs - .skip_serializing_if() - .map(|path| quote!(#path(#field_expr))); + let skip = field + .attrs + .skip_serializing_if() + .map(|path| quote!(#path(#field_expr))); - if let Some(path) = field.attrs.serialize_with() { - field_expr = - wrap_serialize_with(ident, generics, field.ty, path, field_expr); - } + if let Some(path) = field.attrs.serialize_with() { + field_expr = wrap_serialize_with(params, field.ty, path, field_expr); + } - let ser = quote! { + let ser = quote! { try!(#func(&mut __serde_state, #field_expr)); }; - match skip { - None => ser, - Some(skip) => quote!(if !#skip { #ser }), - } - }) + match skip { + None => ser, + Some(skip) => quote!(if !#skip { #ser }), + } + }, + ) .collect() } -fn serialize_struct_visitor(ident: &syn::Ident, - fields: &[Field], - generics: &syn::Generics, - is_enum: bool, - func: Tokens) - -> Vec { - fields.iter() +fn serialize_struct_visitor( + fields: &[Field], + params: &Parameters, + is_enum: bool, + func: Tokens, +) -> Vec { + fields + .iter() .filter(|&field| !field.attrs.skip_serializing()) - .map(|field| { - let field_ident = field.ident.clone().expect("struct has unnamed field"); - let mut field_expr = if is_enum { - quote!(#field_ident) - } else { - quote!(&self.#field_ident) - }; + .map( + |field| { + let field_ident = field.ident.clone().expect("struct has unnamed field"); + let mut field_expr = if is_enum { + quote!(#field_ident) + } else { + get_field(params, field, field_ident) + }; - let key_expr = field.attrs.name().serialize_name(); + let key_expr = field.attrs.name().serialize_name(); - let skip = field.attrs - .skip_serializing_if() - .map(|path| quote!(#path(#field_expr))); + let skip = field + .attrs + .skip_serializing_if() + .map(|path| quote!(#path(#field_expr))); - if let Some(path) = field.attrs.serialize_with() { - field_expr = - wrap_serialize_with(ident, generics, field.ty, path, field_expr) - } + if let Some(path) = field.attrs.serialize_with() { + field_expr = wrap_serialize_with(params, field.ty, path, field_expr) + } - let ser = quote! { + let ser = quote! { try!(#func(&mut __serde_state, #key_expr, #field_expr)); }; - match skip { - None => ser, - Some(skip) => quote!(if !#skip { #ser }), - } - }) + match skip { + None => ser, + Some(skip) => quote!(if !#skip { #ser }), + } + }, + ) .collect() } -fn wrap_serialize_with(ident: &syn::Ident, - generics: &syn::Generics, - field_ty: &syn::Ty, - serialize_with: &syn::Path, - value: Tokens) - -> Tokens { - let (_, ty_generics, where_clause) = generics.split_for_impl(); +fn wrap_serialize_with( + params: &Parameters, + field_ty: &syn::Ty, + serialize_with: &syn::Path, + value: Tokens, +) -> Tokens { + let this = ¶ms.this; + let (_, ty_generics, where_clause) = params.generics.split_for_impl(); - let wrapper_generics = bound::with_lifetime_bound(generics, "'__a"); + let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a"); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote!({ struct __SerializeWith #wrapper_impl_generics #where_clause { value: &'__a #field_ty, - phantom: _serde::export::PhantomData<#ident #ty_generics>, + phantom: _serde::export::PhantomData<#this #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { @@ -776,7 +898,7 @@ fn wrap_serialize_with(ident: &syn::Ident, &__SerializeWith { value: #value, - phantom: _serde::export::PhantomData::<#ident #ty_generics>, + phantom: _serde::export::PhantomData::<#this #ty_generics>, } }) } @@ -790,3 +912,28 @@ fn wrap_serialize_with(ident: &syn::Ident, fn mut_if(is_mut: bool) -> Option { if is_mut { Some(quote!(mut)) } else { None } } + +fn get_field(params: &Parameters, field: &Field, ident: I) -> Tokens +where + I: Into, +{ + let self_var = ¶ms.self_var; + match (params.is_remote, field.attrs.getter()) { + (false, None) => { + let ident = ident.into(); + quote!(&#self_var.#ident) + } + (true, None) => { + let ty = field.ty; + let ident = ident.into(); + quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident)) + } + (true, Some(getter)) => { + let ty = field.ty; + quote!(_serde::private::ser::constrain::<#ty>(&#getter(#self_var))) + } + (false, Some(_)) => { + unreachable!("getter is only allowed for remote impls"); + } + } +} diff --git a/serde_codegen_internals/Cargo.toml b/serde_derive_internals/Cargo.toml similarity index 57% rename from serde_codegen_internals/Cargo.toml rename to serde_derive_internals/Cargo.toml index cd167bfe..85d6cb91 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -1,18 +1,19 @@ [package] -name = "serde_codegen_internals" +name = "serde_derive_internals" version = "0.14.2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" -description = "AST representation used by Serde codegen. Unstable." +description = "AST representation used by Serde derive macros. Unstable." homepage = "https://serde.rs" repository = "https://github.com/serde-rs/serde" -documentation = "https://docs.serde.rs/serde_codegen_internals/" +documentation = "https://docs.serde.rs/serde_derive_internals/" keywords = ["serde", "serialization"] -readme = "../README.md" +readme = "README.md" include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] [dependencies] -syn = { version = "0.11", default-features = false, features = ["parsing"] } +syn = { version = "0.11.10", default-features = false, features = ["parsing"] } +synom = "0.11" [badges] travis-ci = { repository = "serde-rs/serde" } diff --git a/serde_codegen_internals/LICENSE-APACHE b/serde_derive_internals/LICENSE-APACHE similarity index 100% rename from serde_codegen_internals/LICENSE-APACHE rename to serde_derive_internals/LICENSE-APACHE diff --git a/serde_codegen_internals/LICENSE-MIT b/serde_derive_internals/LICENSE-MIT similarity index 100% rename from serde_codegen_internals/LICENSE-MIT rename to serde_derive_internals/LICENSE-MIT diff --git a/serde_codegen_internals/README.md b/serde_derive_internals/README.md similarity index 100% rename from serde_codegen_internals/README.md rename to serde_derive_internals/README.md diff --git a/serde_codegen_internals/src/ast.rs b/serde_derive_internals/src/ast.rs similarity index 80% rename from serde_codegen_internals/src/ast.rs rename to serde_derive_internals/src/ast.rs index 0a50691e..7882334c 100644 --- a/serde_codegen_internals/src/ast.rs +++ b/serde_derive_internals/src/ast.rs @@ -1,10 +1,19 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use syn; use attr; +use check; use Ctxt; -pub struct Item<'a> { +pub struct Container<'a> { pub ident: syn::Ident, - pub attrs: attr::Item, + pub attrs: attr::Container, pub body: Body<'a>, pub generics: &'a syn::Generics, } @@ -27,6 +36,7 @@ pub struct Field<'a> { pub ty: &'a syn::Ty, } +#[derive(Copy, Clone)] pub enum Style { Struct, Tuple, @@ -34,9 +44,9 @@ pub enum Style { Unit, } -impl<'a> Item<'a> { - pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> { - let attrs = attr::Item::from_ast(cx, item); +impl<'a> Container<'a> { + pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Container<'a> { + let attrs = attr::Container::from_ast(cx, item); let mut body = match item.body { syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)), @@ -62,12 +72,14 @@ impl<'a> Item<'a> { } } - Item { + let item = Container { ident: item.ident.clone(), attrs: attrs, body: body, generics: &item.generics, - } + }; + check::check(cx, &item); + item } } @@ -81,6 +93,10 @@ impl<'a> Body<'a> { Body::Struct(_, ref fields) => Box::new(fields.iter()), } } + + pub fn has_getter(&self) -> bool { + self.all_fields().any(|f| f.attrs.getter().is_some()) + } } fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec> { diff --git a/serde_codegen_internals/src/attr.rs b/serde_derive_internals/src/attr.rs similarity index 65% rename from serde_codegen_internals/src/attr.rs rename to serde_derive_internals/src/attr.rs index 11a2eb2a..fd43527b 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_derive_internals/src/attr.rs @@ -1,11 +1,21 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use Ctxt; use syn; use syn::MetaItem::{List, NameValue, Word}; use syn::NestedMetaItem::{Literal, MetaItem}; +use synom::IResult; +use std::collections::BTreeSet; use std::str::FromStr; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints -// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and +// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and // `attr::Field::from_ast`. Each returns an instance of the corresponding // struct. Note that none of them return a Result. Unrecognized, malformed, or // duplicated attributes result in a span_err but otherwise are ignored. The @@ -90,7 +100,7 @@ impl Name { /// Represents container (e.g. struct) attribute information #[derive(Debug)] -pub struct Item { +pub struct Container { name: Name, deny_unknown_fields: bool, default: Default, @@ -100,6 +110,8 @@ pub struct Item { tag: EnumTag, from_type: Option, into_type: Option, + remote: Option, + identifier: Identifier, } /// Styles of representing an enum. @@ -134,7 +146,24 @@ pub enum EnumTag { None, } -impl Item { +/// Whether this enum represents the fields of a struct or the variants of an +/// enum. +#[derive(Copy, Clone, Debug)] +pub enum Identifier { + /// It does not. + No, + + /// This enum represents the fields of a struct. All of the variants must be + /// unit variants, except possibly one which is annotated with + /// `#[serde(other)]` and is a newtype variant. + Field, + + /// This enum represents the variants of an enum. All of the variants must + /// be unit variants. + Variant, +} + +impl Container { /// Extract out the `#[serde(...)]` attributes from an item. pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self { let mut ser_name = Attr::none(cx, "rename"); @@ -149,11 +178,14 @@ impl Item { let mut content = Attr::none(cx, "content"); let mut from_type = Attr::none(cx, "from"); let mut into_type = Attr::none(cx, "into"); + let mut remote = Attr::none(cx, "remote"); + let mut field_identifier = BoolAttr::none(cx, "field_identifier"); + let mut variant_identifier = BoolAttr::none(cx, "variant_identifier"); for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { match meta_item { - // Parse `#[serde(rename="foo")]` + // Parse `#[serde(rename = "foo")]` MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); @@ -161,7 +193,7 @@ impl Item { } } - // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` + // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` MetaItem(List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); @@ -169,7 +201,7 @@ impl Item { } } - // Parse `#[serde(rename_all="foo")]` + // Parse `#[serde(rename_all = "foo")]` MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { match RenameRule::from_str(&s) { @@ -201,7 +233,7 @@ impl Item { } } - // Parse `#[serde(default="...")]` + // Parse `#[serde(default = "...")]` MetaItem(NameValue(ref name, ref lit)) if name == "default" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { match item.body { @@ -216,7 +248,7 @@ impl Item { } } - // Parse `#[serde(bound="D: Serialize")]` + // Parse `#[serde(bound = "D: Serialize")]` MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { @@ -225,7 +257,7 @@ impl Item { } } - // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` + // Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]` MetaItem(List(ref name, ref meta_items)) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); @@ -288,6 +320,23 @@ impl Item { } } + // Parse `#[serde(remote = "...")]` + MetaItem(NameValue(ref name, ref lit)) if name == "remote" => { + if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { + remote.set(path); + } + } + + // Parse `#[serde(field_identifier)]` + MetaItem(Word(ref name)) if name == "field_identifier" => { + field_identifier.set_true(); + } + + // Parse `#[serde(variant_identifier)]` + MetaItem(Word(ref name)) if name == "variant_identifier" => { + variant_identifier.set_true(); + } + MetaItem(ref meta_item) => { cx.error(format!("unknown serde container attribute `{}`", meta_item.name())); @@ -300,53 +349,7 @@ impl Item { } } - let tag = match (untagged.get(), internal_tag.get(), content.get()) { - (false, None, None) => EnumTag::External, - (true, None, None) => EnumTag::None, - (false, Some(tag), None) => { - // Check that there are no tuple variants. - if let syn::Body::Enum(ref variants) = item.body { - for variant in variants { - match variant.data { - syn::VariantData::Struct(_) | - syn::VariantData::Unit => {} - syn::VariantData::Tuple(ref fields) => { - if fields.len() != 1 { - cx.error("#[serde(tag = \"...\")] cannot be used with tuple \ - variants"); - break; - } - } - } - } - } - EnumTag::Internal { tag: tag } - } - (true, Some(_), None) => { - cx.error("enum cannot be both untagged and internally tagged"); - EnumTag::External // doesn't matter, will error - } - (false, None, Some(_)) => { - cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together"); - EnumTag::External - } - (true, None, Some(_)) => { - cx.error("untagged enum cannot have #[serde(content = \"...\")]"); - EnumTag::External - } - (false, Some(tag), Some(content)) => { - EnumTag::Adjacent { - tag: tag, - content: content, - } - } - (true, Some(_), Some(_)) => { - cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"); - EnumTag::External - } - }; - - Item { + Container { name: Name { serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()), @@ -356,9 +359,11 @@ impl Item { rename_all: rename_all.get().unwrap_or(RenameRule::None), ser_bound: ser_bound.get(), de_bound: de_bound.get(), - tag: tag, + tag: decide_tag(cx, item, untagged, internal_tag, content), from_type: from_type.get(), into_type: into_type.get(), + remote: remote.get(), + identifier: decide_identifier(cx, item, field_identifier, variant_identifier), } } @@ -397,6 +402,93 @@ impl Item { pub fn into_type(&self) -> Option<&syn::Ty> { self.into_type.as_ref() } + + pub fn remote(&self) -> Option<&syn::Path> { + self.remote.as_ref() + } + + pub fn identifier(&self) -> Identifier { + self.identifier + } +} + +fn decide_tag( + cx: &Ctxt, + item: &syn::MacroInput, + untagged: BoolAttr, + internal_tag: Attr, + content: Attr, +) -> EnumTag { + match (untagged.get(), internal_tag.get(), content.get()) { + (false, None, None) => EnumTag::External, + (true, None, None) => EnumTag::None, + (false, Some(tag), None) => { + // Check that there are no tuple variants. + if let syn::Body::Enum(ref variants) = item.body { + for variant in variants { + match variant.data { + syn::VariantData::Struct(_) | + syn::VariantData::Unit => {} + syn::VariantData::Tuple(ref fields) => { + if fields.len() != 1 { + cx.error("#[serde(tag = \"...\")] cannot be used with tuple \ + variants"); + break; + } + } + } + } + } + EnumTag::Internal { tag: tag } + } + (true, Some(_), None) => { + cx.error("enum cannot be both untagged and internally tagged"); + EnumTag::External // doesn't matter, will error + } + (false, None, Some(_)) => { + cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together"); + EnumTag::External + } + (true, None, Some(_)) => { + cx.error("untagged enum cannot have #[serde(content = \"...\")]"); + EnumTag::External + } + (false, Some(tag), Some(content)) => { + EnumTag::Adjacent { + tag: tag, + content: content, + } + } + (true, Some(_), Some(_)) => { + cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"); + EnumTag::External + } + } +} + +fn decide_identifier( + cx: &Ctxt, + item: &syn::MacroInput, + field_identifier: BoolAttr, + variant_identifier: BoolAttr, +) -> Identifier { + match (&item.body, field_identifier.get(), variant_identifier.get()) { + (_, false, false) => Identifier::No, + (_, true, true) => { + cx.error("`field_identifier` and `variant_identifier` cannot both be set"); + Identifier::No + } + (&syn::Body::Struct(_), true, false) => { + cx.error("`field_identifier` can only be used on an enum"); + Identifier::No + } + (&syn::Body::Struct(_), false, true) => { + cx.error("`variant_identifier` can only be used on an enum"); + Identifier::No + } + (&syn::Body::Enum(_), true, false) => Identifier::Field, + (&syn::Body::Enum(_), false, true) => Identifier::Variant, + } } /// Represents variant attribute information @@ -408,6 +500,7 @@ pub struct Variant { rename_all: RenameRule, skip_deserializing: bool, skip_serializing: bool, + other: bool, } impl Variant { @@ -417,11 +510,12 @@ impl Variant { let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); let mut rename_all = Attr::none(cx, "rename_all"); + let mut other = BoolAttr::none(cx, "other"); for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { match meta_item { - // Parse `#[serde(rename="foo")]` + // Parse `#[serde(rename = "foo")]` MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); @@ -429,7 +523,7 @@ impl Variant { } } - // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` + // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` MetaItem(List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); @@ -437,7 +531,7 @@ impl Variant { } } - // Parse `#[serde(rename_all="foo")]` + // Parse `#[serde(rename_all = "foo")]` MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { match RenameRule::from_str(&s) { @@ -455,11 +549,17 @@ impl Variant { MetaItem(Word(ref name)) if name == "skip_deserializing" => { skip_deserializing.set_true(); } + // Parse `#[serde(skip_serializing)]` MetaItem(Word(ref name)) if name == "skip_serializing" => { skip_serializing.set_true(); } + // Parse `#[serde(other)]` + MetaItem(Word(ref name)) if name == "other" => { + other.set_true(); + } + MetaItem(ref meta_item) => { cx.error(format!("unknown serde variant attribute `{}`", meta_item.name())); } @@ -485,6 +585,7 @@ impl Variant { rename_all: rename_all.get().unwrap_or(RenameRule::None), skip_deserializing: skip_deserializing.get(), skip_serializing: skip_serializing.get(), + other: other.get(), } } @@ -512,6 +613,10 @@ impl Variant { pub fn skip_serializing(&self) -> bool { self.skip_serializing } + + pub fn other(&self) -> bool { + self.other + } } /// Represents field attribute information @@ -528,6 +633,8 @@ pub struct Field { deserialize_with: Option, ser_bound: Option>, de_bound: Option>, + borrowed_lifetimes: BTreeSet, + getter: Option, } /// Represents the default to use for a field when deserializing. @@ -554,6 +661,8 @@ impl Field { let mut deserialize_with = Attr::none(cx, "deserialize_with"); let mut ser_bound = Attr::none(cx, "bound"); let mut de_bound = Attr::none(cx, "bound"); + let mut borrowed_lifetimes = Attr::none(cx, "borrow"); + let mut getter = Attr::none(cx, "getter"); let ident = match field.ident { Some(ref ident) => ident.to_string(), @@ -563,7 +672,7 @@ impl Field { for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { match meta_item { - // Parse `#[serde(rename="foo")]` + // Parse `#[serde(rename = "foo")]` MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); @@ -571,7 +680,7 @@ impl Field { } } - // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` + // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` MetaItem(List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); @@ -584,7 +693,7 @@ impl Field { default.set(Default::Default); } - // Parse `#[serde(default="...")]` + // Parse `#[serde(default = "...")]` MetaItem(NameValue(ref name, ref lit)) if name == "default" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { default.set(Default::Path(path)); @@ -601,28 +710,28 @@ impl Field { skip_deserializing.set_true(); } - // Parse `#[serde(skip_serializing_if="...")]` + // Parse `#[serde(skip_serializing_if = "...")]` MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { skip_serializing_if.set(path); } } - // Parse `#[serde(serialize_with="...")]` + // Parse `#[serde(serialize_with = "...")]` MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { serialize_with.set(path); } } - // Parse `#[serde(deserialize_with="...")]` + // Parse `#[serde(deserialize_with = "...")]` MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { deserialize_with.set(path); } } - // Parse `#[serde(with="...")]` + // Parse `#[serde(with = "...")]` MetaItem(NameValue(ref name, ref lit)) if name == "with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { let mut ser_path = path.clone(); @@ -634,7 +743,7 @@ impl Field { } } - // Parse `#[serde(bound="D: Serialize")]` + // Parse `#[serde(bound = "D: Serialize")]` MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { @@ -643,7 +752,7 @@ impl Field { } } - // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` + // Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]` MetaItem(List(ref name, ref meta_items)) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); @@ -651,6 +760,34 @@ impl Field { } } + // Parse `#[serde(borrow)]` + MetaItem(Word(ref name)) if name == "borrow" => { + if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) { + borrowed_lifetimes.set(borrowable); + } + } + + // Parse `#[serde(borrow = "'a + 'b")]` + MetaItem(NameValue(ref name, ref lit)) if name == "borrow" => { + if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, name.as_ref(), lit) { + if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) { + for lifetime in &lifetimes { + if !borrowable.contains(lifetime) { + cx.error(format!("field `{}` does not have lifetime {}", ident, lifetime.ident)); + } + } + borrowed_lifetimes.set(lifetimes); + } + } + } + + // Parse `#[serde(getter = "...")]` + MetaItem(NameValue(ref name, ref lit)) if name == "getter" => { + if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { + getter.set(path); + } + } + MetaItem(ref meta_item) => { cx.error(format!("unknown serde field attribute `{}`", meta_item.name())); } @@ -663,11 +800,35 @@ impl Field { } // Is skip_deserializing, initialize the field to Default::default() - // unless a different default is specified by `#[serde(default="...")]` + // unless a different default is specified by `#[serde(default = "...")]` if skip_deserializing.0.value.is_some() { default.set_if_none(Default::Default); } + let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default(); + if !borrowed_lifetimes.is_empty() { + // Cow and Cow<[u8]> never borrow by default: + // + // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> + // + // A #[serde(borrow)] attribute enables borrowing that corresponds + // roughly to these impls: + // + // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str> + // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> + if is_cow(&field.ty, "str") { + let path = syn::parse_path("_serde::private::de::borrow_cow_str").unwrap(); + deserialize_with.set_if_none(path); + } else if is_cow(&field.ty, "[u8]") { + let path = syn::parse_path("_serde::private::de::borrow_cow_bytes").unwrap(); + deserialize_with.set_if_none(path); + } + } else if is_rptr(&field.ty, "str") || is_rptr(&field.ty, "[u8]") { + // Types &str and &[u8] are always implicitly borrowed. No need for + // a #[serde(borrow)]. + borrowed_lifetimes = borrowable_lifetimes(cx, &ident, &field.ty).unwrap(); + } + let ser_name = ser_name.get(); let ser_renamed = ser_name.is_some(); let de_name = de_name.get(); @@ -687,6 +848,8 @@ impl Field { deserialize_with: deserialize_with.get(), ser_bound: ser_bound.get(), de_bound: de_bound.get(), + borrowed_lifetimes: borrowed_lifetimes, + getter: getter.get(), } } @@ -734,6 +897,14 @@ impl Field { pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } + + pub fn borrowed_lifetimes(&self) -> &BTreeSet { + &self.borrowed_lifetimes + } + + pub fn getter(&self) -> Option<&syn::Path> { + self.getter.as_ref() + } } type SerAndDe = (Option, Option); @@ -836,3 +1007,174 @@ fn parse_lit_into_ty(cx: &Ctxt, cx.error(format!("failed to parse type: {} = {:?}", attr_name, string)) }) } + +// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of +// lifetimes separated by `+`. +fn parse_lit_into_lifetimes(cx: &Ctxt, + attr_name: &str, + lit: &syn::Lit) + -> Result, ()> { + let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit)); + if string.is_empty() { + cx.error("at least one lifetime must be borrowed"); + return Err(()); + } + + named!(lifetimes -> Vec, + separated_nonempty_list!(punct!("+"), syn::parse::lifetime) + ); + + if let IResult::Done(rest, o) = lifetimes(&string) { + if rest.trim().is_empty() { + let mut set = BTreeSet::new(); + for lifetime in o { + if !set.insert(lifetime.clone()) { + cx.error(format!("duplicate borrowed lifetime `{}`", lifetime.ident)); + } + } + return Ok(set); + } + } + Err(cx.error(format!("failed to parse borrowed lifetimes: {:?}", string))) +} + +// Whether the type looks like it might be `std::borrow::Cow` where elem="T". +// This can have false negatives and false positives. +// +// False negative: +// +// use std::borrow::Cow as Pig; +// +// #[derive(Deserialize)] +// struct S<'a> { +// #[serde(borrow)] +// pig: Pig<'a, str>, +// } +// +// False positive: +// +// type str = [i16]; +// +// #[derive(Deserialize)] +// struct S<'a> { +// #[serde(borrow)] +// cow: Cow<'a, str>, +// } +fn is_cow(ty: &syn::Ty, elem: &str) -> bool { + let path = match *ty { + syn::Ty::Path(None, ref path) => path, + _ => { + return false; + } + }; + let seg = match path.segments.last() { + Some(seg) => seg, + None => { + return false; + } + }; + let params = match seg.parameters { + syn::PathParameters::AngleBracketed(ref params) => params, + _ => { + return false; + } + }; + seg.ident == "Cow" + && params.lifetimes.len() == 1 + && params.types == vec![syn::parse_type(elem).unwrap()] + && params.bindings.is_empty() +} + +// Whether the type looks like it might be `&T` where elem="T". This can have +// false negatives and false positives. +// +// False negative: +// +// type Yarn = str; +// +// #[derive(Deserialize)] +// struct S<'a> { +// r: &'a Yarn, +// } +// +// False positive: +// +// type str = [i16]; +// +// #[derive(Deserialize)] +// struct S<'a> { +// r: &'a str, +// } +fn is_rptr(ty: &syn::Ty, elem: &str) -> bool { + match *ty { + syn::Ty::Rptr(Some(_), ref mut_ty) => { + mut_ty.mutability == syn::Mutability::Immutable + && mut_ty.ty == syn::parse_type(elem).unwrap() + } + _ => false, + } +} + +// All lifetimes that this type could borrow from a Deserializer. +// +// For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand +// a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer. +// +// This is used when there is an explicit or implicit `#[serde(borrow)]` +// attribute on the field so there must be at least one borrowable lifetime. +fn borrowable_lifetimes(cx: &Ctxt, + name: &str, + ty: &syn::Ty) + -> Result, ()> { + let mut lifetimes = BTreeSet::new(); + collect_lifetimes(ty, &mut lifetimes); + if lifetimes.is_empty() { + Err(cx.error(format!("field `{}` has no lifetimes to borrow", name))) + } else { + Ok(lifetimes) + } +} + +fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet) { + match *ty { + syn::Ty::Slice(ref elem) | + syn::Ty::Array(ref elem, _) | + syn::Ty::Paren(ref elem) => { + collect_lifetimes(elem, out); + } + syn::Ty::Ptr(ref elem) => { + collect_lifetimes(&elem.ty, out); + } + syn::Ty::Rptr(ref lifetime, ref elem) => { + out.extend(lifetime.iter().cloned()); + collect_lifetimes(&elem.ty, out); + } + syn::Ty::Tup(ref elems) => { + for elem in elems { + collect_lifetimes(elem, out); + } + } + syn::Ty::Path(ref qself, ref path) => { + if let Some(ref qself) = *qself { + collect_lifetimes(&qself.ty, out); + } + for seg in &path.segments { + if let syn::PathParameters::AngleBracketed(ref params) = seg.parameters { + out.extend(params.lifetimes.iter().cloned()); + for ty in ¶ms.types { + collect_lifetimes(ty, out); + } + for binding in ¶ms.bindings { + collect_lifetimes(&binding.ty, out); + } + } + } + } + syn::Ty::BareFn(_) | + syn::Ty::Never | + syn::Ty::TraitObject(_) | + syn::Ty::ImplTrait(_) | + syn::Ty::Infer | + syn::Ty::Mac(_) => {} + } +} diff --git a/serde_codegen_internals/src/case.rs b/serde_derive_internals/src/case.rs similarity index 80% rename from serde_codegen_internals/src/case.rs rename to serde_derive_internals/src/case.rs index d25d98df..e51f2e3e 100644 --- a/serde_codegen_internals/src/case.rs +++ b/serde_derive_internals/src/case.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::ascii::AsciiExt; use std::str::FromStr; @@ -7,6 +15,8 @@ use self::RenameRule::*; pub enum RenameRule { /// Don't apply a default rename rule. None, + /// Rename direct children to "lowercase" style. + LowerCase, /// Rename direct children to "PascalCase" style, as typically used for enum variants. PascalCase, /// Rename direct children to "camelCase" style. @@ -23,6 +33,7 @@ impl RenameRule { pub fn apply_to_variant(&self, variant: &str) -> String { match *self { None | PascalCase => variant.to_owned(), + LowerCase => variant.to_ascii_lowercase(), CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..], SnakeCase => { let mut snake = String::new(); @@ -41,7 +52,7 @@ impl RenameRule { pub fn apply_to_field(&self, field: &str) -> String { match *self { - None | SnakeCase => field.to_owned(), + None | LowerCase | SnakeCase => field.to_owned(), PascalCase => { let mut pascal = String::new(); let mut capitalize = true; @@ -72,6 +83,7 @@ impl FromStr for RenameRule { fn from_str(rename_all_str: &str) -> Result { match rename_all_str { + "lowercase" => Ok(LowerCase), "PascalCase" => Ok(PascalCase), "camelCase" => Ok(CamelCase), "snake_case" => Ok(SnakeCase), @@ -84,12 +96,13 @@ impl FromStr for RenameRule { #[test] fn rename_variants() { - for &(original, camel, snake, screaming, kebab) in - &[("Outcome", "outcome", "outcome", "OUTCOME", "outcome"), - ("VeryTasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"), - ("A", "a", "a", "A", "a"), - ("Z42", "z42", "z42", "Z42", "z42")] { + for &(original, lower, camel, snake, screaming, kebab) in + &[("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"), + ("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"), + ("A", "a", "a", "a", "A", "a"), + ("Z42", "z42", "z42", "z42", "Z42", "z42")] { assert_eq!(None.apply_to_variant(original), original); + assert_eq!(LowerCase.apply_to_variant(original), lower); assert_eq!(PascalCase.apply_to_variant(original), original); assert_eq!(CamelCase.apply_to_variant(original), camel); assert_eq!(SnakeCase.apply_to_variant(original), snake); diff --git a/serde_derive_internals/src/check.rs b/serde_derive_internals/src/check.rs new file mode 100644 index 00000000..5a58fbaa --- /dev/null +++ b/serde_derive_internals/src/check.rs @@ -0,0 +1,93 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ast::{Body, Container, Style}; +use attr::Identifier; +use Ctxt; + +/// Cross-cutting checks that require looking at more than a single attrs +/// object. Simpler checks should happen when parsing and building the attrs. +pub fn check(cx: &Ctxt, cont: &Container) { + check_getter(cx, cont); + check_identifier(cx, cont); +} + +/// Getters are only allowed inside structs (not enums) with the `remote` +/// attribute. +fn check_getter(cx: &Ctxt, cont: &Container) { + match cont.body { + Body::Enum(_) => { + if cont.body.has_getter() { + cx.error("#[serde(getter = \"...\")] is not allowed in an enum"); + } + } + Body::Struct(_, _) => { + if cont.body.has_getter() && cont.attrs.remote().is_none() { + cx.error("#[serde(getter = \"...\")] can only be used in structs \ + that have #[serde(remote = \"...\")]"); + } + } + } +} + +/// The `other` attribute must be used at most once and it must be the last +/// variant of an enum that has the `field_identifier` attribute. +/// +/// Inside a `variant_identifier` all variants must be unit variants. Inside a +/// `field_identifier` all but possibly one variant must be unit variants. The +/// last variant may be a newtype variant which is an implicit "other" case. +fn check_identifier(cx: &Ctxt, cont: &Container) { + let variants = match cont.body { + Body::Enum(ref variants) => variants, + Body::Struct(_, _) => { + return; + } + }; + + for (i, variant) in variants.iter().enumerate() { + match (variant.style, cont.attrs.identifier(), variant.attrs.other()) { + // The `other` attribute may only be used in a field_identifier. + (_, Identifier::Variant, true) | (_, Identifier::No, true) => { + cx.error("#[serde(other)] may only be used inside a field_identifier"); + } + + // Variant with `other` attribute must be the last one. + (Style::Unit, Identifier::Field, true) => { + if i < variants.len() - 1 { + cx.error("#[serde(other)] must be the last variant"); + } + } + + // Variant with `other` attribute must be a unit variant. + (_, Identifier::Field, true) => { + cx.error("#[serde(other)] must be on a unit variant"); + } + + // Any sort of variant is allowed if this is not an identifier. + (_, Identifier::No, false) => {} + + // Unit variant without `other` attribute is always fine. + (Style::Unit, _, false) => {} + + // The last field is allowed to be a newtype catch-all. + (Style::Newtype, Identifier::Field, false) => { + if i < variants.len() - 1 { + cx.error(format!("`{}` must be the last variant", variant.ident)); + } + } + + (_, Identifier::Field, false) => { + cx.error("field_identifier may only contain unit variants"); + } + + (_, Identifier::Variant, false) => { + cx.error("variant_identifier may only contain unit variants"); + } + } + } +} diff --git a/serde_codegen_internals/src/ctxt.rs b/serde_derive_internals/src/ctxt.rs similarity index 74% rename from serde_codegen_internals/src/ctxt.rs rename to serde_derive_internals/src/ctxt.rs index a112c7e9..80aec476 100644 --- a/serde_codegen_internals/src/ctxt.rs +++ b/serde_derive_internals/src/ctxt.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::fmt::Display; use std::cell::RefCell; diff --git a/serde_derive_internals/src/lib.rs b/serde_derive_internals/src/lib.rs new file mode 100644 index 00000000..df018f0e --- /dev/null +++ b/serde_derive_internals/src/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate syn; +#[macro_use] +extern crate synom; + +pub mod ast; +pub mod attr; + +mod ctxt; +pub use ctxt::Ctxt; + +mod case; +mod check; diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 3ca5f772..7f1c2602 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.9.14" +version = "0.9.14" # remember to update html_root_url authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -8,8 +8,9 @@ homepage = "https://serde.rs" repository = "https://github.com/serde-rs/serde" documentation = "https://docs.serde.rs/serde_test/" keywords = ["serde", "serialization"] -readme = "../README.md" +readme = "README.md" include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] +publish = false # this branch contains breaking changes [dependencies] serde = { version = "0.9", path = "../serde" } diff --git a/serde_test/src/assert.rs b/serde_test/src/assert.rs index 9d281faa..5f6e946c 100644 --- a/serde_test/src/assert.rs +++ b/serde_test/src/assert.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use serde::{Serialize, Deserialize}; use de::Deserializer; @@ -8,8 +16,9 @@ use token::Token; use std::fmt::Debug; /// Runs both `assert_ser_tokens` and `assert_de_tokens`. -pub fn assert_tokens(value: &T, tokens: &[Token<'static>]) - where T: Serialize + Deserialize + PartialEq + Debug +pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token]) +where + T: Serialize + Deserialize<'de> + PartialEq + Debug, { assert_ser_tokens(value, tokens); assert_de_tokens(value, tokens); @@ -17,38 +26,42 @@ pub fn assert_tokens(value: &T, tokens: &[Token<'static>]) /// Asserts that `value` serializes to the given `tokens`. pub fn assert_ser_tokens(value: &T, tokens: &[Token]) - where T: Serialize +where + T: Serialize, { - let mut ser = Serializer::new(tokens.iter()); + let mut ser = Serializer::new(tokens); assert_eq!(Serialize::serialize(value, &mut ser), Ok(())); assert_eq!(ser.next_token(), None); } /// Asserts that `value` serializes to the given `tokens`, and then yields `error`. pub fn assert_ser_tokens_error(value: &T, tokens: &[Token], error: Error) - where T: Serialize + PartialEq + Debug +where + T: Serialize + PartialEq + Debug, { - let mut ser = Serializer::new(tokens.iter()); + let mut ser = Serializer::new(tokens); let v: Result<(), Error> = Serialize::serialize(value, &mut ser); assert_eq!(v.as_ref(), Err(&error)); assert_eq!(ser.next_token(), None); } /// Asserts that the given `tokens` deserialize into `value`. -pub fn assert_de_tokens(value: &T, tokens: &[Token<'static>]) - where T: Deserialize + PartialEq + Debug +pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token]) +where + T: Deserialize<'de> + PartialEq + Debug, { - let mut de = Deserializer::new(tokens.to_vec().into_iter()); + let mut de = Deserializer::new(tokens); let v: Result = Deserialize::deserialize(&mut de); assert_eq!(v.as_ref(), Ok(value)); assert_eq!(de.next_token(), None); } /// Asserts that the given `tokens` yield `error` when deserializing. -pub fn assert_de_tokens_error(tokens: &[Token<'static>], error: Error) - where T: Deserialize + PartialEq + Debug +pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: Error) +where + T: Deserialize<'de> + PartialEq + Debug, { - let mut de = Deserializer::new(tokens.to_vec().into_iter()); + let mut de = Deserializer::new(tokens); let v: Result = Deserialize::deserialize(&mut de); assert_eq!(v, Err(error)); // There may be one token left if a peek caused the error diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index e975186d..bb201073 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -1,35 +1,43 @@ -use std::iter; +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. -use serde::de::{self, Deserialize, DeserializeSeed, EnumVisitor, MapVisitor, SeqVisitor, - VariantVisitor, Visitor}; -use serde::de::value::{ValueDeserializer, MapVisitorDeserializer, SeqVisitorDeserializer}; +use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, + SeqAccess, VariantAccess, Visitor}; +use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer}; use error::Error; use token::Token; /// A `Deserializer` that reads from a list of tokens. -pub struct Deserializer - where I: Iterator> -{ - tokens: iter::Peekable, +#[derive(Debug)] +pub struct Deserializer<'de> { + tokens: &'de [Token], } -impl Deserializer - where I: Iterator> -{ +impl<'de> Deserializer<'de> { /// Creates the deserializer. - pub fn new(tokens: I) -> Deserializer { - Deserializer { tokens: tokens.peekable() } + pub fn new(tokens: &'de [Token]) -> Self { + Deserializer { tokens: tokens } } /// Pulls the next token off of the deserializer, ignoring it. - pub fn next_token(&mut self) -> Option> { - self.tokens.next() + pub fn next_token(&mut self) -> Option { + if let Some((&first, rest)) = self.tokens.split_first() { + self.tokens = rest; + Some(first) + } else { + None + } } /// Pulls the next token off of the deserializer and checks if it matches an expected token. pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> { - match self.tokens.next() { + match self.next_token() { Some(token) => { if expected == token { Ok(()) @@ -41,151 +49,176 @@ impl Deserializer } } - fn visit_seq(&mut self, - len: Option, - sep: Token<'static>, - end: Token<'static>, - visitor: V) - -> Result - where V: Visitor + fn visit_seq( + &mut self, + len: Option, + end: Token, + visitor: V, + ) -> Result + where + V: Visitor<'de>, { - let value = try!(visitor.visit_seq(DeserializerSeqVisitor { - de: self, - len: len, - sep: sep, - end: end.clone(), - })); + let value = try!( + visitor.visit_seq( + DeserializerSeqVisitor { + de: self, + len: len, + end: end.clone(), + }, + ) + ); try!(self.expect_token(end)); Ok(value) } - fn visit_map(&mut self, - len: Option, - sep: Token<'static>, - end: Token<'static>, - visitor: V) - -> Result - where V: Visitor + fn visit_map( + &mut self, + len: Option, + end: Token, + visitor: V, + ) -> Result + where + V: Visitor<'de>, { - let value = try!(visitor.visit_map(DeserializerMapVisitor { - de: self, - len: len, - sep: sep, - end: end.clone(), - })); + let value = try!( + visitor.visit_map( + DeserializerMapVisitor { + de: self, + len: len, + end: end.clone(), + }, + ) + ); try!(self.expect_token(end)); Ok(value) } } -impl<'a, I> de::Deserializer for &'a mut Deserializer - where I: Iterator> -{ +impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { type Error = Error; - forward_to_deserialize! { - bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit - seq bytes byte_buf map struct_field ignored_any + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf unit seq map identifier ignored_any } - fn deserialize(self, visitor: V) -> Result - where V: Visitor + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, { - match self.tokens.next() { - Some(Token::Bool(v)) => visitor.visit_bool(v), - Some(Token::I8(v)) => visitor.visit_i8(v), - Some(Token::I16(v)) => visitor.visit_i16(v), - Some(Token::I32(v)) => visitor.visit_i32(v), - Some(Token::I64(v)) => visitor.visit_i64(v), - Some(Token::U8(v)) => visitor.visit_u8(v), - Some(Token::U16(v)) => visitor.visit_u16(v), - Some(Token::U32(v)) => visitor.visit_u32(v), - Some(Token::U64(v)) => visitor.visit_u64(v), - Some(Token::F32(v)) => visitor.visit_f32(v), - Some(Token::F64(v)) => visitor.visit_f64(v), - Some(Token::Char(v)) => visitor.visit_char(v), - Some(Token::Str(v)) => visitor.visit_str(v), - Some(Token::String(v)) => visitor.visit_string(v), - Some(Token::Bytes(v)) => visitor.visit_bytes(v), - Some(Token::ByteBuf(v)) => visitor.visit_byte_buf(v), - 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(), - Some(Token::SeqStart(len)) => { - self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor) + let token = self.next_token().ok_or(Error::EndOfTokens)?; + match token { + Token::Bool(v) => visitor.visit_bool(v), + Token::I8(v) => visitor.visit_i8(v), + Token::I16(v) => visitor.visit_i16(v), + Token::I32(v) => visitor.visit_i32(v), + Token::I64(v) => visitor.visit_i64(v), + Token::U8(v) => visitor.visit_u8(v), + Token::U16(v) => visitor.visit_u16(v), + Token::U32(v) => visitor.visit_u32(v), + Token::U64(v) => visitor.visit_u64(v), + Token::F32(v) => visitor.visit_f32(v), + Token::F64(v) => visitor.visit_f64(v), + Token::Char(v) => visitor.visit_char(v), + Token::Str(v) => visitor.visit_str(v), + Token::BorrowedStr(v) => visitor.visit_borrowed_str(v), + Token::String(v) => visitor.visit_string(v.to_owned()), + Token::Bytes(v) => visitor.visit_bytes(v), + Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v), + Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()), + Token::None => visitor.visit_none(), + Token::Some => visitor.visit_some(self), + Token::Unit => visitor.visit_unit(), + Token::UnitStruct(_name) => visitor.visit_unit(), + Token::NewtypeStruct(_name) => visitor.visit_newtype_struct(self), + Token::Seq(len) => self.visit_seq(len, Token::SeqEnd, visitor), + Token::Tuple(len) => self.visit_seq(Some(len), Token::TupleEnd, visitor), + Token::TupleStruct(_, len) => self.visit_seq(Some(len), Token::TupleStructEnd, visitor), + Token::Map(len) => self.visit_map(len, Token::MapEnd, visitor), + Token::Struct(_, len) => self.visit_map(Some(len), Token::StructEnd, visitor), + Token::Enum(_) => { + let variant = self.next_token().ok_or(Error::EndOfTokens)?; + let next = *self.tokens.first().ok_or(Error::EndOfTokens)?; + match (variant, next) { + (Token::Str(variant), Token::Unit) => { + self.next_token(); + visitor.visit_str(variant) + } + (Token::Bytes(variant), Token::Unit) => { + self.next_token(); + visitor.visit_bytes(variant) + } + (Token::U32(variant), Token::Unit) => { + self.next_token(); + visitor.visit_u32(variant) + } + (variant, Token::Unit) => Err(Error::UnexpectedToken(variant)), + (variant, _) => { + visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any)) + } + } } - Some(Token::SeqArrayStart(len)) => { - self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) + Token::UnitVariant(_, variant) => visitor.visit_str(variant), + Token::NewtypeVariant(_, variant) => { + visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),) } - Some(Token::TupleStart(len)) => { - self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor) + Token::TupleVariant(_, variant, _) => { + visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),) } - Some(Token::TupleStructStart(_, len)) => { - self.visit_seq(Some(len), - Token::TupleStructSep, - Token::TupleStructEnd, - visitor) + Token::StructVariant(_, variant, _) => { + visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),) } - Some(Token::MapStart(len)) => { - self.visit_map(len, Token::MapSep, Token::MapEnd, visitor) + Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd | + Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => { + Err(Error::UnexpectedToken(token)) } - Some(Token::StructStart(_, len)) => { - self.visit_map(Some(len), Token::StructSep, Token::StructEnd, visitor) - } - Some(Token::EnumUnit(_, variant)) => visitor.visit_str(variant), - Some(Token::EnumStart(variant)) | - Some(Token::EnumNewType(_, variant)) | - Some(Token::EnumSeqStart(_, variant, _)) | - Some(Token::EnumMapStart(_, variant, _)) => { - visitor.visit_map(EnumMapVisitor::new(self, variant)) - } - Some(token) => Err(Error::UnexpectedToken(token)), - None => Err(Error::EndOfTokens), } } /// Hook into `Option` deserializing so we can treat `Unit` as a /// `None`, or a regular value as `Some(value)`. fn deserialize_option(self, visitor: V) -> Result - where V: Visitor + where + V: Visitor<'de>, { - match self.tokens.peek() { + match self.tokens.first() { Some(&Token::Unit) | - Some(&Token::Option(false)) => { - self.tokens.next(); + Some(&Token::None) => { + self.next_token(); visitor.visit_none() } - Some(&Token::Option(true)) => { - self.tokens.next(); + Some(&Token::Some) => { + self.next_token(); visitor.visit_some(self) } - Some(_) => visitor.visit_some(self), + Some(_) => self.deserialize_any(visitor), None => Err(Error::EndOfTokens), } } - fn deserialize_enum(self, - name: &str, - _variants: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor + fn deserialize_enum( + self, + name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, { - match self.tokens.peek() { - Some(&Token::EnumStart(n)) if name == n => { - self.tokens.next(); + match self.tokens.first() { + Some(&Token::Enum(n)) if name == n => { + self.next_token(); visitor.visit_enum(DeserializerEnumVisitor { de: self }) } - Some(&Token::EnumUnit(n, _)) | - Some(&Token::EnumNewType(n, _)) | - Some(&Token::EnumSeqStart(n, _, _)) | - Some(&Token::EnumMapStart(n, _, _)) if name == n => { + Some(&Token::UnitVariant(n, _)) | + Some(&Token::NewtypeVariant(n, _)) | + Some(&Token::TupleVariant(n, _, _)) | + Some(&Token::StructVariant(n, _, _)) if name == n => { visitor.visit_enum(DeserializerEnumVisitor { de: self }) } Some(_) => { - let token = self.tokens.next().unwrap(); + let token = self.next_token().unwrap(); Err(Error::UnexpectedToken(token)) } None => Err(Error::EndOfTokens), @@ -193,157 +226,134 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer } fn deserialize_unit_struct(self, name: &str, visitor: V) -> Result - where V: Visitor + where + V: Visitor<'de>, { - match self.tokens.peek() { + match self.tokens.first() { Some(&Token::UnitStruct(n)) => { - self.tokens.next(); + self.next_token(); if name == n { visitor.visit_unit() } else { Err(Error::InvalidName(n)) } } - Some(_) => self.deserialize(visitor), + Some(_) => self.deserialize_any(visitor), None => Err(Error::EndOfTokens), } } fn deserialize_newtype_struct(self, name: &str, visitor: V) -> Result - where V: Visitor + where + V: Visitor<'de>, { - match self.tokens.peek() { - Some(&Token::StructNewType(n)) => { - self.tokens.next(); + match self.tokens.first() { + Some(&Token::NewtypeStruct(n)) => { + self.next_token(); if name == n { visitor.visit_newtype_struct(self) } else { Err(Error::InvalidName(n)) } } - Some(_) => self.deserialize(visitor), - None => Err(Error::EndOfTokens), - } - } - - fn deserialize_seq_fixed_size(self, len: usize, visitor: V) -> Result - where V: Visitor - { - match self.tokens.peek() { - Some(&Token::SeqArrayStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) - } - Some(_) => self.deserialize(visitor), + Some(_) => self.deserialize_any(visitor), None => Err(Error::EndOfTokens), } } fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where V: Visitor + where + V: Visitor<'de>, { - match self.tokens.peek() { + match self.tokens.first() { Some(&Token::Unit) | Some(&Token::UnitStruct(_)) => { - self.tokens.next(); + self.next_token(); visitor.visit_unit() } - Some(&Token::SeqStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) + Some(&Token::Seq(_)) => { + self.next_token(); + self.visit_seq(Some(len), Token::SeqEnd, visitor) } - Some(&Token::SeqArrayStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) + Some(&Token::Tuple(_)) => { + self.next_token(); + self.visit_seq(Some(len), Token::TupleEnd, visitor) } - Some(&Token::TupleStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor) + Some(&Token::TupleStruct(_, _)) => { + self.next_token(); + self.visit_seq(Some(len), Token::TupleStructEnd, visitor) } - Some(&Token::TupleStructStart(_, _)) => { - self.tokens.next(); - self.visit_seq(Some(len), - Token::TupleStructSep, - Token::TupleStructEnd, - visitor) - } - Some(_) => self.deserialize(visitor), + Some(_) => self.deserialize_any(visitor), None => Err(Error::EndOfTokens), } } - fn deserialize_tuple_struct(self, - name: &str, - len: usize, - visitor: V) - -> Result - where V: Visitor + fn deserialize_tuple_struct( + self, + name: &str, + len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, { - match self.tokens.peek() { + match self.tokens.first() { Some(&Token::Unit) => { - self.tokens.next(); + self.next_token(); visitor.visit_unit() } Some(&Token::UnitStruct(n)) => { - self.tokens.next(); + self.next_token(); if name == n { visitor.visit_unit() } else { Err(Error::InvalidName(n)) } } - Some(&Token::SeqStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) + Some(&Token::Seq(_)) => { + self.next_token(); + self.visit_seq(Some(len), Token::SeqEnd, visitor) } - Some(&Token::SeqArrayStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) + Some(&Token::Tuple(_)) => { + self.next_token(); + self.visit_seq(Some(len), Token::TupleEnd, visitor) } - Some(&Token::TupleStart(_)) => { - self.tokens.next(); - self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor) - } - Some(&Token::TupleStructStart(n, _)) => { - self.tokens.next(); + Some(&Token::TupleStruct(n, _)) => { + self.next_token(); if name == n { - self.visit_seq(Some(len), - Token::TupleStructSep, - Token::TupleStructEnd, - visitor) + self.visit_seq(Some(len), Token::TupleStructEnd, visitor) } else { Err(Error::InvalidName(n)) } } - Some(_) => self.deserialize(visitor), + Some(_) => self.deserialize_any(visitor), None => Err(Error::EndOfTokens), } } - fn deserialize_struct(self, - name: &str, - fields: &'static [&'static str], - visitor: V) - -> Result - where V: Visitor + fn deserialize_struct( + self, + name: &str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, { - match self.tokens.peek() { - Some(&Token::StructStart(n, _)) => { - self.tokens.next(); + match self.tokens.first() { + Some(&Token::Struct(n, _)) => { + self.next_token(); if name == n { - self.visit_map(Some(fields.len()), - Token::StructSep, - Token::StructEnd, - visitor) + self.visit_map(Some(fields.len()), Token::StructEnd, visitor) } else { Err(Error::InvalidName(n)) } } - Some(&Token::MapStart(_)) => { - self.tokens.next(); - self.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor) + Some(&Token::Map(_)) => { + self.next_token(); + self.visit_map(Some(fields.len()), Token::MapEnd, visitor) } - Some(_) => self.deserialize(visitor), + Some(_) => self.deserialize_any(visitor), None => Err(Error::EndOfTokens), } } @@ -351,108 +361,84 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer ////////////////////////////////////////////////////////////////////////// -struct DeserializerSeqVisitor<'a, I: 'a> - where I: Iterator> -{ - de: &'a mut Deserializer, +struct DeserializerSeqVisitor<'a, 'de: 'a> { + de: &'a mut Deserializer<'de>, len: Option, - sep: Token<'static>, - end: Token<'static>, + end: Token, } -impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I> - where I: Iterator> -{ +impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> { type Error = Error; - fn visit_seed(&mut self, seed: T) -> Result, Error> - where T: DeserializeSeed + fn next_element_seed(&mut self, seed: T) -> Result, Error> + where + T: DeserializeSeed<'de>, { - if self.de.tokens.peek() == Some(&self.end) { + if self.de.tokens.first() == Some(&self.end) { return Ok(None); } - match self.de.tokens.next() { - Some(ref token) if *token == self.sep => { - self.len = self.len.map(|len| len.saturating_sub(1)); - seed.deserialize(&mut *self.de).map(Some) - } - Some(other) => Err(Error::UnexpectedToken(other)), - None => Err(Error::EndOfTokens), - } + self.len = self.len.map(|len| len.saturating_sub(1)); + seed.deserialize(&mut *self.de).map(Some) } - fn size_hint(&self) -> (usize, Option) { - let len = self.len.unwrap_or(0); - (len, self.len) + fn size_hint(&self) -> Option { + self.len } } ////////////////////////////////////////////////////////////////////////// -struct DeserializerMapVisitor<'a, I: 'a> - where I: Iterator> -{ - de: &'a mut Deserializer, +struct DeserializerMapVisitor<'a, 'de: 'a> { + de: &'a mut Deserializer<'de>, len: Option, - sep: Token<'static>, - end: Token<'static>, + end: Token, } -impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I> - where I: Iterator> -{ +impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> { type Error = Error; - fn visit_key_seed(&mut self, seed: K) -> Result, Error> - where K: DeserializeSeed + fn next_key_seed(&mut self, seed: K) -> Result, Error> + where + K: DeserializeSeed<'de>, { - if self.de.tokens.peek() == Some(&self.end) { + if self.de.tokens.first() == Some(&self.end) { return Ok(None); } - match self.de.tokens.next() { - Some(ref token) if *token == self.sep => { - self.len = self.len.map(|len| len.saturating_sub(1)); - seed.deserialize(&mut *self.de).map(Some) - } - Some(other) => Err(Error::UnexpectedToken(other)), - None => Err(Error::EndOfTokens), - } + self.len = self.len.map(|len| len.saturating_sub(1)); + seed.deserialize(&mut *self.de).map(Some) } - fn visit_value_seed(&mut self, seed: V) -> Result - where V: DeserializeSeed + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, { seed.deserialize(&mut *self.de) } - fn size_hint(&self) -> (usize, Option) { - let len = self.len.unwrap_or(0); - (len, self.len) + fn size_hint(&self) -> Option { + self.len } } ////////////////////////////////////////////////////////////////////////// -struct DeserializerEnumVisitor<'a, I: 'a> - where I: Iterator> -{ - de: &'a mut Deserializer, +struct DeserializerEnumVisitor<'a, 'de: 'a> { + de: &'a mut Deserializer<'de>, } -impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I> - where I: Iterator> -{ +impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> { type Error = Error; type Variant = Self; - fn visit_variant_seed(self, seed: V) -> Result<(V::Value, Self), Error> - where V: DeserializeSeed + fn variant_seed(self, seed: V) -> Result<(V::Value, Self), Error> + where + V: DeserializeSeed<'de>, { - match self.de.tokens.peek() { - Some(&Token::EnumUnit(_, v)) | - Some(&Token::EnumNewType(_, v)) | - Some(&Token::EnumSeqStart(_, v, _)) | - Some(&Token::EnumMapStart(_, v, _)) => { + match self.de.tokens.first() { + Some(&Token::UnitVariant(_, v)) | + Some(&Token::NewtypeVariant(_, v)) | + Some(&Token::TupleVariant(_, v, _)) | + Some(&Token::StructVariant(_, v, _)) => { let de = v.into_deserializer(); let value = try!(seed.deserialize(de)); Ok((value, self)) @@ -466,15 +452,13 @@ impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I> } } -impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> - where I: Iterator> -{ +impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> { type Error = Error; - fn visit_unit(self) -> Result<(), Error> { - match self.de.tokens.peek() { - Some(&Token::EnumUnit(_, _)) => { - self.de.tokens.next(); + fn unit_variant(self) -> Result<(), Error> { + match self.de.tokens.first() { + Some(&Token::UnitVariant(_, _)) => { + self.de.next_token(); Ok(()) } Some(_) => Deserialize::deserialize(self.de), @@ -482,12 +466,13 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> } } - fn visit_newtype_seed(self, seed: T) -> Result - where T: DeserializeSeed + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, { - match self.de.tokens.peek() { - Some(&Token::EnumNewType(_, _)) => { - self.de.tokens.next(); + match self.de.tokens.first() { + Some(&Token::NewtypeVariant(_, _)) => { + self.de.next_token(); seed.deserialize(self.de) } Some(_) => seed.deserialize(self.de), @@ -495,59 +480,61 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> } } - fn visit_tuple(self, len: usize, visitor: V) -> Result - where V: Visitor + fn tuple_variant(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, { - match self.de.tokens.peek() { - Some(&Token::EnumSeqStart(_, _, enum_len)) => { - let token = self.de.tokens.next().unwrap(); + match self.de.tokens.first() { + Some(&Token::TupleVariant(_, _, enum_len)) => { + let token = self.de.next_token().unwrap(); if len == enum_len { - self.de.visit_seq(Some(len), Token::EnumSeqSep, Token::EnumSeqEnd, visitor) + self.de + .visit_seq(Some(len), Token::TupleVariantEnd, visitor) } else { Err(Error::UnexpectedToken(token)) } } - Some(&Token::SeqStart(Some(enum_len))) => { - let token = self.de.tokens.next().unwrap(); + Some(&Token::Seq(Some(enum_len))) => { + let token = self.de.next_token().unwrap(); if len == enum_len { - self.de.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) + self.de.visit_seq(Some(len), Token::SeqEnd, visitor) } else { Err(Error::UnexpectedToken(token)) } } - Some(_) => de::Deserializer::deserialize(self.de, visitor), + Some(_) => de::Deserializer::deserialize_any(self.de, visitor), None => Err(Error::EndOfTokens), } } - fn visit_struct(self, fields: &'static [&'static str], visitor: V) -> Result - where V: Visitor + fn struct_variant(self, fields: &'static [&'static str], visitor: V) -> Result + where + V: Visitor<'de>, { - match self.de.tokens.peek() { - Some(&Token::EnumMapStart(_, _, enum_len)) => { - let token = self.de.tokens.next().unwrap(); + match self.de.tokens.first() { + Some(&Token::StructVariant(_, _, enum_len)) => { + let token = self.de.next_token().unwrap(); if fields.len() == enum_len { - self.de.visit_map(Some(fields.len()), - Token::EnumMapSep, - Token::EnumMapEnd, - visitor) + self.de + .visit_map(Some(fields.len()), Token::StructVariantEnd, visitor) } else { Err(Error::UnexpectedToken(token)) } } - Some(&Token::MapStart(Some(enum_len))) => { - let token = self.de.tokens.next().unwrap(); + Some(&Token::Map(Some(enum_len))) => { + let token = self.de.next_token().unwrap(); if fields.len() == enum_len { - self.de.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor) + self.de + .visit_map(Some(fields.len()), Token::MapEnd, visitor) } else { Err(Error::UnexpectedToken(token)) } } - Some(_) => de::Deserializer::deserialize(self.de, visitor), + Some(_) => de::Deserializer::deserialize_any(self.de, visitor), None => Err(Error::EndOfTokens), } } @@ -555,69 +542,98 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> ////////////////////////////////////////////////////////////////////////// -struct EnumMapVisitor<'a, I: 'a> - where I: Iterator> -{ - de: &'a mut Deserializer, - variant: Option<&'a str>, +struct EnumMapVisitor<'a, 'de: 'a> { + de: &'a mut Deserializer<'de>, + variant: Option, + format: EnumFormat, } -impl<'a, I: 'a> EnumMapVisitor<'a, I> - where I: Iterator> -{ - fn new(de: &'a mut Deserializer, variant: &'a str) -> Self { +enum EnumFormat { + Seq, + Map, + Any, +} + +impl<'a, 'de> EnumMapVisitor<'a, 'de> { + fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self { EnumMapVisitor { de: de, variant: Some(variant), + format: format, } } } -impl<'a, I: 'a> MapVisitor for EnumMapVisitor<'a, I> - where I: Iterator> -{ +impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> { type Error = Error; - fn visit_key_seed(&mut self, seed: K) -> Result, Error> - where K: DeserializeSeed + fn next_key_seed(&mut self, seed: K) -> Result, Error> + where + K: DeserializeSeed<'de>, { match self.variant.take() { - Some(variant) => seed.deserialize(variant.into_deserializer()).map(Some), + Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), + Some(Token::Bytes(variant)) => { + seed.deserialize(BytesDeserializer { value: variant }) + .map(Some) + } + Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), + Some(other) => Err(Error::UnexpectedToken(other)), None => Ok(None), } } - fn visit_value_seed(&mut self, seed: V) -> Result - where V: DeserializeSeed + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, { - match self.de.tokens.peek() { - Some(&Token::EnumSeqSep) => { + match self.format { + EnumFormat::Seq => { let value = { let visitor = DeserializerSeqVisitor { de: self.de, len: None, - sep: Token::EnumSeqSep, - end: Token::EnumSeqEnd, + end: Token::TupleVariantEnd, }; - try!(seed.deserialize(SeqVisitorDeserializer::new(visitor))) + try!(seed.deserialize(SeqAccessDeserializer::new(visitor))) }; - try!(self.de.expect_token(Token::EnumSeqEnd)); + try!(self.de.expect_token(Token::TupleVariantEnd)); Ok(value) } - Some(&Token::EnumMapSep) => { + EnumFormat::Map => { let value = { let visitor = DeserializerMapVisitor { de: self.de, len: None, - sep: Token::EnumMapSep, - end: Token::EnumMapEnd, + end: Token::StructVariantEnd, }; - try!(seed.deserialize(MapVisitorDeserializer::new(visitor))) + try!(seed.deserialize(MapAccessDeserializer::new(visitor))) }; - try!(self.de.expect_token(Token::EnumMapEnd)); + try!(self.de.expect_token(Token::StructVariantEnd)); Ok(value) } - _ => seed.deserialize(&mut *self.de), + EnumFormat::Any => seed.deserialize(&mut *self.de), } } } + +struct BytesDeserializer { + value: &'static [u8], +} + +impl<'de> de::Deserializer<'de> for BytesDeserializer { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_bytes(self.value) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum identifier ignored_any + } +} diff --git a/serde_test/src/error.rs b/serde_test/src/error.rs index 507cfd46..034a019a 100644 --- a/serde_test/src/error.rs +++ b/serde_test/src/error.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::error; use std::fmt::{self, Display}; @@ -15,7 +23,7 @@ pub enum Error { InvalidName(&'static str), /// `Serialize` generated a token that didn't match the test. - UnexpectedToken(Token<'static>), + UnexpectedToken(Token), /// The expected token list was too short. EndOfTokens, diff --git a/serde_test/src/lib.rs b/serde_test/src/lib.rs index 29668e8c..346e0d70 100644 --- a/serde_test/src/lib.rs +++ b/serde_test/src/lib.rs @@ -1,3 +1,13 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![doc(html_root_url = "https://docs.rs/serde_test/0.9.13")] + #[macro_use] extern crate serde; diff --git a/serde_test/src/ser.rs b/serde_test/src/ser.rs index 93608a19..5c90fee4 100644 --- a/serde_test/src/ser.rs +++ b/serde_test/src/ser.rs @@ -1,4 +1,10 @@ -use std::marker::PhantomData; +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. use serde::{ser, Serialize}; @@ -6,33 +12,54 @@ use error::Error; use token::Token; /// A `Serializer` that ensures that a value serializes to a given list of tokens. -pub struct Serializer<'a, I> - where I: Iterator> -{ - tokens: I, - phantom: PhantomData<&'a Token<'a>>, +#[derive(Debug)] +pub struct Serializer<'a> { + tokens: &'a [Token], } -impl<'a, I> Serializer<'a, I> - where I: Iterator> -{ +impl<'a> Serializer<'a> { /// Creates the serializer. - pub fn new(tokens: I) -> Serializer<'a, I> { - Serializer { - tokens: tokens, - phantom: PhantomData, - } + pub fn new(tokens: &'a [Token]) -> Self { + Serializer { tokens: tokens } } /// Pulls the next token off of the serializer, ignoring it. - pub fn next_token(&mut self) -> Option<&'a Token<'a>> { - self.tokens.next() + pub fn next_token(&mut self) -> Option { + if let Some((&first, rest)) = self.tokens.split_first() { + self.tokens = rest; + Some(first) + } else { + None + } } } -impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I> - where I: Iterator> -{ +macro_rules! assert_next_token { + ($ser:ident, $expected:ident($a:expr)) => { + assert_next_token!($ser, $expected { a: $a }); + }; + ($ser:ident, $expected:ident($a:expr, $b:expr)) => { + assert_next_token!($ser, $expected { a: $a, b: $b }); + }; + ($ser:ident, $expected:ident($a:expr, $b:expr, $c:expr)) => { + assert_next_token!($ser, $expected { a: $a, b: $b, c: $c }); + }; + ($ser:ident, $expected:ident $({ $($n:ident: $v:expr),* })*) => { + match $ser.next_token() { + Some(Token::$expected $(($($n),*))*) $(if $($n == $v)&&*)* => {} + Some(other) => { + panic!("expected Token::{} but serialized as {:?}", + stringify!($expected), other); + } + None => { + panic!("expected Token::{} after end of serialized tokens", + stringify!($expected)); + } + } + }; +} + +impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { type Ok = (); type Error = Error; @@ -45,322 +72,321 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I> type SerializeStructVariant = Self; fn serialize_bool(self, v: bool) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::Bool(v))); + assert_next_token!(self, Bool(v)); Ok(()) } fn serialize_i8(self, v: i8) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::I8(v))); + assert_next_token!(self, I8(v)); Ok(()) } fn serialize_i16(self, v: i16) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::I16(v))); + assert_next_token!(self, I16(v)); Ok(()) } fn serialize_i32(self, v: i32) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::I32(v))); + assert_next_token!(self, I32(v)); Ok(()) } fn serialize_i64(self, v: i64) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::I64(v))); + assert_next_token!(self, I64(v)); Ok(()) } fn serialize_u8(self, v: u8) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::U8(v))); + assert_next_token!(self, U8(v)); Ok(()) } fn serialize_u16(self, v: u16) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::U16(v))); + assert_next_token!(self, U16(v)); Ok(()) } fn serialize_u32(self, v: u32) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::U32(v))); + assert_next_token!(self, U32(v)); Ok(()) } fn serialize_u64(self, v: u64) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::U64(v))); + assert_next_token!(self, U64(v)); Ok(()) } fn serialize_f32(self, v: f32) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::F32(v))); + assert_next_token!(self, F32(v)); Ok(()) } fn serialize_f64(self, v: f64) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::F64(v))); + assert_next_token!(self, F64(v)); Ok(()) } fn serialize_char(self, v: char) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::Char(v))); + assert_next_token!(self, Char(v)); Ok(()) } fn serialize_str(self, v: &str) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::Str(v))); + assert_next_token!(self, Str(v)); Ok(()) } fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> { - assert_eq!(self.tokens.next(), Some(&Token::Bytes(value))); + assert_next_token!(self, Bytes(value)); Ok(()) } fn serialize_unit(self) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::Unit)); + assert_next_token!(self, Unit); Ok(()) } - fn serialize_unit_struct(self, name: &str) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name))); + fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> { + assert_next_token!(self, UnitStruct(name)); Ok(()) } - fn serialize_unit_variant(self, - name: &str, - _variant_index: usize, - variant: &str) - -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant))); + fn serialize_unit_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<(), Error> { + if self.tokens.first() == Some(&Token::Enum(name)) { + self.next_token(); + assert_next_token!(self, Str(variant)); + assert_next_token!(self, Unit); + } else { + assert_next_token!(self, UnitVariant(name, variant)); + } Ok(()) } fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<(), Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name))); + assert_next_token!(self, NewtypeStruct(name)); value.serialize(self) } - fn serialize_newtype_variant(self, - name: &str, - _variant_index: usize, - variant: &str, - value: &T) - -> Result<(), Error> - where T: Serialize + fn serialize_newtype_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<(), Error> + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant))); + if self.tokens.first() == Some(&Token::Enum(name)) { + self.next_token(); + assert_next_token!(self, Str(variant)); + } else { + assert_next_token!(self, NewtypeVariant(name, variant)); + } value.serialize(self) } fn serialize_none(self) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::Option(false))); + assert_next_token!(self, None); Ok(()) } fn serialize_some(self, value: &T) -> Result<(), Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::Option(true))); + assert_next_token!(self, Some); value.serialize(self) } fn serialize_seq(self, len: Option) -> Result { - assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len))); - Ok(self) - } - - fn serialize_seq_fixed_size(self, len: usize) -> Result { - assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len))); + assert_next_token!(self, Seq(len)); Ok(self) } fn serialize_tuple(self, len: usize) -> Result { - assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len))); + assert_next_token!(self, Tuple(len)); Ok(self) } fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result { - assert_eq!(self.tokens.next(), - Some(&Token::TupleStructStart(name, len))); + assert_next_token!(self, TupleStruct(name, len)); Ok(self) } - fn serialize_tuple_variant(self, - name: &str, - _variant_index: usize, - variant: &str, - len: usize) - -> Result { - assert_eq!(self.tokens.next(), - Some(&Token::EnumSeqStart(name, variant, len))); + fn serialize_tuple_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + assert_next_token!(self, TupleVariant(name, variant, len)); Ok(self) } fn serialize_map(self, len: Option) -> Result { - assert_eq!(self.tokens.next(), Some(&Token::MapStart(len))); + assert_next_token!(self, Map(len)); Ok(self) } - fn serialize_struct(self, name: &str, len: usize) -> Result { - assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len))); + fn serialize_struct(self, name: &'static str, len: usize) -> Result { + assert_next_token!(self, Struct(name, len)); Ok(self) } - fn serialize_struct_variant(self, - name: &str, - _variant_index: usize, - variant: &str, - len: usize) - -> Result { - assert_eq!(self.tokens.next(), - Some(&Token::EnumMapStart(name, variant, len))); + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + assert_next_token!(self, StructVariant(name, variant, len)); Ok(self) } } -impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> { type Ok = (); type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::SeqSep)); value.serialize(&mut **self) } fn end(self) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::SeqEnd)); + assert_next_token!(self, SeqEnd); Ok(()) } } -impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> { type Ok = (); type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::TupleSep)); value.serialize(&mut **self) } fn end(self) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::TupleEnd)); + assert_next_token!(self, TupleEnd); Ok(()) } } -impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> { type Ok = (); type Error = Error; fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep)); value.serialize(&mut **self) } fn end(self) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd)); + assert_next_token!(self, TupleStructEnd); Ok(()) } } -impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> { type Ok = (); type Error = Error; fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep)); value.serialize(&mut **self) } fn end(self) -> Result<(), Error> { - assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd)); + assert_next_token!(self, TupleVariantEnd); Ok(()) } } -impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> { type Ok = (); type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> - where T: Serialize + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::MapSep)); key.serialize(&mut **self) } fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> - where T: Serialize + where + T: Serialize, { value.serialize(&mut **self) } fn end(self) -> Result<(), Self::Error> { - assert_eq!(self.tokens.next(), Some(&Token::MapEnd)); + assert_next_token!(self, MapEnd); Ok(()) } } -impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> { type Ok = (); type Error = Error; - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), Self::Error> - where T: Serialize + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::StructSep)); try!(key.serialize(&mut **self)); value.serialize(&mut **self) } fn end(self) -> Result<(), Self::Error> { - assert_eq!(self.tokens.next(), Some(&Token::StructEnd)); + assert_next_token!(self, StructEnd); Ok(()) } } -impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I> - where I: Iterator> -{ +impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> { type Ok = (); type Error = Error; - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), Self::Error> - where T: Serialize + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep)); try!(key.serialize(&mut **self)); value.serialize(&mut **self) } fn end(self) -> Result<(), Self::Error> { - assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd)); + assert_next_token!(self, StructVariantEnd); Ok(()) } } diff --git a/serde_test/src/token.rs b/serde_test/src/token.rs index 82ccd9f2..07bbc0b9 100644 --- a/serde_test/src/token.rs +++ b/serde_test/src/token.rs @@ -1,5 +1,13 @@ -#[derive(Clone, PartialEq, Debug)] -pub enum Token<'a> { +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Token { /// A serialized `bool`. Bool(bool), @@ -37,90 +45,75 @@ pub enum Token<'a> { Char(char), /// A serialized `str`. - Str(&'a str), + Str(&'static str), + + /// A borrowed `str`. + BorrowedStr(&'static str), /// A serialized `String`. - String(String), + String(&'static str), /// A serialized `[u8]` - Bytes(&'a [u8]), + Bytes(&'static [u8]), + + /// A borrowed `[u8]`. + BorrowedBytes(&'static [u8]), /// A serialized `ByteBuf` - ByteBuf(Vec), + ByteBuf(&'static [u8]), - /// The header to a serialized `Option`. + /// The header to a serialized `Option` containing some value. /// - /// `None` is serialized as `Option(false)`, while `Some` is serialized as `Option(true)`, then - /// the value contained in the option. - Option(bool), + /// The tokens of the value follow after this header. + Some, + + /// A serialized `Option` containing none. + None, /// A serialized `()`. Unit, /// A serialized unit struct of the given name. - UnitStruct(&'a str), + UnitStruct(&'static str), /// The header to a serialized newtype struct of the given name. /// /// Newtype structs are serialized with this header, followed by the value contained in the /// newtype struct. - StructNewType(&'a str), + NewtypeStruct(&'static str), /// The header to an enum of the given name. - /// - /// This token is only used for deserializers, and ensures that the following tokens are read as - /// an enum. Because this is never emitted by serializers, calling `assert_ser_tokens` or - /// `assert_tokens` will fail if this token is used. - /// - /// TODO: Trash this. - EnumStart(&'a str), + Enum(&'static str), /// A unit variant of an enum of the given name, of the given name. /// /// The first string represents the name of the enum, and the second represents the name of the /// variant. - EnumUnit(&'a str, &'a str), + UnitVariant(&'static str, &'static str), /// The header to a newtype variant of an enum of the given name, of the given name. /// /// The first string represents the name of the enum, and the second represents the name of the /// variant. The value contained within this enum works the same as `StructNewType`. - EnumNewType(&'a str, &'a str), + NewtypeVariant(&'static str, &'static str), /// The header to a sequence of the given length. /// /// These are serialized via `serialize_seq`, which takes an optional length. After this /// header is a list of elements, followed by `SeqEnd`. - SeqStart(Option), - - /// The header to an array of the given length. - /// - /// These are serialized via `serialize_seq_fized_size`, which requires a length. After this - /// header is a list of elements, followed by `SeqEnd`. - SeqArrayStart(usize), - - /// A separator, which occurs *before* every element in a sequence. - /// - /// Elements in sequences are represented by a `SeqSep`, followed by the value of the element. - SeqSep, + Seq(Option), /// An indicator of the end of a sequence. SeqEnd, - /// The header to a tuple of the given length, similar to `SeqArrayStart`. - TupleStart(usize), - - /// A separator, similar to `SeqSep`. - TupleSep, + /// The header to a tuple of the given length, similar to `SeqFixedSize`. + Tuple(usize), /// An indicator of the end of a tuple, similar to `SeqEnd`. TupleEnd, /// The header to a tuple struct of the given name and length. - TupleStructStart(&'a str, usize), - - /// A separator, similar to `TupleSep`. - TupleStructSep, + TupleStruct(&'static str, usize), /// An indicator of the end of a tuple struct, similar to `TupleEnd`. TupleStructEnd, @@ -129,42 +122,27 @@ pub enum Token<'a> { /// /// These are serialized via `serialize_map`, which takes an optional length. After this header /// is a list of key-value pairs, followed by `MapEnd`. - MapStart(Option), - - /// A separator, which occurs *before* every key-value pair in a map. - /// - /// Elements in maps are represented by a `MapSep`, followed by a serialized key, followed - /// by a serialized value. - MapSep, + Map(Option), /// An indicator of the end of a map. MapEnd, - /// The header of a struct of the given name and length, similar to `MapStart`. - StructStart(&'a str, usize), - - /// A separator, similar to `MapSep`. - StructSep, + /// The header of a struct of the given name and length, similar to `Map`. + Struct(&'static str, usize), /// An indicator of the end of a struct, similar to `MapEnd`. StructEnd, /// The header to a tuple variant of an enum of the given name, of the given name and length. - EnumSeqStart(&'a str, &'a str, usize), - - /// A separator, similar to `TupleSep`. - EnumSeqSep, + TupleVariant(&'static str, &'static str, usize), /// An indicator of the end of a tuple variant, similar to `TupleEnd`. - EnumSeqEnd, + TupleVariantEnd, /// The header of a struct variant of an enum of the given name, of the given name and length, - /// similar to `StructStart`. - EnumMapStart(&'a str, &'a str, usize), - - /// A separator, similar to `StructSep`. - EnumMapSep, + /// similar to `Struct`. + StructVariant(&'static str, &'static str, usize), /// An indicator of the end of a struct, similar to `StructEnd`. - EnumMapEnd, + StructVariantEnd, } diff --git a/test_suite/tests/compile-fail/borrow/bad_lifetimes.rs b/test_suite/tests/compile-fail/borrow/bad_lifetimes.rs new file mode 100644 index 00000000..a33968f3 --- /dev/null +++ b/test_suite/tests/compile-fail/borrow/bad_lifetimes.rs @@ -0,0 +1,18 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +struct Test<'a> { + #[serde(borrow = "zzz")] //~^^ HELP: failed to parse borrowed lifetimes: "zzz" + s: &'a str, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/borrow/duplicate_lifetime.rs b/test_suite/tests/compile-fail/borrow/duplicate_lifetime.rs new file mode 100644 index 00000000..482a8411 --- /dev/null +++ b/test_suite/tests/compile-fail/borrow/duplicate_lifetime.rs @@ -0,0 +1,18 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +struct Test<'a> { + #[serde(borrow = "'a + 'a")] //~^^ HELP: duplicate borrowed lifetime `'a` + s: &'a str, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/borrow/empty_lifetimes.rs b/test_suite/tests/compile-fail/borrow/empty_lifetimes.rs new file mode 100644 index 00000000..0aec052b --- /dev/null +++ b/test_suite/tests/compile-fail/borrow/empty_lifetimes.rs @@ -0,0 +1,18 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +struct Test<'a> { + #[serde(borrow = "")] //~^^ HELP: at least one lifetime must be borrowed + s: &'a str, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/borrow/no_lifetimes.rs b/test_suite/tests/compile-fail/borrow/no_lifetimes.rs new file mode 100644 index 00000000..ca0f0409 --- /dev/null +++ b/test_suite/tests/compile-fail/borrow/no_lifetimes.rs @@ -0,0 +1,18 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +struct Test { + #[serde(borrow)] //~^^ HELP: field `s` has no lifetimes to borrow + s: String, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/borrow/wrong_lifetime.rs b/test_suite/tests/compile-fail/borrow/wrong_lifetime.rs new file mode 100644 index 00000000..707cd118 --- /dev/null +++ b/test_suite/tests/compile-fail/borrow/wrong_lifetime.rs @@ -0,0 +1,18 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +struct Test<'a> { + #[serde(borrow = "'b")] //~^^ HELP: field `s` does not have lifetime 'b + s: &'a str, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/default-attribute/enum.rs b/test_suite/tests/compile-fail/default-attribute/enum.rs index 74c5d7ca..7b0649bb 100644 --- a/test_suite/tests/compile-fail/default-attribute/enum.rs +++ b/test_suite/tests/compile-fail/default-attribute/enum.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/default-attribute/nameless_struct_fields.rs b/test_suite/tests/compile-fail/default-attribute/nameless_struct_fields.rs index 2e8bccc6..83aec668 100644 --- a/test_suite/tests/compile-fail/default-attribute/nameless_struct_fields.rs +++ b/test_suite/tests/compile-fail/default-attribute/nameless_struct_fields.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/rename-and-ser.rs b/test_suite/tests/compile-fail/duplicate-attribute/rename-and-ser.rs index c55a7140..cc94685c 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/rename-and-ser.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/rename-and-ser.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/rename-rename-de.rs b/test_suite/tests/compile-fail/duplicate-attribute/rename-rename-de.rs index 92b02a8d..9b02357a 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/rename-rename-de.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/rename-rename-de.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs b/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs index 3f3ead14..b8434413 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs b/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs index 5f160c40..8aee5131 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs b/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs index 7792bf6a..25c50fa2 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/two-rename-ser.rs b/test_suite/tests/compile-fail/duplicate-attribute/two-rename-ser.rs index 31d903ee..96a65732 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/two-rename-ser.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/two-rename-ser.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/duplicate-attribute/with-and-serialize-with.rs b/test_suite/tests/compile-fail/duplicate-attribute/with-and-serialize-with.rs index 9d6058f6..9ca98995 100644 --- a/test_suite/tests/compile-fail/duplicate-attribute/with-and-serialize-with.rs +++ b/test_suite/tests/compile-fail/duplicate-attribute/with-and-serialize-with.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/enum-representation/internal-tuple-variant.rs b/test_suite/tests/compile-fail/enum-representation/internal-tuple-variant.rs index c399ab07..6b02bfd0 100644 --- a/test_suite/tests/compile-fail/enum-representation/internal-tuple-variant.rs +++ b/test_suite/tests/compile-fail/enum-representation/internal-tuple-variant.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/enum-representation/internally-tagged-struct.rs b/test_suite/tests/compile-fail/enum-representation/internally-tagged-struct.rs index bd4fe2ea..31615ff6 100644 --- a/test_suite/tests/compile-fail/enum-representation/internally-tagged-struct.rs +++ b/test_suite/tests/compile-fail/enum-representation/internally-tagged-struct.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/enum-representation/untagged-and-internal.rs b/test_suite/tests/compile-fail/enum-representation/untagged-and-internal.rs index 71104ff6..4edbf004 100644 --- a/test_suite/tests/compile-fail/enum-representation/untagged-and-internal.rs +++ b/test_suite/tests/compile-fail/enum-representation/untagged-and-internal.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/enum-representation/untagged-struct.rs b/test_suite/tests/compile-fail/enum-representation/untagged-struct.rs index 0bf6dd13..3546748e 100644 --- a/test_suite/tests/compile-fail/enum-representation/untagged-struct.rs +++ b/test_suite/tests/compile-fail/enum-representation/untagged-struct.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/identifier/both.rs b/test_suite/tests/compile-fail/identifier/both.rs new file mode 100644 index 00000000..13a8d917 --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/both.rs @@ -0,0 +1,19 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier, variant_identifier)] //~^ HELP: `field_identifier` and `variant_identifier` cannot both be set +enum F { + A, + B, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/field_struct.rs b/test_suite/tests/compile-fail/identifier/field_struct.rs new file mode 100644 index 00000000..79b380d9 --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/field_struct.rs @@ -0,0 +1,16 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier)] +struct S; //~^^ HELP: `field_identifier` can only be used on an enum + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/field_tuple.rs b/test_suite/tests/compile-fail/identifier/field_tuple.rs new file mode 100644 index 00000000..7b26885d --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/field_tuple.rs @@ -0,0 +1,19 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier)] +enum F { + A, + B(u8, u8), //~^^^^ HELP: field_identifier may only contain unit variants +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/newtype_not_last.rs b/test_suite/tests/compile-fail/identifier/newtype_not_last.rs new file mode 100644 index 00000000..f601be3e --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/newtype_not_last.rs @@ -0,0 +1,20 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier)] +enum F { + A, + Other(String), //~^^^^ HELP: `Other` must be the last variant + B, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/not_identifier.rs b/test_suite/tests/compile-fail/identifier/not_identifier.rs new file mode 100644 index 00000000..3dd6d65f --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/not_identifier.rs @@ -0,0 +1,19 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +enum F { + A, + #[serde(other)] //~^^^ HELP: #[serde(other)] may only be used inside a field_identifier + B, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/not_unit.rs b/test_suite/tests/compile-fail/identifier/not_unit.rs new file mode 100644 index 00000000..dfc65df2 --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/not_unit.rs @@ -0,0 +1,20 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier)] +enum F { + A, + #[serde(other)] //~^^^^ HELP: #[serde(other)] must be on a unit variant + Other(u8, u8), +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/other_not_last.rs b/test_suite/tests/compile-fail/identifier/other_not_last.rs new file mode 100644 index 00000000..481f4764 --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/other_not_last.rs @@ -0,0 +1,21 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier)] +enum F { + A, + #[serde(other)] //~^^^^ HELP: #[serde(other)] must be the last variant + Other, + B, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/serialize.rs b/test_suite/tests/compile-fail/identifier/serialize.rs new file mode 100644 index 00000000..1c928b3f --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/serialize.rs @@ -0,0 +1,19 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: proc-macro derive panicked +#[serde(field_identifier)] //~^ HELP: field identifiers cannot be serialized +enum F { + A, + B, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/variant_struct.rs b/test_suite/tests/compile-fail/identifier/variant_struct.rs new file mode 100644 index 00000000..aeb37f9a --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/variant_struct.rs @@ -0,0 +1,16 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(variant_identifier)] +struct S; //~^^ HELP: `variant_identifier` can only be used on an enum + +fn main() {} diff --git a/test_suite/tests/compile-fail/identifier/variant_tuple.rs b/test_suite/tests/compile-fail/identifier/variant_tuple.rs new file mode 100644 index 00000000..9ea2ee2e --- /dev/null +++ b/test_suite/tests/compile-fail/identifier/variant_tuple.rs @@ -0,0 +1,19 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked +#[serde(variant_identifier)] +enum F { + A, + B(u8, u8), //~^^^^ HELP: variant_identifier may only contain unit variants +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/bad_getter.rs b/test_suite/tests/compile-fail/remote/bad_getter.rs new file mode 100644 index 00000000..7b01c9cf --- /dev/null +++ b/test_suite/tests/compile-fail/remote/bad_getter.rs @@ -0,0 +1,25 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S { + a: u8, + } +} + +#[derive(Serialize)] //~ ERROR: proc-macro derive panicked +#[serde(remote = "remote::S")] +struct S { + #[serde(getter = "~~~")] //~^^^ HELP: failed to parse path: "~~~" + a: u8, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/bad_remote.rs b/test_suite/tests/compile-fail/remote/bad_remote.rs new file mode 100644 index 00000000..a81627db --- /dev/null +++ b/test_suite/tests/compile-fail/remote/bad_remote.rs @@ -0,0 +1,24 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S { + a: u8, + } +} + +#[derive(Serialize)] //~ ERROR: proc-macro derive panicked +#[serde(remote = "~~~")] //~^ HELP: failed to parse path: "~~~" +struct S { + a: u8, +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/enum_getter.rs b/test_suite/tests/compile-fail/remote/enum_getter.rs new file mode 100644 index 00000000..016cfc03 --- /dev/null +++ b/test_suite/tests/compile-fail/remote/enum_getter.rs @@ -0,0 +1,27 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub enum E { + A { a: u8 } + } +} + +#[derive(Serialize)] //~ ERROR: proc-macro derive panicked +#[serde(remote = "remote::E")] +pub enum E { + A { + #[serde(getter = "get_a")] //~^^^^ HELP: #[serde(getter = "...")] is not allowed in an enum + a: u8, + } +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/missing_field.rs b/test_suite/tests/compile-fail/remote/missing_field.rs new file mode 100644 index 00000000..d4ceca3c --- /dev/null +++ b/test_suite/tests/compile-fail/remote/missing_field.rs @@ -0,0 +1,25 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S { + pub a: u8, + pub b: u8, + } +} + +#[derive(Serialize, Deserialize)] //~ ERROR: missing field `b` in initializer of `remote::S` +#[serde(remote = "remote::S")] +struct S { + a: u8, //~^^^ ERROR: missing field `b` in initializer of `remote::S` +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/nonremote_getter.rs b/test_suite/tests/compile-fail/remote/nonremote_getter.rs new file mode 100644 index 00000000..ce7539be --- /dev/null +++ b/test_suite/tests/compile-fail/remote/nonremote_getter.rs @@ -0,0 +1,24 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: proc-macro derive panicked +struct S { + #[serde(getter = "S::get")] //~^^ HELP: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")] + a: u8, +} + +impl S { + fn get(&self) -> u8 { + self.a + } +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/unknown_field.rs b/test_suite/tests/compile-fail/remote/unknown_field.rs new file mode 100644 index 00000000..d1f2206c --- /dev/null +++ b/test_suite/tests/compile-fail/remote/unknown_field.rs @@ -0,0 +1,24 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S { + pub a: u8, + } +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::S")] +struct S { + b: u8, //~^^^ ERROR: no field `b` on type `&remote::S` +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/wrong_de.rs b/test_suite/tests/compile-fail/remote/wrong_de.rs new file mode 100644 index 00000000..10e97986 --- /dev/null +++ b/test_suite/tests/compile-fail/remote/wrong_de.rs @@ -0,0 +1,20 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S(pub u16); +} + +#[derive(Deserialize)] //~ ERROR: mismatched types +#[serde(remote = "remote::S")] +struct S(u8); //~^^ expected u16, found u8 + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/wrong_getter.rs b/test_suite/tests/compile-fail/remote/wrong_getter.rs new file mode 100644 index 00000000..e939928a --- /dev/null +++ b/test_suite/tests/compile-fail/remote/wrong_getter.rs @@ -0,0 +1,31 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S { + a: u8, + } + + impl S { + pub fn get(&self) -> u16 { + self.a as u16 + } + } +} + +#[derive(Serialize)] //~ ERROR: mismatched types +#[serde(remote = "remote::S")] +struct S { + #[serde(getter = "remote::S::get")] + a: u8, //~^^^^ expected u8, found u16 +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/remote/wrong_ser.rs b/test_suite/tests/compile-fail/remote/wrong_ser.rs new file mode 100644 index 00000000..ac3c7c24 --- /dev/null +++ b/test_suite/tests/compile-fail/remote/wrong_ser.rs @@ -0,0 +1,24 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +mod remote { + pub struct S { + pub a: u16, + } +} + +#[derive(Serialize)] //~ ERROR: mismatched types +#[serde(remote = "remote::S")] +struct S { + a: u8, //~^^^ expected u8, found u16 +} + +fn main() {} diff --git a/test_suite/tests/compile-fail/str_ref_deser.rs b/test_suite/tests/compile-fail/str_ref_deser.rs deleted file mode 100644 index 51f03f5c..00000000 --- a/test_suite/tests/compile-fail/str_ref_deser.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[macro_use] -extern crate serde_derive; - -#[derive(Serialize, Deserialize)] //~ ERROR: proc-macro derive panicked -struct Test<'a> { - s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str -} - -fn main() {} diff --git a/test_suite/tests/compile-fail/type-attribute/from.rs b/test_suite/tests/compile-fail/type-attribute/from.rs index 408f33b5..72e0f1de 100644 --- a/test_suite/tests/compile-fail/type-attribute/from.rs +++ b/test_suite/tests/compile-fail/type-attribute/from.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/type-attribute/into.rs b/test_suite/tests/compile-fail/type-attribute/into.rs index 62a0982a..8f6de4d4 100644 --- a/test_suite/tests/compile-fail/type-attribute/into.rs +++ b/test_suite/tests/compile-fail/type-attribute/into.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/unknown-attribute/container.rs b/test_suite/tests/compile-fail/unknown-attribute/container.rs index 9bf97a19..c60c99c1 100644 --- a/test_suite/tests/compile-fail/unknown-attribute/container.rs +++ b/test_suite/tests/compile-fail/unknown-attribute/container.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/unknown-attribute/field.rs b/test_suite/tests/compile-fail/unknown-attribute/field.rs index 82915b21..66c3a0a8 100644 --- a/test_suite/tests/compile-fail/unknown-attribute/field.rs +++ b/test_suite/tests/compile-fail/unknown-attribute/field.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compile-fail/unknown-attribute/variant.rs b/test_suite/tests/compile-fail/unknown-attribute/variant.rs index de3ec976..0cfac627 100644 --- a/test_suite/tests/compile-fail/unknown-attribute/variant.rs +++ b/test_suite/tests/compile-fail/unknown-attribute/variant.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; diff --git a/test_suite/tests/compiletest.rs b/test_suite/tests/compiletest.rs index a4773093..f5fb664e 100644 --- a/test_suite/tests/compiletest.rs +++ b/test_suite/tests/compiletest.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![cfg(feature = "unstable")] extern crate compiletest_rs as compiletest; diff --git a/test_suite/tests/macros.rs b/test_suite/tests/macros.rs index fdf61515..4f6ea66e 100644 --- a/test_suite/tests/macros.rs +++ b/test_suite/tests/macros.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + macro_rules! btreeset { () => { BTreeSet::new() diff --git a/test_suite/tests/run-pass/identity-op.rs b/test_suite/tests/run-pass/identity-op.rs index e1638025..2ec0cc19 100644 --- a/test_suite/tests/run-pass/identity-op.rs +++ b/test_suite/tests/run-pass/identity-op.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![deny(identity_op)] #[macro_use] diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index af49203b..74376209 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; @@ -5,14 +13,8 @@ extern crate serde; use self::serde::{Serialize, Serializer, Deserialize, Deserializer}; extern crate serde_test; -use self::serde_test::{ - Error, - Token, - assert_tokens, - assert_ser_tokens, - assert_de_tokens, - assert_de_tokens_error -}; +use self::serde_test::{Error, Token, assert_tokens, assert_ser_tokens, assert_de_tokens, + assert_de_tokens_error}; trait MyDefault: Sized { fn my_default() -> Self; @@ -24,25 +26,32 @@ trait ShouldSkip: Sized { trait SerializeWith: Sized { fn serialize_with(&self, ser: S) -> Result - where S: Serializer; + where + S: Serializer; } trait DeserializeWith: Sized { - fn deserialize_with(de: D) -> Result - where D: Deserializer; + fn deserialize_with<'de, D>(de: D) -> Result + where + D: Deserializer<'de>; } impl MyDefault for i32 { - fn my_default() -> Self { 123 } + fn my_default() -> Self { + 123 + } } impl ShouldSkip for i32 { - fn should_skip(&self) -> bool { *self == 123 } + fn should_skip(&self) -> bool { + *self == 123 + } } impl SerializeWith for i32 { fn serialize_with(&self, ser: S) -> Result - where S: Serializer + where + S: Serializer, { if *self == 123 { true.serialize(ser) @@ -53,8 +62,9 @@ impl SerializeWith for i32 { } impl DeserializeWith for i32 { - fn deserialize_with(de: D) -> Result - where D: Deserializer + fn deserialize_with<'de, D>(de: D) -> Result + where + D: Deserializer<'de>, { if try!(Deserialize::deserialize(de)) { Ok(123) @@ -66,8 +76,9 @@ impl DeserializeWith for i32 { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct DefaultStruct - where C: MyDefault, - E: MyDefault, +where + C: MyDefault, + E: MyDefault, { a1: A, #[serde(default)] @@ -83,52 +94,59 @@ struct DefaultStruct #[test] fn test_default_struct() { assert_de_tokens( - &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, + &DefaultStruct { + a1: 1, + a2: 2, + a3: 3, + a4: 0, + a5: 123, + }, &[ - Token::StructStart("DefaultStruct", 3), + Token::Struct("DefaultStruct", 3), - Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::StructSep, Token::Str("a2"), Token::I32(2), - Token::StructSep, Token::Str("a3"), Token::I32(3), - Token::StructSep, Token::Str("a4"), Token::I32(4), - Token::StructSep, Token::Str("a5"), Token::I32(5), Token::StructEnd, - ] + ], ); assert_de_tokens( - &DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 }, + &DefaultStruct { + a1: 1, + a2: 0, + a3: 123, + a4: 0, + a5: 123, + }, &[ - Token::StructStart("DefaultStruct", 1), + Token::Struct("DefaultStruct", 1), - Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructEnd, - ] + ], ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum DefaultEnum - where C: MyDefault, - E: MyDefault +where + C: MyDefault, + E: MyDefault, { Struct { a1: A, @@ -140,51 +158,57 @@ enum DefaultEnum a4: D, #[serde(skip_deserializing, default="MyDefault::my_default")] a5: E, - } + }, } #[test] fn test_default_enum() { assert_de_tokens( - &DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, + &DefaultEnum::Struct { + a1: 1, + a2: 2, + a3: 3, + a4: 0, + a5: 123, + }, &[ - Token::EnumMapStart("DefaultEnum", "Struct", 3), + Token::StructVariant("DefaultEnum", "Struct", 3), - Token::EnumMapSep, Token::Str("a1"), Token::I32(1), - Token::EnumMapSep, Token::Str("a2"), Token::I32(2), - Token::EnumMapSep, Token::Str("a3"), Token::I32(3), - Token::EnumMapSep, Token::Str("a4"), Token::I32(4), - Token::EnumMapSep, Token::Str("a5"), Token::I32(5), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_de_tokens( - &DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 }, + &DefaultEnum::Struct { + a1: 1, + a2: 0, + a3: 123, + a4: 0, + a5: 123, + }, &[ - Token::EnumMapStart("DefaultEnum", "Struct", 3), + Token::StructVariant("DefaultEnum", "Struct", 3), - Token::EnumMapSep, Token::Str("a1"), Token::I32(1), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -210,24 +234,20 @@ struct ContainsNoStdDefault { fn test_no_std_default() { assert_de_tokens( &ContainsNoStdDefault { a: NoStdDefault(123) }, - &[ - Token::StructStart("ContainsNoStdDefault", 1), - Token::StructEnd, - ] + &[Token::Struct("ContainsNoStdDefault", 1), Token::StructEnd], ); assert_de_tokens( &ContainsNoStdDefault { a: NoStdDefault(8) }, &[ - Token::StructStart("ContainsNoStdDefault", 1), + Token::Struct("ContainsNoStdDefault", 1), - Token::StructSep, Token::Str("a"), - Token::StructNewType("NoStdDefault"), + Token::NewtypeStruct("NoStdDefault"), Token::I8(8), Token::StructEnd, - ] + ], ); } @@ -242,8 +262,9 @@ impl Default for NotDeserializeStruct { } impl DeserializeWith for NotDeserializeStruct { - fn deserialize_with(_: D) -> Result - where D: Deserializer + fn deserialize_with<'de, D>(_: D) -> Result + where + D: Deserializer<'de>, { panic!() } @@ -251,7 +272,9 @@ impl DeserializeWith for NotDeserializeStruct { // Does not implement Deserialize. #[derive(Debug, PartialEq)] -enum NotDeserializeEnum { Trouble } +enum NotDeserializeEnum { + Trouble, +} impl MyDefault for NotDeserializeEnum { fn my_default() -> Self { @@ -278,15 +301,12 @@ struct ContainsNotDeserialize { fn test_elt_not_deserialize() { assert_de_tokens( &ContainsNotDeserialize { - a: NotDeserializeStruct(123), - b: NotDeserializeStruct(123), - c: NotDeserializeStruct(123), - e: NotDeserializeEnum::Trouble, - }, - &[ - Token::StructStart("ContainsNotDeserialize", 3), - Token::StructEnd, - ] + a: NotDeserializeStruct(123), + b: NotDeserializeStruct(123), + c: NotDeserializeStruct(123), + e: NotDeserializeEnum::Trouble, + }, + &[Token::Struct("ContainsNotDeserialize", 3), Token::StructEnd], ); } @@ -300,53 +320,50 @@ struct DenyUnknown { fn test_ignore_unknown() { // 'Default' allows unknown. Basic smoke test of ignore... assert_de_tokens( - &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, + &DefaultStruct { + a1: 1, + a2: 2, + a3: 3, + a4: 0, + a5: 123, + }, &[ - Token::StructStart("DefaultStruct", 5), + Token::Struct("DefaultStruct", 5), - Token::StructSep, Token::Str("whoops1"), Token::I32(2), - Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::StructSep, Token::Str("whoops2"), - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(2), Token::SeqEnd, - Token::StructSep, Token::Str("a2"), Token::I32(2), - Token::StructSep, Token::Str("whoops3"), Token::I32(2), - Token::StructSep, Token::Str("a3"), Token::I32(3), Token::StructEnd, - ] + ], ); assert_de_tokens_error::( &[ - Token::StructStart("DenyUnknown", 2), + Token::Struct("DenyUnknown", 2), - Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::StructSep, Token::Str("whoops"), ], - Error::Message("unknown field `whoops`, expected `a1`".to_owned()) + Error::Message("unknown field `whoops`, expected `a1`".to_owned()), ); } @@ -371,52 +388,46 @@ fn test_rename_struct() { assert_tokens( &RenameStruct { a1: 1, a2: 2 }, &[ - Token::StructStart("Superhero", 2), + Token::Struct("Superhero", 2), - Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::StructSep, Token::Str("a3"), Token::I32(2), Token::StructEnd, - ] + ], ); assert_ser_tokens( &RenameStructSerializeDeserialize { a1: 1, a2: 2 }, &[ - Token::StructStart("SuperheroSer", 2), + Token::Struct("SuperheroSer", 2), - Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::StructSep, Token::Str("a4"), Token::I32(2), Token::StructEnd, - ] + ], ); assert_de_tokens( &RenameStructSerializeDeserialize { a1: 1, a2: 2 }, &[ - Token::StructStart("SuperheroDe", 2), + Token::Struct("SuperheroDe", 2), - Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::StructSep, Token::Str("a5"), Token::I32(2), Token::StructEnd, - ] + ], ); } @@ -452,90 +463,81 @@ enum RenameEnumSerializeDeserialize { fn test_rename_enum() { assert_tokens( &RenameEnum::Batman, - &[ - Token::EnumUnit("Superhero", "bruce_wayne"), - ] + &[Token::UnitVariant("Superhero", "bruce_wayne")], ); assert_tokens( &RenameEnum::Superman(0), &[ - Token::EnumNewType("Superhero", "clark_kent"), + Token::NewtypeVariant("Superhero", "clark_kent"), Token::I8(0), - ] + ], ); assert_tokens( &RenameEnum::WonderWoman(0, 1), &[ - Token::EnumSeqStart("Superhero", "diana_prince", 2), - - Token::EnumSeqSep, + Token::TupleVariant("Superhero", "diana_prince", 2), Token::I8(0), - - Token::EnumSeqSep, Token::I8(1), - - Token::EnumSeqEnd, - ] + Token::TupleVariantEnd, + ], ); assert_tokens( &RenameEnum::Flash { a: 1 }, &[ - Token::EnumMapStart("Superhero", "barry_allan", 1), + Token::StructVariant("Superhero", "barry_allan", 1), - Token::EnumMapSep, Token::Str("b"), Token::I32(1), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_ser_tokens( &RenameEnumSerializeDeserialize::Robin { - a: 0, - b: String::new(), - }, + a: 0, + b: String::new(), + }, &[ - Token::EnumMapStart("SuperheroSer", "dick_grayson", 2), + Token::StructVariant("SuperheroSer", "dick_grayson", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(0), - Token::EnumMapSep, Token::Str("c"), Token::Str(""), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_de_tokens( &RenameEnumSerializeDeserialize::Robin { - a: 0, - b: String::new(), - }, + a: 0, + b: String::new(), + }, &[ - Token::EnumMapStart("SuperheroDe", "jason_todd", 2), + Token::StructVariant("SuperheroDe", "jason_todd", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(0), - Token::EnumMapSep, Token::Str("d"), Token::Str(""), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } #[derive(Debug, PartialEq, Serialize)] -struct SkipSerializingStruct<'a, B, C> where C: ShouldSkip { +struct SkipSerializingStruct<'a, B, C> +where + C: ShouldSkip, +{ a: &'a i8, #[serde(skip_serializing)] b: B, @@ -547,94 +549,83 @@ struct SkipSerializingStruct<'a, B, C> where C: ShouldSkip { fn test_skip_serializing_struct() { let a = 1; assert_ser_tokens( - &SkipSerializingStruct { - a: &a, - b: 2, - c: 3, - }, + &SkipSerializingStruct { a: &a, b: 2, c: 3 }, &[ - Token::StructStart("SkipSerializingStruct", 2), + Token::Struct("SkipSerializingStruct", 2), - Token::StructSep, Token::Str("a"), Token::I8(1), - Token::StructSep, Token::Str("c"), Token::I32(3), Token::StructEnd, - ] + ], ); assert_ser_tokens( &SkipSerializingStruct { - a: &a, - b: 2, - c: 123, - }, + a: &a, + b: 2, + c: 123, + }, &[ - Token::StructStart("SkipSerializingStruct", 1), + Token::Struct("SkipSerializingStruct", 1), - Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructEnd, - ] + ], ); } #[derive(Debug, PartialEq, Serialize)] -enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip { +enum SkipSerializingEnum<'a, B, C> +where + C: ShouldSkip, +{ Struct { a: &'a i8, #[serde(skip_serializing)] _b: B, #[serde(skip_serializing_if="ShouldSkip::should_skip")] c: C, - } + }, } #[test] fn test_skip_serializing_enum() { let a = 1; assert_ser_tokens( - &SkipSerializingEnum::Struct { - a: &a, - _b: 2, - c: 3, - }, + &SkipSerializingEnum::Struct { a: &a, _b: 2, c: 3 }, &[ - Token::EnumMapStart("SkipSerializingEnum", "Struct", 2), + Token::StructVariant("SkipSerializingEnum", "Struct", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_ser_tokens( &SkipSerializingEnum::Struct { - a: &a, - _b: 2, - c: 123, - }, + a: &a, + _b: 2, + c: 123, + }, &[ - Token::EnumMapStart("SkipSerializingEnum", "Struct", 1), + Token::StructVariant("SkipSerializingEnum", "Struct", 1), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -642,18 +633,25 @@ fn test_skip_serializing_enum() { struct NotSerializeStruct(i8); #[derive(Debug, PartialEq)] -enum NotSerializeEnum { Trouble } +enum NotSerializeEnum { + Trouble, +} impl SerializeWith for NotSerializeEnum { fn serialize_with(&self, ser: S) -> Result - where S: Serializer + where + S: Serializer, { "trouble".serialize(ser) } } #[derive(Debug, PartialEq, Serialize)] -struct ContainsNotSerialize<'a, B, C, D> where B: 'a, D: SerializeWith { +struct ContainsNotSerialize<'a, B, C, D> +where + B: 'a, + D: SerializeWith, +{ a: &'a Option, #[serde(skip_serializing)] b: &'a B, @@ -668,30 +666,31 @@ fn test_elt_not_serialize() { let a = 1; assert_ser_tokens( &ContainsNotSerialize { - a: &Some(a), - b: &NotSerializeStruct(2), - c: Some(NotSerializeEnum::Trouble), - d: NotSerializeEnum::Trouble, - }, + a: &Some(a), + b: &NotSerializeStruct(2), + c: Some(NotSerializeEnum::Trouble), + d: NotSerializeEnum::Trouble, + }, &[ - Token::StructStart("ContainsNotSerialize", 2), + Token::Struct("ContainsNotSerialize", 2), - Token::StructSep, Token::Str("a"), - Token::Option(true), + Token::Some, Token::I8(1), - Token::StructSep, Token::Str("d"), Token::Str("trouble"), Token::StructEnd, - ] + ], ); } #[derive(Debug, PartialEq, Serialize)] -struct SerializeWithStruct<'a, B> where B: SerializeWith { +struct SerializeWithStruct<'a, B> +where + B: SerializeWith, +{ a: &'a i8, #[serde(serialize_with="SerializeWith::serialize_with")] b: B, @@ -701,101 +700,87 @@ struct SerializeWithStruct<'a, B> where B: SerializeWith { fn test_serialize_with_struct() { let a = 1; assert_ser_tokens( - &SerializeWithStruct { - a: &a, - b: 2, - }, + &SerializeWithStruct { a: &a, b: 2 }, &[ - Token::StructStart("SerializeWithStruct", 2), + Token::Struct("SerializeWithStruct", 2), - Token::StructSep, Token::Str("a"), Token::I8(1), - Token::StructSep, Token::Str("b"), Token::Bool(false), Token::StructEnd, - ] + ], ); assert_ser_tokens( - &SerializeWithStruct { - a: &a, - b: 123, - }, + &SerializeWithStruct { a: &a, b: 123 }, &[ - Token::StructStart("SerializeWithStruct", 2), + Token::Struct("SerializeWithStruct", 2), - Token::StructSep, Token::Str("a"), Token::I8(1), - Token::StructSep, Token::Str("b"), Token::Bool(true), Token::StructEnd, - ] + ], ); } #[derive(Debug, PartialEq, Serialize)] -enum SerializeWithEnum<'a, B> where B: SerializeWith { +enum SerializeWithEnum<'a, B> +where + B: SerializeWith, +{ Struct { a: &'a i8, #[serde(serialize_with="SerializeWith::serialize_with")] b: B, - } + }, } #[test] fn test_serialize_with_enum() { let a = 1; assert_ser_tokens( - &SerializeWithEnum::Struct { - a: &a, - b: 2, - }, + &SerializeWithEnum::Struct { a: &a, b: 2 }, &[ - Token::EnumMapStart("SerializeWithEnum", "Struct", 2), + Token::StructVariant("SerializeWithEnum", "Struct", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("b"), Token::Bool(false), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_ser_tokens( - &SerializeWithEnum::Struct { - a: &a, - b: 123, - }, + &SerializeWithEnum::Struct { a: &a, b: 123 }, &[ - Token::EnumMapStart("SerializeWithEnum", "Struct", 2), + Token::StructVariant("SerializeWithEnum", "Struct", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("b"), Token::Bool(true), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } #[derive(Debug, PartialEq, Deserialize)] -struct DeserializeWithStruct where B: DeserializeWith { +struct DeserializeWithStruct +where + B: DeserializeWith, +{ a: i8, #[serde(deserialize_with="DeserializeWith::deserialize_with")] b: B, @@ -804,95 +789,78 @@ struct DeserializeWithStruct where B: DeserializeWith { #[test] fn test_deserialize_with_struct() { assert_de_tokens( - &DeserializeWithStruct { - a: 1, - b: 2, - }, + &DeserializeWithStruct { a: 1, b: 2 }, &[ - Token::StructStart("DeserializeWithStruct", 2), + Token::Struct("DeserializeWithStruct", 2), - Token::StructSep, Token::Str("a"), Token::I8(1), - Token::StructSep, Token::Str("b"), Token::Bool(false), Token::StructEnd, - ] + ], ); assert_de_tokens( - &DeserializeWithStruct { - a: 1, - b: 123, - }, + &DeserializeWithStruct { a: 1, b: 123 }, &[ - Token::StructStart("DeserializeWithStruct", 2), + Token::Struct("DeserializeWithStruct", 2), - Token::StructSep, Token::Str("a"), Token::I8(1), - Token::StructSep, Token::Str("b"), Token::Bool(true), Token::StructEnd, - ] + ], ); } #[derive(Debug, PartialEq, Deserialize)] -enum DeserializeWithEnum where B: DeserializeWith { +enum DeserializeWithEnum +where + B: DeserializeWith, +{ Struct { a: i8, #[serde(deserialize_with="DeserializeWith::deserialize_with")] b: B, - } + }, } #[test] fn test_deserialize_with_enum() { assert_de_tokens( - &DeserializeWithEnum::Struct { - a: 1, - b: 2, - }, + &DeserializeWithEnum::Struct { a: 1, b: 2 }, &[ - Token::EnumMapStart("DeserializeWithEnum", "Struct", 2), + Token::StructVariant("DeserializeWithEnum", "Struct", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("b"), Token::Bool(false), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_de_tokens( - &DeserializeWithEnum::Struct { - a: 1, - b: 123, - }, + &DeserializeWithEnum::Struct { a: 1, b: 123 }, &[ - Token::EnumMapStart("DeserializeWithEnum", "Struct", 2), + Token::StructVariant("DeserializeWithEnum", "Struct", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("b"), Token::Bool(true), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -900,9 +868,8 @@ fn test_deserialize_with_enum() { fn test_missing_renamed_field_struct() { assert_de_tokens_error::( &[ - Token::StructStart("Superhero", 2), + Token::Struct("Superhero", 2), - Token::StructSep, Token::Str("a1"), Token::I32(1), @@ -913,9 +880,8 @@ fn test_missing_renamed_field_struct() { assert_de_tokens_error::( &[ - Token::StructStart("SuperheroDe", 2), + Token::Struct("SuperheroDe", 2), - Token::StructSep, Token::Str("a1"), Token::I32(1), @@ -929,22 +895,21 @@ fn test_missing_renamed_field_struct() { fn test_missing_renamed_field_enum() { assert_de_tokens_error::( &[ - Token::EnumMapStart("Superhero", "barry_allan", 1), + Token::StructVariant("Superhero", "barry_allan", 1), - Token::EnumMapEnd, + Token::StructVariantEnd, ], Error::Message("missing field `b`".to_owned()), ); assert_de_tokens_error::>( &[ - Token::EnumMapStart("SuperheroDe", "jason_todd", 2), + Token::StructVariant("SuperheroDe", "jason_todd", 2), - Token::EnumMapSep, Token::Str("a"), Token::I8(0), - Token::EnumMapEnd, + Token::StructVariantEnd, ], Error::Message("missing field `d`".to_owned()), ); @@ -953,26 +918,29 @@ fn test_missing_renamed_field_enum() { #[derive(Debug, PartialEq, Deserialize)] enum InvalidLengthEnum { A(i32, i32, i32), - B(#[serde(skip_deserializing)] i32, i32, i32), + B( + #[serde(skip_deserializing)] + i32, + i32, + i32 + ), } #[test] fn test_invalid_length_enum() { assert_de_tokens_error::( &[ - Token::EnumSeqStart("InvalidLengthEnum", "A", 3), - Token::EnumSeqSep, - Token::I32(1), - Token::EnumSeqEnd, + Token::TupleVariant("InvalidLengthEnum", "A", 3), + Token::I32(1), + Token::TupleVariantEnd, ], Error::Message("invalid length 1, expected tuple of 3 elements".to_owned()), ); assert_de_tokens_error::( &[ - Token::EnumSeqStart("InvalidLengthEnum", "B", 3), - Token::EnumSeqSep, - Token::I32(1), - Token::EnumSeqEnd, + Token::TupleVariant("InvalidLengthEnum", "B", 3), + Token::I32(1), + Token::TupleVariantEnd, ], Error::Message("invalid length 1, expected tuple of 2 elements".to_owned()), ); @@ -985,7 +953,7 @@ struct StructFromEnum(Option); impl Into for StructFromEnum { fn into(self) -> EnumToU32 { match self { - StructFromEnum(v) => v.into() + StructFromEnum(v) => v.into(), } } } @@ -1003,7 +971,7 @@ enum EnumToU32 { Two, Three, Four, - Nothing + Nothing, } impl Into> for EnumToU32 { @@ -1013,7 +981,7 @@ impl Into> for EnumToU32 { EnumToU32::Two => Some(2), EnumToU32::Three => Some(3), EnumToU32::Four => Some(4), - EnumToU32::Nothing => None + EnumToU32::Nothing => None, } } } @@ -1025,35 +993,17 @@ impl From> for EnumToU32 { Some(2) => EnumToU32::Two, Some(3) => EnumToU32::Three, Some(4) => EnumToU32::Four, - _ => EnumToU32::Nothing + _ => EnumToU32::Nothing, } } } #[test] fn test_from_into_traits() { - assert_ser_tokens::(&EnumToU32::One, - &[Token::Option(true), - Token::U32(1) - ] - ); - assert_ser_tokens::(&EnumToU32::Nothing, - &[Token::Option(false)] - ); - assert_de_tokens::(&EnumToU32::Two, - &[Token::Option(true), - Token::U32(2) - ] - ); - assert_ser_tokens::(&StructFromEnum(Some(5)), - &[Token::Option(false)] - ); - assert_ser_tokens::(&StructFromEnum(None), - &[Token::Option(false)] - ); - assert_de_tokens::(&StructFromEnum(Some(2)), - &[Token::Option(true), - Token::U32(2) - ] - ); + assert_ser_tokens::(&EnumToU32::One, &[Token::Some, Token::U32(1)]); + assert_ser_tokens::(&EnumToU32::Nothing, &[Token::None]); + assert_de_tokens::(&EnumToU32::Two, &[Token::Some, Token::U32(2)]); + assert_ser_tokens::(&StructFromEnum(Some(5)), &[Token::None]); + assert_ser_tokens::(&StructFromEnum(None), &[Token::None]); + assert_de_tokens::(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]); } diff --git a/test_suite/tests/test_borrow.rs b/test_suite/tests/test_borrow.rs new file mode 100644 index 00000000..9d0a65fc --- /dev/null +++ b/test_suite/tests/test_borrow.rs @@ -0,0 +1,175 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +extern crate serde; +use serde::{Deserialize, Deserializer}; + +extern crate serde_test; +use serde_test::{Error, Token, assert_de_tokens, assert_de_tokens_error}; + +use std::borrow::Cow; + +#[test] +fn test_borrowed_str() { + assert_de_tokens(&"borrowed", &[Token::BorrowedStr("borrowed")]); +} + +#[test] +fn test_borrowed_str_from_string() { + assert_de_tokens_error::<&str>( + &[Token::String("borrowed")], + Error::Message("invalid type: string \"borrowed\", expected a borrowed string".to_owned(),), + ); +} + +#[test] +fn test_borrowed_str_from_str() { + assert_de_tokens_error::<&str>( + &[Token::Str("borrowed")], + Error::Message("invalid type: string \"borrowed\", expected a borrowed string".to_owned(),), + ); +} + +#[test] +fn test_string_from_borrowed_str() { + assert_de_tokens(&"owned".to_owned(), &[Token::BorrowedStr("owned")]); +} + +#[test] +fn test_borrowed_bytes() { + assert_de_tokens(&&b"borrowed"[..], &[Token::BorrowedBytes(b"borrowed")]); +} + +#[test] +fn test_borrowed_bytes_from_bytebuf() { + assert_de_tokens_error::<&[u8]>( + &[Token::ByteBuf(b"borrowed")], + Error::Message("invalid type: byte array, expected a borrowed byte array".to_owned(),), + ); +} + +#[test] +fn test_borrowed_bytes_from_bytes() { + assert_de_tokens_error::<&[u8]>( + &[Token::Bytes(b"borrowed")], + Error::Message("invalid type: byte array, expected a borrowed byte array".to_owned(),), + ); +} + +#[test] +fn test_tuple() { + assert_de_tokens( + &("str", &b"bytes"[..]), + &[ + Token::Tuple(2), + Token::BorrowedStr("str"), + Token::BorrowedBytes(b"bytes"), + Token::TupleEnd, + ], + ); +} + +#[test] +fn test_struct() { + #[derive(Deserialize, Debug, PartialEq)] + struct Borrowing<'a, 'b> { + bs: &'a str, + bb: &'b [u8], + } + + assert_de_tokens( + &Borrowing { + bs: "str", + bb: b"bytes", + }, + &[ + Token::Struct("Borrowing", 2), + + Token::BorrowedStr("bs"), + Token::BorrowedStr("str"), + + Token::BorrowedStr("bb"), + Token::BorrowedBytes(b"bytes"), + + Token::StructEnd, + ], + ); +} + +#[test] +fn test_cow() { + #[derive(Deserialize)] + struct Cows<'a, 'b> { + copied: Cow<'a, str>, + + #[serde(borrow)] + borrowed: Cow<'b, str>, + } + + let tokens = &[ + Token::Struct("Cows", 2), + + Token::Str("copied"), + Token::BorrowedStr("copied"), + + Token::Str("borrowed"), + Token::BorrowedStr("borrowed"), + + Token::StructEnd, + ]; + + let mut de = serde_test::Deserializer::new(tokens); + let cows = Cows::deserialize(&mut de).unwrap(); + assert_eq!(de.next_token(), None); + + match cows.copied { + Cow::Owned(ref s) if s == "copied" => {} + _ => panic!("expected a copied string"), + } + + match cows.borrowed { + Cow::Borrowed("borrowed") => {} + _ => panic!("expected a borrowed string"), + } +} + +#[test] +fn test_lifetimes() { + #[derive(Deserialize)] + struct Cows<'a, 'b> { + _copied: Cow<'a, str>, + + #[serde(borrow)] + _borrowed: Cow<'b, str>, + } + + // Tests that `'de: 'a` is not required by the Deserialize impl. + fn _cows_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Cows<'a, 'b> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).unwrap() + } + + #[derive(Deserialize)] + struct Wrap<'a, 'b> { + #[serde(borrow = "'b")] + _cows: Cows<'a, 'b>, + } + + // Tests that `'de: 'a` is not required by the Deserialize impl. + fn _wrap_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Wrap<'a, 'b> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).unwrap() + } +} diff --git a/test_suite/tests/test_bytes.rs b/test_suite/tests/test_bytes.rs deleted file mode 100644 index 28e47d1b..00000000 --- a/test_suite/tests/test_bytes.rs +++ /dev/null @@ -1,58 +0,0 @@ -extern crate serde; -use serde::bytes::{ByteBuf, Bytes}; - -extern crate serde_test; -use serde_test::{assert_tokens, assert_ser_tokens, assert_de_tokens, Token}; - -#[test] -fn test_bytes() { - let empty = Bytes::new(&[]); - assert_ser_tokens(&empty, &[Token::Bytes(b"")]); - - let buf = vec![65, 66, 67]; - let bytes = Bytes::new(&buf); - assert_ser_tokens(&bytes, &[Token::Bytes(b"ABC")]); -} - -#[test] -fn test_byte_buf() { - let empty = ByteBuf::new(); - assert_tokens(&empty, &[Token::Bytes(b"")]); - assert_de_tokens(&empty, &[Token::ByteBuf(Vec::new())]); - assert_de_tokens(&empty, &[Token::Str("")]); - assert_de_tokens(&empty, &[Token::String(String::new())]); - assert_de_tokens(&empty, &[ - Token::SeqStart(None), - Token::SeqEnd, - ]); - assert_de_tokens(&empty, &[ - Token::SeqStart(Some(0)), - Token::SeqEnd, - ]); - - let buf = ByteBuf::from(vec![65, 66, 67]); - assert_tokens(&buf, &[Token::Bytes(b"ABC")]); - assert_de_tokens(&buf, &[Token::ByteBuf(vec![65, 66, 67])]); - assert_de_tokens(&buf, &[Token::Str("ABC")]); - assert_de_tokens(&buf, &[Token::String("ABC".to_owned())]); - assert_de_tokens(&buf, &[ - Token::SeqStart(None), - Token::SeqSep, - Token::U8(65), - Token::SeqSep, - Token::U8(66), - Token::SeqSep, - Token::U8(67), - Token::SeqEnd, - ]); - assert_de_tokens(&buf, &[ - Token::SeqStart(Some(3)), - Token::SeqSep, - Token::U8(65), - Token::SeqSep, - Token::U8(66), - Token::SeqSep, - Token::U8(67), - Token::SeqEnd, - ]); -} diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 8d21844c..e76fc6a9 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -1,3 +1,11 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![cfg_attr(feature = "unstable", feature(into_boxed_c_str))] #[macro_use] @@ -20,12 +28,7 @@ extern crate fnv; use self::fnv::FnvHasher; extern crate serde_test; -use self::serde_test::{ - Error, - Token, - assert_de_tokens, - assert_de_tokens_error, -}; +use self::serde_test::{Error, Token, assert_de_tokens, assert_de_tokens_error}; #[macro_use] mod macros; @@ -35,6 +38,9 @@ mod macros; #[derive(Copy, Clone, PartialEq, Debug, Deserialize)] struct UnitStruct; +#[derive(PartialEq, Debug, Deserialize)] +struct NewtypeStruct(i32); + #[derive(PartialEq, Debug, Deserialize)] struct TupleStruct(i32, i32, i32); @@ -137,42 +143,31 @@ macro_rules! declare_error_tests { } } -fn assert_de_tokens_ignore(ignorable_tokens: &[Token<'static>]) { +fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { #[derive(PartialEq, Debug, Deserialize)] struct IgnoreBase { a: i32, } - let expected = IgnoreBase{a: 1}; + let expected = IgnoreBase { a: 1 }; // Embed the tokens to be ignored in the normal token // stream for an IgnoreBase type - let concated_tokens : Vec> = vec![ - Token::MapStart(Some(2)), - Token::MapSep, - Token::Str("a"), - Token::I32(1), + let concated_tokens: Vec = vec![ + Token::Map(Some(2)), + Token::Str("a"), + Token::I32(1), - Token::MapSep, - Token::Str("ignored") - ] - .into_iter() - .chain(ignorable_tokens.to_vec().into_iter()) - .chain(vec![ - Token::MapEnd, - ].into_iter()) - .collect(); + Token::Str("ignored"), + ] + .into_iter() + .chain(ignorable_tokens.to_vec().into_iter()) + .chain(vec![Token::MapEnd].into_iter()) + .collect(); - let mut de = serde_test::Deserializer::new(concated_tokens.into_iter()); + let mut de = serde_test::Deserializer::new(&concated_tokens); let v: Result = Deserialize::deserialize(&mut de); - // We run this test on every token stream for convenience, but - // some token streams don't make sense embedded as a map value, - // so we ignore those. SyntaxError is the real sign of trouble. - if let Err(Error::UnexpectedToken(_)) = v { - return; - } - assert_eq!(v.as_ref(), Ok(&expected)); assert_eq!(de.next_token(), None); } @@ -193,8 +188,6 @@ declare_tests! { 0isize => &[Token::U16(0)], 0isize => &[Token::U32(0)], 0isize => &[Token::U64(0)], - 0isize => &[Token::F32(0.)], - 0isize => &[Token::F64(0.)], } test_ints { 0i8 => &[Token::I8(0)], @@ -215,448 +208,308 @@ declare_tests! { test_char { 'a' => &[Token::Char('a')], 'a' => &[Token::Str("a")], - 'a' => &[Token::String("a".to_owned())], + 'a' => &[Token::String("a")], } test_string { "abc".to_owned() => &[Token::Str("abc")], - "abc".to_owned() => &[Token::String("abc".to_owned())], + "abc".to_owned() => &[Token::String("abc")], "a".to_owned() => &[Token::Char('a')], } test_option { None:: => &[Token::Unit], - None:: => &[Token::Option(false)], - Some(1) => &[Token::I32(1)], + None:: => &[Token::None], Some(1) => &[ - Token::Option(true), + Token::Some, Token::I32(1), ], } test_result { Ok::(0) => &[ - Token::EnumStart("Result"), + Token::Enum("Result"), Token::Str("Ok"), Token::I32(0), ], Err::(1) => &[ - Token::EnumStart("Result"), + Token::Enum("Result"), Token::Str("Err"), Token::I32(1), ], } test_unit { () => &[Token::Unit], - () => &[ - Token::SeqStart(Some(0)), - Token::SeqEnd, - ], - () => &[ - Token::SeqStart(None), - Token::SeqEnd, - ], - () => &[ - Token::TupleStructStart("Anything", 0), - Token::TupleStructEnd, - ], } test_unit_struct { UnitStruct => &[Token::Unit], UnitStruct => &[ Token::UnitStruct("UnitStruct"), ], - UnitStruct => &[ - Token::SeqStart(Some(0)), - Token::SeqEnd, - ], - UnitStruct => &[ - Token::SeqStart(None), - Token::SeqEnd, - ], } - test_unit_string { - String::new() => &[Token::Unit], + test_newtype_struct { + NewtypeStruct(1) => &[ + Token::NewtypeStruct("NewtypeStruct"), + Token::I32(1), + ], } test_tuple_struct { TupleStruct(1, 2, 3) => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, ], TupleStruct(1, 2, 3) => &[ - Token::SeqStart(None), - Token::SeqSep, + Token::Seq(None), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, ], TupleStruct(1, 2, 3) => &[ - Token::TupleStructStart("TupleStruct", 3), - Token::TupleStructSep, + Token::TupleStruct("TupleStruct", 3), Token::I32(1), - - Token::TupleStructSep, Token::I32(2), - - Token::TupleStructSep, Token::I32(3), Token::TupleStructEnd, ], TupleStruct(1, 2, 3) => &[ - Token::TupleStructStart("TupleStruct", 3), - Token::TupleStructSep, + Token::TupleStruct("TupleStruct", 3), Token::I32(1), - - Token::TupleStructSep, Token::I32(2), - - Token::TupleStructSep, Token::I32(3), Token::TupleStructEnd, ], } test_btreeset { BTreeSet::::new() => &[ - Token::Unit, - ], - BTreeSet::::new() => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], btreeset![btreeset![], btreeset![1], btreeset![2, 3]] => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, - Token::SeqStart(Some(0)), + Token::Seq(Some(3)), + Token::Seq(Some(0)), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(2)), - Token::SeqSep, + Token::Seq(Some(2)), Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], BTreeSet::::new() => &[ - Token::UnitStruct("Anything"), - ], - BTreeSet::::new() => &[ - Token::TupleStructStart("Anything", 0), + Token::TupleStruct("Anything", 0), Token::TupleStructEnd, ], } test_hashset { HashSet::::new() => &[ - Token::Unit, - ], - HashSet::::new() => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], hashset![1, 2, 3] => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, ], HashSet::::new() => &[ - Token::UnitStruct("Anything"), - ], - HashSet::::new() => &[ - Token::TupleStructStart("Anything", 0), + Token::TupleStruct("Anything", 0), Token::TupleStructEnd, ], hashset![FnvHasher @ 1, 2, 3] => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, ], } test_vec { Vec::::new() => &[ - Token::Unit, - ], - Vec::::new() => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], vec![vec![], vec![1], vec![2, 3]] => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, - Token::SeqStart(Some(0)), + Token::Seq(Some(3)), + Token::Seq(Some(0)), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(2)), - Token::SeqSep, + Token::Seq(Some(2)), Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], Vec::::new() => &[ - Token::UnitStruct("Anything"), - ], - Vec::::new() => &[ - Token::TupleStructStart("Anything", 0), + Token::TupleStruct("Anything", 0), Token::TupleStructEnd, ], } test_array { [0; 0] => &[ - Token::Unit, - ], - [0; 0] => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], [0; 0] => &[ - Token::SeqArrayStart(0), - Token::SeqEnd, + Token::Tuple(0), + Token::TupleEnd, ], ([0; 0], [1], [2, 3]) => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, - Token::SeqStart(Some(0)), + Token::Seq(Some(3)), + Token::Seq(Some(0)), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(2)), - Token::SeqSep, + Token::Seq(Some(2)), Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], ([0; 0], [1], [2, 3]) => &[ - Token::SeqArrayStart(3), - Token::SeqSep, - Token::SeqArrayStart(0), - Token::SeqEnd, + Token::Tuple(3), + Token::Tuple(0), + Token::TupleEnd, - Token::SeqSep, - Token::SeqArrayStart(1), - Token::SeqSep, + Token::Tuple(1), Token::I32(1), - Token::SeqEnd, + Token::TupleEnd, - Token::SeqSep, - Token::SeqArrayStart(2), - Token::SeqSep, + Token::Tuple(2), Token::I32(2), - - Token::SeqSep, Token::I32(3), - Token::SeqEnd, - Token::SeqEnd, + Token::TupleEnd, + Token::TupleEnd, ], [0; 0] => &[ - Token::UnitStruct("Anything"), - ], - [0; 0] => &[ - Token::TupleStructStart("Anything", 0), + Token::TupleStruct("Anything", 0), Token::TupleStructEnd, ], } test_tuple { (1,) => &[ - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, ], (1, 2, 3) => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, ], (1,) => &[ - Token::TupleStart(1), - Token::TupleSep, + Token::Tuple(1), Token::I32(1), Token::TupleEnd, ], (1, 2, 3) => &[ - Token::TupleStart(3), - Token::TupleSep, + Token::Tuple(3), Token::I32(1), - - Token::TupleSep, Token::I32(2), - - Token::TupleSep, Token::I32(3), Token::TupleEnd, ], } test_btreemap { BTreeMap::::new() => &[ - Token::Unit, - ], - BTreeMap::::new() => &[ - Token::MapStart(Some(0)), + Token::Map(Some(0)), Token::MapEnd, ], btreemap![1 => 2] => &[ - Token::MapStart(Some(1)), - Token::MapSep, + Token::Map(Some(1)), Token::I32(1), Token::I32(2), Token::MapEnd, ], btreemap![1 => 2, 3 => 4] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), Token::I32(2), - Token::MapSep, Token::I32(3), Token::I32(4), Token::MapEnd, ], btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), - Token::MapStart(Some(0)), + Token::Map(Some(0)), Token::MapEnd, - Token::MapSep, Token::I32(2), - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(3), Token::I32(4), - Token::MapSep, Token::I32(5), Token::I32(6), Token::MapEnd, Token::MapEnd, ], BTreeMap::::new() => &[ - Token::UnitStruct("Anything"), - ], - BTreeMap::::new() => &[ - Token::StructStart("Anything", 0), + Token::Struct("Anything", 0), Token::StructEnd, ], } test_hashmap { HashMap::::new() => &[ - Token::Unit, - ], - HashMap::::new() => &[ - Token::MapStart(Some(0)), + Token::Map(Some(0)), Token::MapEnd, ], hashmap![1 => 2] => &[ - Token::MapStart(Some(1)), - Token::MapSep, + Token::Map(Some(1)), Token::I32(1), Token::I32(2), Token::MapEnd, ], hashmap![1 => 2, 3 => 4] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), Token::I32(2), - Token::MapSep, Token::I32(3), Token::I32(4), Token::MapEnd, ], hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), - Token::MapStart(Some(0)), + Token::Map(Some(0)), Token::MapEnd, - Token::MapSep, Token::I32(2), - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(3), Token::I32(4), - Token::MapSep, Token::I32(5), Token::I32(6), Token::MapEnd, Token::MapEnd, ], HashMap::::new() => &[ - Token::UnitStruct("Anything"), - ], - HashMap::::new() => &[ - Token::StructStart("Anything", 0), + Token::Struct("Anything", 0), Token::StructEnd, ], hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), Token::I32(2), - Token::MapSep, Token::I32(3), Token::I32(4), Token::MapEnd, @@ -664,72 +517,57 @@ declare_tests! { } test_struct { Struct { a: 1, b: 2, c: 0 } => &[ - Token::MapStart(Some(3)), - Token::MapSep, + Token::Map(Some(3)), Token::Str("a"), Token::I32(1), - Token::MapSep, Token::Str("b"), Token::I32(2), Token::MapEnd, ], Struct { a: 1, b: 2, c: 0 } => &[ - Token::StructStart("Struct", 3), - Token::StructSep, + Token::Struct("Struct", 3), Token::Str("a"), Token::I32(1), - Token::StructSep, Token::Str("b"), Token::I32(2), Token::StructEnd, ], Struct { a: 1, b: 2, c: 0 } => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(1), - - Token::SeqSep, Token::I32(2), Token::SeqEnd, ], } test_struct_with_skip { Struct { a: 1, b: 2, c: 0 } => &[ - Token::MapStart(Some(3)), - Token::MapSep, + Token::Map(Some(3)), Token::Str("a"), Token::I32(1), - Token::MapSep, Token::Str("b"), Token::I32(2), - Token::MapSep, Token::Str("c"), Token::I32(3), - Token::MapSep, Token::Str("d"), Token::I32(4), Token::MapEnd, ], Struct { a: 1, b: 2, c: 0 } => &[ - Token::StructStart("Struct", 3), - Token::StructSep, + Token::Struct("Struct", 3), Token::Str("a"), Token::I32(1), - Token::StructSep, Token::Str("b"), Token::I32(2), - Token::StructSep, Token::Str("c"), Token::I32(3), - Token::StructSep, Token::Str("d"), Token::I32(4), Token::StructEnd, @@ -737,16 +575,14 @@ declare_tests! { } test_struct_skip_all { StructSkipAll { a: 0 } => &[ - Token::StructStart("StructSkipAll", 0), + Token::Struct("StructSkipAll", 0), Token::StructEnd, ], StructSkipAll { a: 0 } => &[ - Token::StructStart("StructSkipAll", 1), - Token::StructSep, + Token::Struct("StructSkipAll", 1), Token::Str("a"), Token::I32(1), - Token::StructSep, Token::Str("b"), Token::I32(2), Token::StructEnd, @@ -754,79 +590,69 @@ declare_tests! { } test_struct_skip_all_deny_unknown { StructSkipAllDenyUnknown { a: 0 } => &[ - Token::StructStart("StructSkipAllDenyUnknown", 0), + Token::Struct("StructSkipAllDenyUnknown", 0), Token::StructEnd, ], } test_struct_default { StructDefault { a: 50, b: "overwritten".to_string() } => &[ - Token::StructStart("StructDefault", 1), - Token::StructSep, + Token::Struct("StructDefault", 1), Token::Str("a"), Token::I32(50), - Token::StructSep, Token::Str("b"), - Token::String("overwritten".to_string()), + Token::String("overwritten"), Token::StructEnd, ], StructDefault { a: 100, b: "default".to_string() } => &[ - Token::StructStart("StructDefault", 0), + Token::Struct("StructDefault", 0), Token::StructEnd, ], } test_enum_unit { Enum::Unit => &[ - Token::EnumUnit("Enum", "Unit"), + Token::UnitVariant("Enum", "Unit"), ], } test_enum_simple { Enum::Simple(1) => &[ - Token::EnumNewType("Enum", "Simple"), + Token::NewtypeVariant("Enum", "Simple"), Token::I32(1), ], } test_enum_seq { Enum::Seq(1, 2, 3) => &[ - Token::EnumSeqStart("Enum", "Seq", 3), - Token::EnumSeqSep, + Token::TupleVariant("Enum", "Seq", 3), Token::I32(1), - - Token::EnumSeqSep, Token::I32(2), - - Token::EnumSeqSep, Token::I32(3), - Token::EnumSeqEnd, + Token::TupleVariantEnd, ], } test_enum_map { Enum::Map { a: 1, b: 2, c: 3 } => &[ - Token::EnumMapStart("Enum", "Map", 3), - Token::EnumMapSep, + Token::StructVariant("Enum", "Map", 3), Token::Str("a"), Token::I32(1), - Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::EnumMapEnd, + Token::StructVariantEnd, ], } test_enum_unit_usize { Enum::Unit => &[ - Token::EnumStart("Enum"), + Token::Enum("Enum"), Token::U32(0), Token::Unit, ], } test_enum_unit_bytes { Enum::Unit => &[ - Token::EnumStart("Enum"), + Token::Enum("Enum"), Token::Bytes(b"Unit"), Token::Unit, ], @@ -836,56 +662,43 @@ declare_tests! { } test_boxed_slice { Box::new([0, 1, 2]) => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(0), - Token::SeqSep, Token::I32(1), - Token::SeqSep, Token::I32(2), Token::SeqEnd, ], } test_duration { Duration::new(1, 2) => &[ - Token::StructStart("Duration", 2), - Token::StructSep, + Token::Struct("Duration", 2), Token::Str("secs"), Token::U64(1), - Token::StructSep, Token::Str("nanos"), Token::U32(2), Token::StructEnd, ], Duration::new(1, 2) => &[ - Token::SeqStart(Some(2)), - Token::SeqSep, + Token::Seq(Some(2)), Token::I64(1), - - Token::SeqSep, Token::I64(2), Token::SeqEnd, ], } test_range { 1u32..2u32 => &[ - Token::StructStart("Range", 2), - Token::StructSep, + Token::Struct("Range", 2), Token::Str("start"), Token::U32(1), - Token::StructSep, Token::Str("end"), Token::U32(2), Token::StructEnd, ], 1u32..2u32 => &[ - Token::SeqStart(Some(2)), - Token::SeqSep, + Token::Seq(Some(2)), Token::U64(1), - - Token::SeqSep, Token::U64(2), Token::SeqEnd, ], @@ -903,7 +716,7 @@ declare_tests! { } test_path_buf { PathBuf::from("/usr/local/lib") => &[ - Token::String("/usr/local/lib".to_owned()), + Token::String("/usr/local/lib"), ], } test_cstring { @@ -920,17 +733,12 @@ fn test_osstring() { let value = OsString::from_vec(vec![1, 2, 3]); let tokens = [ - Token::EnumStart("OsString"), + Token::Enum("OsString"), Token::Str("Unix"), - Token::SeqStart(Some(2)), - Token::SeqSep, - Token::U8(1), - - Token::SeqSep, - Token::U8(2), - - Token::SeqSep, - Token::U8(3), + Token::Seq(Some(2)), + Token::U8(1), + Token::U8(2), + Token::U8(3), Token::SeqEnd, ]; @@ -945,17 +753,12 @@ fn test_osstring() { let value = OsString::from_wide(&[1, 2, 3]); let tokens = [ - Token::EnumStart("OsString"), + Token::Enum("OsString"), Token::Str("Windows"), - Token::SeqStart(Some(2)), - Token::SeqSep, - Token::U16(1), - - Token::SeqSep, - Token::U16(2), - - Token::SeqSep, - Token::U16(3), + Token::Seq(Some(2)), + Token::U16(1), + Token::U16(2), + Token::U16(3), Token::SeqEnd, ]; @@ -966,8 +769,10 @@ fn test_osstring() { #[cfg(feature = "unstable")] #[test] fn test_cstr() { - assert_de_tokens::>(&CString::new("abc").unwrap().into_boxed_c_str(), - &[Token::Bytes(b"abc")]); + assert_de_tokens::>( + &CString::new("abc").unwrap().into_boxed_c_str(), + &[Token::Bytes(b"abc")], + ); } #[cfg(feature = "unstable")] @@ -983,10 +788,8 @@ fn test_net_ipaddr() { #[test] fn test_cstr_internal_null() { assert_de_tokens_error::>( - &[ - Token::Bytes(b"a\0c"), - ], - Error::Message("nul byte found in provided data at position: 1".into()) + &[Token::Bytes(b"a\0c")], + Error::Message("nul byte found in provided data at position: 1".into()), ); } @@ -994,96 +797,86 @@ fn test_cstr_internal_null() { #[test] fn test_cstr_internal_null_end() { assert_de_tokens_error::>( - &[ - Token::Bytes(b"ac\0"), - ], - Error::Message("nul byte found in provided data at position: 2".into()) + &[Token::Bytes(b"ac\0")], + Error::Message("nul byte found in provided data at position: 2".into()), ); } declare_error_tests! { test_unknown_field { &[ - Token::StructStart("StructDenyUnknown", 2), - Token::StructSep, + Token::Struct("StructDenyUnknown", 2), Token::Str("a"), Token::I32(0), - Token::StructSep, Token::Str("d"), ], Error::Message("unknown field `d`, expected `a`".to_owned()), } test_skipped_field_is_unknown { &[ - Token::StructStart("StructDenyUnknown", 2), - Token::StructSep, + Token::Struct("StructDenyUnknown", 2), Token::Str("b"), ], Error::Message("unknown field `b`, expected `a`".to_owned()), } test_skip_all_deny_unknown { &[ - Token::StructStart("StructSkipAllDenyUnknown", 1), - Token::StructSep, + Token::Struct("StructSkipAllDenyUnknown", 1), Token::Str("a"), ], Error::Message("unknown field `a`, there are no fields".to_owned()), } test_unknown_variant { &[ - Token::EnumUnit("Enum", "Foo"), + Token::UnitVariant("Enum", "Foo"), ], Error::Message("unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`".to_owned()), } test_enum_skipped_variant { &[ - Token::EnumUnit("Enum", "Skipped"), + Token::UnitVariant("Enum", "Skipped"), ], Error::Message("unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`".to_owned()), } test_enum_skip_all { &[ - Token::EnumUnit("EnumSkipAll", "Skipped"), + Token::UnitVariant("EnumSkipAll", "Skipped"), ], Error::Message("unknown variant `Skipped`, there are no variants".to_owned()), } test_struct_seq_too_long { &[ - Token::SeqStart(Some(4)), - Token::SeqSep, Token::I32(1), - Token::SeqSep, Token::I32(2), - Token::SeqSep, Token::I32(3), + Token::Seq(Some(4)), + Token::I32(1), + Token::I32(2), + Token::I32(3), ], - Error::UnexpectedToken(Token::SeqSep), + Error::UnexpectedToken(Token::I32(3)), } test_duplicate_field_struct { &[ - Token::MapStart(Some(3)), - Token::MapSep, + Token::Map(Some(3)), Token::Str("a"), Token::I32(1), - Token::MapSep, Token::Str("a"), ], Error::Message("duplicate field `a`".to_owned()), } test_duplicate_field_enum { &[ - Token::EnumMapStart("Enum", "Map", 3), - Token::EnumMapSep, + Token::StructVariant("Enum", "Map", 3), Token::Str("a"), Token::I32(1), - Token::EnumMapSep, Token::Str("a"), ], Error::Message("duplicate field `a`".to_owned()), } test_enum_out_of_range { &[ - Token::EnumStart("Enum"), + Token::Enum("Enum"), Token::U32(4), Token::Unit, ], @@ -1091,8 +884,7 @@ declare_error_tests! { } test_short_tuple<(u8, u8, u8)> { &[ - Token::TupleStart(1), - Token::TupleSep, + Token::Tuple(1), Token::U8(1), Token::TupleEnd, ], @@ -1100,8 +892,7 @@ declare_error_tests! { } test_short_array<[u8; 3]> { &[ - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::U8(1), Token::SeqEnd, ], @@ -1119,4 +910,128 @@ declare_error_tests! { ], Error::Message("nul byte found in provided data at position: 2".into()), } + test_unit_from_empty_seq<()> { + &[ + Token::Seq(Some(0)), + Token::SeqEnd, + ], + Error::Message("invalid type: sequence, expected unit".into()), + } + test_unit_from_empty_seq_without_len<()> { + &[ + Token::Seq(None), + Token::SeqEnd, + ], + Error::Message("invalid type: sequence, expected unit".into()), + } + test_unit_from_tuple_struct<()> { + &[ + Token::TupleStruct("Anything", 0), + Token::TupleStructEnd, + ], + Error::Message("invalid type: sequence, expected unit".into()), + } + test_string_from_unit { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected a string".into()), + } + test_btreeset_from_unit> { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected a sequence".into()), + } + test_btreeset_from_unit_struct> { + &[ + Token::UnitStruct("Anything"), + ], + Error::Message("invalid type: unit value, expected a sequence".into()), + } + test_hashset_from_unit> { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected a sequence".into()), + } + test_hashset_from_unit_struct> { + &[ + Token::UnitStruct("Anything"), + ], + Error::Message("invalid type: unit value, expected a sequence".into()), + } + test_vec_from_unit> { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected a sequence".into()), + } + test_vec_from_unit_struct> { + &[ + Token::UnitStruct("Anything"), + ], + Error::Message("invalid type: unit value, expected a sequence".into()), + } + test_zero_array_from_unit<[isize; 0]> { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected an empty array".into()), + } + test_zero_array_from_unit_struct<[isize; 0]> { + &[ + Token::UnitStruct("Anything"), + ], + Error::Message("invalid type: unit value, expected an empty array".into()), + } + test_btreemap_from_unit> { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected a map".into()), + } + test_btreemap_from_unit_struct> { + &[ + Token::UnitStruct("Anything"), + ], + Error::Message("invalid type: unit value, expected a map".into()), + } + test_hashmap_from_unit> { + &[ + Token::Unit, + ], + Error::Message("invalid type: unit value, expected a map".into()), + } + test_hashmap_from_unit_struct> { + &[ + Token::UnitStruct("Anything"), + ], + Error::Message("invalid type: unit value, expected a map".into()), + } + test_bool_from_string { + &[ + Token::Str("false"), + ], + Error::Message("invalid type: string \"false\", expected a boolean".into()), + } + test_number_from_string { + &[ + Token::Str("1"), + ], + Error::Message("invalid type: string \"1\", expected isize".into()), + } + test_integer_from_float { + &[ + Token::F32(0.0), + ], + Error::Message("invalid type: floating point `0`, expected isize".into()), + } + test_unit_struct_from_seq { + &[ + Token::Seq(Some(0)), + Token::SeqEnd, + ], + Error::Message("invalid type: sequence, expected unit struct UnitStruct".into()), + } } diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 8cdb254e..2f3d6299 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -1,15 +1,27 @@ +// Copyright 2017 Serde Developer +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + // These just test that serde_codegen is able to produce code that compiles // successfully when there are a variety of generics and non-(de)serializable // types involved. #![cfg_attr(feature = "unstable", feature(non_ascii_idents))] +// Clippy false positive +// https://github.com/Manishearth/rust-clippy/issues/292 +#![cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] + #[macro_use] extern crate serde_derive; extern crate serde; use self::serde::ser::{Serialize, Serializer}; -use self::serde::de::{Deserialize, Deserializer}; +use self::serde::de::{DeserializeOwned, Deserializer}; use std::borrow::Cow; use std::marker::PhantomData; @@ -64,15 +76,6 @@ fn test_gen() { } assert::>(); - #[derive(Serialize, Deserialize)] - struct Bounds { - t: T, - option: Option, - boxed: Box, - option_boxed: Option>, - } - assert::>(); - #[derive(Serialize, Deserialize)] struct NoBounds { t: T, @@ -87,20 +90,28 @@ fn test_gen() { Unit, Newtype( #[serde(serialize_with="ser_x", deserialize_with="de_x")] - X), + X + ), Tuple( T, #[serde(serialize_with="ser_x", deserialize_with="de_x")] - X), + X + ), Struct { t: T, #[serde(serialize_with="ser_x", deserialize_with="de_x")] - x: X }, + x: X, + }, } assert::>(); #[derive(Serialize)] - struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a { + struct MultipleRef<'a, 'b, 'c, T> + where + T: 'c, + 'c: 'b, + 'b: 'a, + { t: T, rrrt: &'a &'b &'c T, } @@ -117,7 +128,7 @@ fn test_gen() { struct Tuple( T, #[serde(serialize_with="ser_x", deserialize_with="de_x")] - X, + X ); assert::>(); @@ -127,9 +138,7 @@ fn test_gen() { left: Box>, right: Box>, }, - Leaf { - data: D, - }, + Leaf { data: D }, } assert::>(); @@ -206,7 +215,7 @@ fn test_gen() { assert::(); #[derive(Serialize, Deserialize)] - #[serde(bound(deserialize = "T::Owned: Deserialize"))] + #[serde(bound(deserialize = "T::Owned: DeserializeOwned"))] struct CowT<'a, T: ?Sized + 'a + ToOwned>(Cow<'a, T>); assert::>(); @@ -223,7 +232,7 @@ fn test_gen() { #[cfg(feature = "unstable")] #[derive(Serialize, Deserialize)] struct NonAsciiIdents { - σ: f64 + σ: f64, } #[derive(Serialize, Deserialize)] @@ -256,11 +265,17 @@ fn test_gen() { struct EmptyTupleDenyUnknown(); #[derive(Serialize, Deserialize)] - struct TupleSkipAll(#[serde(skip_deserializing)] u8); + struct TupleSkipAll( + #[serde(skip_deserializing)] + u8 + ); #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8); + struct TupleSkipAllDenyUnknown( + #[serde(skip_deserializing)] + u8 + ); #[derive(Serialize, Deserialize)] enum EmptyEnum {} @@ -285,7 +300,10 @@ fn test_gen() { #[serde(skip_deserializing)] f: u8, }, - TupleSkip(#[serde(skip_deserializing)] u8), + TupleSkip( + #[serde(skip_deserializing)] + u8 + ), } #[cfg(feature = "unstable")] @@ -298,17 +316,25 @@ fn test_gen() { #[serde(skip_deserializing)] f: u8, }, - TupleSkip(#[serde(skip_deserializing)] u8), + TupleSkip( + #[serde(skip_deserializing)] + u8 + ), } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] struct UnitDenyUnknown; + + #[derive(Serialize, Deserialize)] + struct EmptyArray { + empty: [X; 0], + } } ////////////////////////////////////////////////////////////////////////// -fn assert() {} +fn assert() {} fn assert_ser() {} trait SerializeWith { @@ -316,7 +342,7 @@ trait SerializeWith { } trait DeserializeWith: Sized { - fn deserialize_with(_: D) -> StdResult; + fn deserialize_with<'de, D: Deserializer<'de>>(_: D) -> StdResult; } // Implements neither Serialize nor Deserialize @@ -326,7 +352,7 @@ pub fn ser_x(_: &X, _: S) -> StdResult { unimplemented!() } -pub fn de_x(_: D) -> StdResult { +pub fn de_x<'de, D: Deserializer<'de>>(_: D) -> StdResult { unimplemented!() } @@ -341,7 +367,7 @@ impl SerializeWith for X { } impl DeserializeWith for X { - fn deserialize_with(_: D) -> StdResult { + fn deserialize_with<'de, D: Deserializer<'de>>(_: D) -> StdResult { unimplemented!() } } diff --git a/test_suite/tests/test_identifier.rs b/test_suite/tests/test_identifier.rs new file mode 100644 index 00000000..76f1cffa --- /dev/null +++ b/test_suite/tests/test_identifier.rs @@ -0,0 +1,82 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +extern crate serde; + +extern crate serde_test; +use serde_test::{Token, assert_de_tokens}; + +#[test] +fn test_variant_identifier() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(variant_identifier)] + enum V { + Aaa, + Bbb, + } + + assert_de_tokens(&V::Aaa, &[Token::U32(0)]); + assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]); + assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]); +} + +#[test] +fn test_field_identifier() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + } + + assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]); + assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]); +} + +#[test] +fn test_unit_fallthrough() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + #[serde(other)] + Other, + } + + assert_de_tokens(&F::Other, &[Token::Str("x")]); +} + +#[test] +fn test_newtype_fallthrough() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + Other(String), + } + + assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); +} + +#[test] +fn test_newtype_fallthrough_generic() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + Other(T), + } + + assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); +} diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 43fe0980..2f35fcf4 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -1,15 +1,17 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; extern crate serde_test; -use self::serde_test::{ - Error, - Token, - assert_tokens, - assert_ser_tokens, - assert_de_tokens, - assert_de_tokens_error, -}; +use self::serde_test::{Error, Token, assert_tokens, assert_ser_tokens, assert_de_tokens, + assert_de_tokens_error}; use std::collections::BTreeMap; use std::marker::PhantomData; @@ -45,67 +47,30 @@ struct DeNamedMap { } #[derive(Debug, PartialEq, Serialize)] -enum SerEnum<'a, B: 'a, C: 'a, D> where D: 'a { +enum SerEnum<'a, B: 'a, C: 'a, D> +where + D: 'a, +{ Unit, - Seq( - i8, - B, - &'a C, - &'a mut D, - ), - Map { - a: i8, - b: B, - c: &'a C, - d: &'a mut D, - }, + Seq(i8, B, &'a C, &'a mut D), + Map { a: i8, b: B, c: &'a C, d: &'a mut D }, // Make sure we can support more than one variant. _Unit2, - _Seq2( - i8, - B, - &'a C, - &'a mut D, - ), - _Map2 { - a: i8, - b: B, - c: &'a C, - d: &'a mut D, - }, + _Seq2(i8, B, &'a C, &'a mut D), + _Map2 { a: i8, b: B, c: &'a C, d: &'a mut D }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum DeEnum { Unit, - Seq( - i8, - B, - C, - D, - ), - Map { - a: i8, - b: B, - c: C, - d: D, - }, + Seq(i8, B, C, D), + Map { a: i8, b: B, c: C, d: D }, // Make sure we can support more than one variant. _Unit2, - _Seq2( - i8, - B, - C, - D, - ), - _Map2 { - a: i8, - b: B, - c: C, - d: D, - }, + _Seq2(i8, B, C, D), + _Map2 { a: i8, b: B, c: C, d: D }, } #[derive(Serialize)] @@ -144,16 +109,13 @@ impl AssociatedType for i32 { } #[derive(Debug, PartialEq, Serialize, Deserialize)] -struct DefaultTyParam = i32> { - phantom: PhantomData +struct DefaultTyParam = i32> { + phantom: PhantomData, } #[test] fn test_named_unit() { - assert_tokens( - &NamedUnit, - &[Token::UnitStruct("NamedUnit")] - ); + assert_tokens(&NamedUnit, &[Token::UnitStruct("NamedUnit")]); } #[test] @@ -164,16 +126,10 @@ fn test_ser_named_tuple() { assert_ser_tokens( &SerNamedTuple(&a, &mut b, c), &[ - Token::TupleStructStart("SerNamedTuple", 3), - Token::TupleStructSep, + Token::TupleStruct("SerNamedTuple", 3), Token::I32(5), - - Token::TupleStructSep, Token::I32(6), - - Token::TupleStructSep, Token::I32(7), - Token::TupleStructEnd, ], ); @@ -184,35 +140,23 @@ fn test_de_named_tuple() { assert_de_tokens( &DeNamedTuple(5, 6, 7), &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(5), - - Token::SeqSep, Token::I32(6), - - Token::SeqSep, Token::I32(7), - Token::SeqEnd, - ] + ], ); assert_de_tokens( &DeNamedTuple(5, 6, 7), &[ - Token::TupleStructStart("DeNamedTuple", 3), - Token::TupleStructSep, + Token::TupleStruct("DeNamedTuple", 3), Token::I32(5), - - Token::TupleStructSep, Token::I32(6), - - Token::TupleStructSep, Token::I32(7), - Token::TupleStructEnd, - ] + ], ); } @@ -224,55 +168,45 @@ fn test_ser_named_map() { assert_ser_tokens( &SerNamedMap { - a: &a, - b: &mut b, - c: c, - }, + a: &a, + b: &mut b, + c: c, + }, &[ - Token::StructStart("SerNamedMap", 3), + Token::Struct("SerNamedMap", 3), - Token::StructSep, Token::Str("a"), Token::I32(5), - Token::StructSep, Token::Str("b"), Token::I32(6), - Token::StructSep, Token::Str("c"), Token::I32(7), Token::StructEnd, - ] + ], ); } #[test] fn test_de_named_map() { assert_de_tokens( - &DeNamedMap { - a: 5, - b: 6, - c: 7, - }, + &DeNamedMap { a: 5, b: 6, c: 7 }, &[ - Token::StructStart("DeNamedMap", 3), + Token::Struct("DeNamedMap", 3), - Token::StructSep, Token::Str("a"), Token::I32(5), - Token::StructSep, Token::Str("b"), Token::I32(6), - Token::StructSep, Token::Str("c"), Token::I32(7), Token::StructEnd, - ] + ], ); } @@ -280,9 +214,7 @@ fn test_de_named_map() { fn test_ser_enum_unit() { assert_ser_tokens( &SerEnum::Unit::, - &[ - Token::EnumUnit("SerEnum", "Unit"), - ] + &[Token::UnitVariant("SerEnum", "Unit")], ); } @@ -294,28 +226,14 @@ fn test_ser_enum_seq() { let mut d = 4; assert_ser_tokens( - &SerEnum::Seq( - a, - b, - &c, - &mut d, - ), + &SerEnum::Seq(a, b, &c, &mut d), &[ - Token::EnumSeqStart("SerEnum", "Seq", 4), - - Token::EnumSeqSep, + Token::TupleVariant("SerEnum", "Seq", 4), Token::I8(1), - - Token::EnumSeqSep, Token::I32(2), - - Token::EnumSeqSep, Token::I32(3), - - Token::EnumSeqSep, Token::I32(4), - - Token::EnumSeqEnd, + Token::TupleVariantEnd, ], ); } @@ -329,31 +247,27 @@ fn test_ser_enum_map() { assert_ser_tokens( &SerEnum::Map { - a: a, - b: b, - c: &c, - d: &mut d, - }, + a: a, + b: b, + c: &c, + d: &mut d, + }, &[ - Token::EnumMapStart("SerEnum", "Map", 4), + Token::StructVariant("SerEnum", "Map", 4), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::EnumMapSep, Token::Str("d"), Token::I32(4), - Token::EnumMapEnd, + Token::StructVariantEnd, ], ); } @@ -362,9 +276,7 @@ fn test_ser_enum_map() { fn test_de_enum_unit() { assert_tokens( &DeEnum::Unit::, - &[ - Token::EnumUnit("DeEnum", "Unit"), - ], + &[Token::UnitVariant("DeEnum", "Unit")], ); } @@ -376,28 +288,14 @@ fn test_de_enum_seq() { let d = 4; assert_tokens( - &DeEnum::Seq( - a, - b, - c, - d, - ), + &DeEnum::Seq(a, b, c, d), &[ - Token::EnumSeqStart("DeEnum", "Seq", 4), - - Token::EnumSeqSep, + Token::TupleVariant("DeEnum", "Seq", 4), Token::I8(1), - - Token::EnumSeqSep, Token::I32(2), - - Token::EnumSeqSep, Token::I32(3), - - Token::EnumSeqSep, Token::I32(4), - - Token::EnumSeqEnd, + Token::TupleVariantEnd, ], ); } @@ -411,31 +309,27 @@ fn test_de_enum_map() { assert_tokens( &DeEnum::Map { - a: a, - b: b, - c: c, - d: d, - }, + a: a, + b: b, + c: c, + d: d, + }, &[ - Token::EnumMapStart("DeEnum", "Map", 4), + Token::StructVariant("DeEnum", "Map", 4), - Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::EnumMapSep, Token::Str("d"), Token::I32(4), - Token::EnumMapEnd, + Token::StructVariantEnd, ], ); } @@ -447,43 +341,41 @@ fn test_lifetimes() { assert_ser_tokens( &Lifetimes::LifetimeSeq(&value), &[ - Token::EnumNewType("Lifetimes", "LifetimeSeq"), + Token::NewtypeVariant("Lifetimes", "LifetimeSeq"), Token::I32(5), - ] + ], ); assert_ser_tokens( &Lifetimes::NoLifetimeSeq(5), &[ - Token::EnumNewType("Lifetimes", "NoLifetimeSeq"), + Token::NewtypeVariant("Lifetimes", "NoLifetimeSeq"), Token::I32(5), - ] + ], ); assert_ser_tokens( &Lifetimes::LifetimeMap { a: &value }, &[ - Token::EnumMapStart("Lifetimes", "LifetimeMap", 1), + Token::StructVariant("Lifetimes", "LifetimeMap", 1), - Token::EnumMapSep, Token::Str("a"), Token::I32(5), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_ser_tokens( &Lifetimes::NoLifetimeMap { a: 5 }, &[ - Token::EnumMapStart("Lifetimes", "NoLifetimeMap", 1), + Token::StructVariant("Lifetimes", "NoLifetimeMap", 1), - Token::EnumMapSep, Token::Str("a"), Token::I32(5), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -492,14 +384,13 @@ fn test_generic_struct() { assert_tokens( &GenericStruct { x: 5u32 }, &[ - Token::StructStart("GenericStruct", 1), + Token::Struct("GenericStruct", 1), - Token::StructSep, Token::Str("x"), Token::U32(5), Token::StructEnd, - ] + ], ); } @@ -507,10 +398,7 @@ fn test_generic_struct() { fn test_generic_newtype_struct() { assert_tokens( &GenericNewTypeStruct(5u32), - &[ - Token::StructNewType("GenericNewTypeStruct"), - Token::U32(5), - ] + &[Token::NewtypeStruct("GenericNewTypeStruct"), Token::U32(5)], ); } @@ -519,16 +407,11 @@ fn test_generic_tuple_struct() { assert_tokens( &GenericTupleStruct(5u32, 6u32), &[ - Token::TupleStructStart("GenericTupleStruct", 2), - - Token::TupleStructSep, + Token::TupleStruct("GenericTupleStruct", 2), Token::U32(5), - - Token::TupleStructSep, Token::U32(6), - Token::TupleStructEnd, - ] + ], ); } @@ -536,9 +419,7 @@ fn test_generic_tuple_struct() { fn test_generic_enum_unit() { assert_tokens( &GenericEnum::Unit::, - &[ - Token::EnumUnit("GenericEnum", "Unit"), - ] + &[Token::UnitVariant("GenericEnum", "Unit")], ); } @@ -547,9 +428,9 @@ fn test_generic_enum_newtype() { assert_tokens( &GenericEnum::NewType::(5), &[ - Token::EnumNewType("GenericEnum", "NewType"), + Token::NewtypeVariant("GenericEnum", "NewType"), Token::U32(5), - ] + ], ); } @@ -558,16 +439,11 @@ fn test_generic_enum_seq() { assert_tokens( &GenericEnum::Seq::(5, 6), &[ - Token::EnumSeqStart("GenericEnum", "Seq", 2), - - Token::EnumSeqSep, + Token::TupleVariant("GenericEnum", "Seq", 2), Token::U32(5), - - Token::EnumSeqSep, Token::U32(6), - - Token::EnumSeqEnd, - ] + Token::TupleVariantEnd, + ], ); } @@ -576,18 +452,16 @@ fn test_generic_enum_map() { assert_tokens( &GenericEnum::Map:: { x: 5, y: 6 }, &[ - Token::EnumMapStart("GenericEnum", "Map", 2), + Token::StructVariant("GenericEnum", "Map", 2), - Token::EnumMapSep, Token::Str("x"), Token::U32(5), - Token::EnumMapSep, Token::Str("y"), Token::U32(6), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -596,14 +470,13 @@ fn test_default_ty_param() { assert_tokens( &DefaultTyParam:: { phantom: PhantomData }, &[ - Token::StructStart("DefaultTyParam", 1), + Token::Struct("DefaultTyParam", 1), - Token::StructSep, Token::Str("phantom"), Token::UnitStruct("PhantomData"), Token::StructEnd, - ] + ], ); } @@ -615,20 +488,21 @@ fn test_enum_state_field() { } assert_tokens( - &SomeEnum::Key { key: 'a', state: true }, + &SomeEnum::Key { + key: 'a', + state: true, + }, &[ - Token::EnumMapStart("SomeEnum", "Key", 2), + Token::StructVariant("SomeEnum", "Key", 2), - Token::EnumMapSep, Token::Str("key"), Token::Char('a'), - Token::EnumMapSep, Token::Str("state"), Token::Bool(true), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -637,12 +511,8 @@ fn test_untagged_enum() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum Untagged { - A { - a: u8, - }, - B { - b: u8, - }, + A { a: u8 }, + B { b: u8 }, C, D(u8), E(String), @@ -652,99 +522,56 @@ fn test_untagged_enum() { assert_tokens( &Untagged::A { a: 1 }, &[ - Token::StructStart("Untagged", 1), + Token::Struct("Untagged", 1), - Token::StructSep, Token::Str("a"), Token::U8(1), Token::StructEnd, - ] + ], ); assert_tokens( &Untagged::B { b: 2 }, &[ - Token::StructStart("Untagged", 1), + Token::Struct("Untagged", 1), - Token::StructSep, Token::Str("b"), Token::U8(2), Token::StructEnd, - ] + ], ); - assert_tokens( - &Untagged::C, - &[ - Token::Unit, - ] - ); + assert_tokens(&Untagged::C, &[Token::Unit]); - assert_tokens( - &Untagged::D(4), - &[ - Token::U8(4), - ] - ); - assert_tokens( - &Untagged::E("e".to_owned()), - &[ - Token::Str("e"), - ] - ); + assert_tokens(&Untagged::D(4), &[Token::U8(4)]); + assert_tokens(&Untagged::E("e".to_owned()), &[Token::Str("e")]); assert_tokens( &Untagged::F(1, 2), + &[Token::Tuple(2), Token::U8(1), Token::U8(2), Token::TupleEnd], + ); + + assert_de_tokens_error::( + &[Token::None], + Error::Message("data did not match any variant of untagged enum Untagged".to_owned(),), + ); + + assert_de_tokens_error::( + &[Token::Tuple(1), Token::U8(1), Token::TupleEnd], + Error::Message("data did not match any variant of untagged enum Untagged".to_owned(),), + ); + + assert_de_tokens_error::( &[ - Token::TupleStart(2), - - Token::TupleSep, + Token::Tuple(3), Token::U8(1), - - Token::TupleSep, Token::U8(2), - - Token::TupleEnd, - ] - ); - - assert_de_tokens_error::( - &[ - Token::Option(false), - ], - Error::Message("data did not match any variant of untagged enum Untagged".to_owned()), - ); - - assert_de_tokens_error::( - &[ - Token::TupleStart(1), - - Token::TupleSep, - Token::U8(1), - - Token::TupleEnd, - ], - Error::Message("data did not match any variant of untagged enum Untagged".to_owned()), - ); - - assert_de_tokens_error::( - &[ - Token::TupleStart(3), - - Token::TupleSep, - Token::U8(1), - - Token::TupleSep, - Token::U8(2), - - Token::TupleSep, Token::U8(3), - Token::TupleEnd, ], - Error::Message("data did not match any variant of untagged enum Untagged".to_owned()), + Error::Message("data did not match any variant of untagged enum Untagged".to_owned(),), ); } @@ -761,12 +588,8 @@ fn test_internally_tagged_enum() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] enum InternallyTagged { - A { - a: u8, - }, - B { - b: u8, - }, + A { a: u8 }, + B { b: u8 }, C, D(BTreeMap), E(Newtype), @@ -776,112 +599,99 @@ fn test_internally_tagged_enum() { assert_tokens( &InternallyTagged::A { a: 1 }, &[ - Token::StructStart("InternallyTagged", 2), + Token::Struct("InternallyTagged", 2), - Token::StructSep, Token::Str("type"), Token::Str("A"), - Token::StructSep, Token::Str("a"), Token::U8(1), Token::StructEnd, - ] + ], ); assert_tokens( &InternallyTagged::B { b: 2 }, &[ - Token::StructStart("InternallyTagged", 2), + Token::Struct("InternallyTagged", 2), - Token::StructSep, Token::Str("type"), Token::Str("B"), - Token::StructSep, Token::Str("b"), Token::U8(2), Token::StructEnd, - ] + ], ); assert_tokens( &InternallyTagged::C, &[ - Token::StructStart("InternallyTagged", 1), + Token::Struct("InternallyTagged", 1), - Token::StructSep, Token::Str("type"), Token::Str("C"), Token::StructEnd, - ] + ], ); assert_tokens( &InternallyTagged::D(BTreeMap::new()), &[ - Token::MapStart(Some(1)), + Token::Map(Some(1)), - Token::MapSep, Token::Str("type"), Token::Str("D"), Token::MapEnd, - ] + ], ); assert_tokens( &InternallyTagged::E(Newtype(BTreeMap::new())), &[ - Token::MapStart(Some(1)), + Token::Map(Some(1)), - Token::MapSep, Token::Str("type"), Token::Str("E"), Token::MapEnd, - ] + ], ); assert_tokens( &InternallyTagged::F(Struct { f: 6 }), &[ - Token::StructStart("Struct", 2), + Token::Struct("Struct", 2), - Token::StructSep, Token::Str("type"), Token::Str("F"), - Token::StructSep, Token::Str("f"), Token::U8(6), Token::StructEnd, - ] + ], ); assert_de_tokens_error::( - &[ - Token::MapStart(Some(0)), - Token::MapEnd, - ], + &[Token::Map(Some(0)), Token::MapEnd], Error::Message("missing field `type`".to_owned()), ); assert_de_tokens_error::( &[ - Token::MapStart(Some(1)), + Token::Map(Some(1)), - Token::MapSep, Token::Str("type"), Token::Str("Z"), Token::MapEnd, ], - Error::Message("unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`, `F`".to_owned()), + Error::Message("unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`, `F`".to_owned(),), ); } @@ -900,176 +710,153 @@ fn test_adjacently_tagged_enum() { assert_tokens( &AdjacentlyTagged::Unit::, &[ - Token::StructStart("AdjacentlyTagged", 1), + Token::Struct("AdjacentlyTagged", 1), - Token::StructSep, Token::Str("t"), Token::Str("Unit"), Token::StructEnd, - ] + ], ); // unit with tag first assert_de_tokens( &AdjacentlyTagged::Unit::, &[ - Token::StructStart("AdjacentlyTagged", 1), + Token::Struct("AdjacentlyTagged", 1), - Token::StructSep, Token::Str("t"), Token::Str("Unit"), - Token::StructSep, Token::Str("c"), Token::Unit, Token::StructEnd, - ] + ], ); // unit with content first assert_de_tokens( &AdjacentlyTagged::Unit::, &[ - Token::StructStart("AdjacentlyTagged", 1), + Token::Struct("AdjacentlyTagged", 1), - Token::StructSep, Token::Str("c"), Token::Unit, - Token::StructSep, Token::Str("t"), Token::Str("Unit"), Token::StructEnd, - ] + ], ); // newtype with tag first assert_tokens( &AdjacentlyTagged::Newtype::(1), &[ - Token::StructStart("AdjacentlyTagged", 2), + Token::Struct("AdjacentlyTagged", 2), - Token::StructSep, Token::Str("t"), Token::Str("Newtype"), - Token::StructSep, Token::Str("c"), Token::U8(1), Token::StructEnd, - ] + ], ); // newtype with content first assert_de_tokens( &AdjacentlyTagged::Newtype::(1), &[ - Token::StructStart("AdjacentlyTagged", 2), + Token::Struct("AdjacentlyTagged", 2), - Token::StructSep, Token::Str("c"), Token::U8(1), - Token::StructSep, Token::Str("t"), Token::Str("Newtype"), Token::StructEnd, - ] + ], ); // tuple with tag first assert_tokens( &AdjacentlyTagged::Tuple::(1, 1), &[ - Token::StructStart("AdjacentlyTagged", 2), + Token::Struct("AdjacentlyTagged", 2), - Token::StructSep, Token::Str("t"), Token::Str("Tuple"), - Token::StructSep, Token::Str("c"), - Token::TupleStart(2), - Token::TupleSep, + Token::Tuple(2), Token::U8(1), - Token::TupleSep, Token::U8(1), Token::TupleEnd, Token::StructEnd, - ] + ], ); // tuple with content first assert_de_tokens( &AdjacentlyTagged::Tuple::(1, 1), &[ - Token::StructStart("AdjacentlyTagged", 2), + Token::Struct("AdjacentlyTagged", 2), - Token::StructSep, Token::Str("c"), - Token::TupleStart(2), - Token::TupleSep, + Token::Tuple(2), Token::U8(1), - Token::TupleSep, Token::U8(1), Token::TupleEnd, - Token::StructSep, Token::Str("t"), Token::Str("Tuple"), Token::StructEnd, - ] + ], ); // struct with tag first assert_tokens( &AdjacentlyTagged::Struct:: { f: 1 }, &[ - Token::StructStart("AdjacentlyTagged", 2), + Token::Struct("AdjacentlyTagged", 2), - Token::StructSep, Token::Str("t"), Token::Str("Struct"), - Token::StructSep, Token::Str("c"), - Token::StructStart("Struct", 1), - Token::StructSep, + Token::Struct("Struct", 1), Token::Str("f"), Token::U8(1), Token::StructEnd, Token::StructEnd, - ] + ], ); // struct with content first assert_de_tokens( &AdjacentlyTagged::Struct:: { f: 1 }, &[ - Token::StructStart("AdjacentlyTagged", 2), + Token::Struct("AdjacentlyTagged", 2), - Token::StructSep, Token::Str("c"), - Token::StructStart("Struct", 1), - Token::StructSep, + Token::Struct("Struct", 1), Token::Str("f"), Token::U8(1), Token::StructEnd, - Token::StructSep, Token::Str("t"), Token::Str("Struct"), Token::StructEnd, - ] + ], ); } @@ -1092,78 +879,67 @@ fn test_enum_in_internally_tagged_enum() { assert_tokens( &Outer::Inner(Inner::Unit), &[ - Token::MapStart(Some(2)), + Token::Map(Some(2)), - Token::MapSep, Token::Str("type"), Token::Str("Inner"), - Token::MapSep, Token::Str("Unit"), Token::Unit, Token::MapEnd, - ] + ], ); assert_tokens( &Outer::Inner(Inner::Newtype(1)), &[ - Token::MapStart(Some(2)), + Token::Map(Some(2)), - Token::MapSep, Token::Str("type"), Token::Str("Inner"), - Token::MapSep, Token::Str("Newtype"), Token::U8(1), Token::MapEnd, - ] + ], ); assert_tokens( &Outer::Inner(Inner::Tuple(1, 1)), &[ - Token::MapStart(Some(2)), + Token::Map(Some(2)), - Token::MapSep, Token::Str("type"), Token::Str("Inner"), - Token::MapSep, Token::Str("Tuple"), - Token::TupleStructStart("Tuple", 2), - Token::TupleStructSep, + Token::TupleStruct("Tuple", 2), Token::U8(1), - Token::TupleStructSep, Token::U8(1), Token::TupleStructEnd, Token::MapEnd, - ] + ], ); assert_tokens( &Outer::Inner(Inner::Struct { f: 1 }), &[ - Token::MapStart(Some(2)), + Token::Map(Some(2)), - Token::MapSep, Token::Str("type"), Token::Str("Inner"), - Token::MapSep, Token::Str("Struct"), - Token::StructStart("Struct", 1), - Token::StructSep, + Token::Struct("Struct", 1), Token::Str("f"), Token::U8(1), Token::StructEnd, Token::MapEnd, - ] + ], ); } @@ -1185,44 +961,34 @@ fn test_enum_in_untagged_enum() { assert_tokens( &Outer::Inner(Inner::Unit), - &[ - Token::EnumUnit("Inner", "Unit"), - ] + &[Token::UnitVariant("Inner", "Unit")], ); assert_tokens( &Outer::Inner(Inner::Newtype(1)), - &[ - Token::EnumNewType("Inner", "Newtype"), - Token::U8(1), - ] + &[Token::NewtypeVariant("Inner", "Newtype"), Token::U8(1)], ); assert_tokens( &Outer::Inner(Inner::Tuple(1, 1)), &[ - Token::EnumSeqStart("Inner", "Tuple", 2), - - Token::EnumSeqSep, + Token::TupleVariant("Inner", "Tuple", 2), Token::U8(1), - Token::EnumSeqSep, Token::U8(1), - - Token::EnumSeqEnd, - ] + Token::TupleVariantEnd, + ], ); assert_tokens( &Outer::Inner(Inner::Struct { f: 1 }), &[ - Token::EnumMapStart("Inner", "Struct", 1), + Token::StructVariant("Inner", "Struct", 1), - Token::EnumMapSep, Token::Str("f"), Token::U8(1), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); } @@ -1256,58 +1022,62 @@ fn test_rename_all() { } assert_tokens( - &E::Serialize { serialize: true, serialize_seq: true }, + &E::Serialize { + serialize: true, + serialize_seq: true, + }, &[ - Token::EnumMapStart("E", "serialize", 2), - Token::EnumMapSep, + Token::StructVariant("E", "serialize", 2), Token::Str("serialize"), Token::Bool(true), - Token::EnumMapSep, Token::Str("serializeSeq"), Token::Bool(true), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_tokens( - &E::SerializeSeq { serialize: true, serialize_seq: true }, + &E::SerializeSeq { + serialize: true, + serialize_seq: true, + }, &[ - Token::EnumMapStart("E", "serialize_seq", 2), - Token::EnumMapSep, + Token::StructVariant("E", "serialize_seq", 2), Token::Str("serialize"), Token::Bool(true), - Token::EnumMapSep, Token::Str("serialize-seq"), Token::Bool(true), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_tokens( - &E::SerializeMap { serialize: true, serialize_seq: true }, + &E::SerializeMap { + serialize: true, + serialize_seq: true, + }, &[ - Token::EnumMapStart("E", "serialize_map", 2), - Token::EnumMapSep, + Token::StructVariant("E", "serialize_map", 2), Token::Str("SERIALIZE"), Token::Bool(true), - Token::EnumMapSep, Token::Str("SERIALIZE_SEQ"), Token::Bool(true), - Token::EnumMapEnd, - ] + Token::StructVariantEnd, + ], ); assert_tokens( - &S { serialize: true, serialize_seq: true }, + &S { + serialize: true, + serialize_seq: true, + }, &[ - Token::StructStart("S", 2), - Token::StructSep, + Token::Struct("S", 2), Token::Str("Serialize"), Token::Bool(true), - Token::StructSep, Token::Str("SerializeSeq"), Token::Bool(true), Token::StructEnd, - ] + ], ); } diff --git a/test_suite/tests/test_remote.rs b/test_suite/tests/test_remote.rs new file mode 100644 index 00000000..30ccbb27 --- /dev/null +++ b/test_suite/tests/test_remote.rs @@ -0,0 +1,208 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate serde_derive; + +extern crate serde; + +mod remote { + pub struct Unit; + + pub struct PrimitivePriv(u8); + + pub struct PrimitivePub(pub u8); + + pub struct NewtypePriv(Unit); + + pub struct NewtypePub(pub Unit); + + pub struct TuplePriv(u8, Unit); + + pub struct TuplePub(pub u8, pub Unit); + + pub struct StructPriv { + a: u8, + b: Unit, + } + + pub struct StructPub { + pub a: u8, + pub b: Unit, + } + + impl PrimitivePriv { + pub fn new(a: u8) -> Self { + PrimitivePriv(a) + } + + pub fn get(&self) -> u8 { + self.0 + } + } + + impl NewtypePriv { + pub fn new(a: Unit) -> Self { + NewtypePriv(a) + } + + pub fn get(&self) -> &Unit { + &self.0 + } + } + + impl TuplePriv { + pub fn new(a: u8, b: Unit) -> Self { + TuplePriv(a, b) + } + + pub fn first(&self) -> u8 { + self.0 + } + + pub fn second(&self) -> &Unit { + &self.1 + } + } + + impl StructPriv { + pub fn new(a: u8, b: Unit) -> Self { + StructPriv { a: a, b: b } + } + + pub fn a(&self) -> u8 { + self.a + } + + pub fn b(&self) -> &Unit { + &self.b + } + } +} + +#[derive(Serialize, Deserialize)] +struct Test { + #[serde(with = "UnitDef")] + unit: remote::Unit, + + #[serde(with = "PrimitivePrivDef")] + primitive_priv: remote::PrimitivePriv, + + #[serde(with = "PrimitivePubDef")] + primitive_pub: remote::PrimitivePub, + + #[serde(with = "NewtypePrivDef")] + newtype_priv: remote::NewtypePriv, + + #[serde(with = "NewtypePubDef")] + newtype_pub: remote::NewtypePub, + + #[serde(with = "TuplePrivDef")] + tuple_priv: remote::TuplePriv, + + #[serde(with = "TuplePubDef")] + tuple_pub: remote::TuplePub, + + #[serde(with = "StructPrivDef")] + struct_priv: remote::StructPriv, + + #[serde(with = "StructPubDef")] + struct_pub: remote::StructPub, +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::Unit")] +struct UnitDef; + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::PrimitivePriv")] +struct PrimitivePrivDef( + #[serde(getter = "remote::PrimitivePriv::get")] + u8 +); + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::PrimitivePub")] +struct PrimitivePubDef(u8); + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::NewtypePriv")] +struct NewtypePrivDef( + #[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] + remote::Unit +); + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::NewtypePub")] +struct NewtypePubDef( + #[serde(with = "UnitDef")] + remote::Unit +); + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::TuplePriv")] +struct TuplePrivDef( + #[serde(getter = "remote::TuplePriv::first")] + u8, + #[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] + remote::Unit +); + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::TuplePub")] +struct TuplePubDef( + u8, + #[serde(with = "UnitDef")] + remote::Unit +); + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::StructPriv")] +struct StructPrivDef { + #[serde(getter = "remote::StructPriv::a")] + a: u8, + + #[serde(getter = "remote::StructPriv::b")] + #[serde(with= "UnitDef")] + b: remote::Unit, +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::StructPub")] +struct StructPubDef { + #[allow(dead_code)] + a: u8, + + #[allow(dead_code)] + #[serde(with= "UnitDef")] + b: remote::Unit, +} + +impl From for remote::PrimitivePriv { + fn from(def: PrimitivePrivDef) -> Self { + remote::PrimitivePriv::new(def.0) + } +} + +impl From for remote::NewtypePriv { + fn from(def: NewtypePrivDef) -> Self { + remote::NewtypePriv::new(def.0) + } +} + +impl From for remote::TuplePriv { + fn from(def: TuplePrivDef) -> Self { + remote::TuplePriv::new(def.0, def.1) + } +} + +impl From for remote::StructPriv { + fn from(def: StructPrivDef) -> Self { + remote::StructPriv::new(def.a, def.b) + } +} diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 7613cb8a..2de5db14 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -1,22 +1,27 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; use std::collections::{BTreeMap, HashMap, HashSet}; use std::net; use std::path::{Path, PathBuf}; -use std::str; use std::time::Duration; use std::ffi::CString; +#[cfg(unix)] +use std::str; + extern crate serde; extern crate serde_test; -use self::serde_test::{ - Error, - Token, - assert_ser_tokens, - assert_ser_tokens_error, -}; +use self::serde_test::{Error, Token, assert_ser_tokens, assert_ser_tokens_error}; extern crate fnv; use self::fnv::FnvHasher; @@ -102,81 +107,64 @@ declare_tests! { "abc".to_owned() => &[Token::Str("abc")], } test_option { - None:: => &[Token::Option(false)], + None:: => &[Token::None], Some(1) => &[ - Token::Option(true), + Token::Some, Token::I32(1), ], } test_result { Ok::(0) => &[ - Token::EnumNewType("Result", "Ok"), + Token::NewtypeVariant("Result", "Ok"), Token::I32(0), ], Err::(1) => &[ - Token::EnumNewType("Result", "Err"), + Token::NewtypeVariant("Result", "Err"), Token::I32(1), ], } test_slice { &[0][..0] => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], &[1, 2, 3][..] => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, + Token::Seq(Some(3)), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, ], } test_array { [0; 0] => &[ - Token::SeqArrayStart(0), - Token::SeqEnd, + Token::Tuple(0), + Token::TupleEnd, ], [1, 2, 3] => &[ - Token::SeqArrayStart(3), - Token::SeqSep, + Token::Tuple(3), Token::I32(1), - - Token::SeqSep, Token::I32(2), - - Token::SeqSep, Token::I32(3), - Token::SeqEnd, + Token::TupleEnd, ], } test_vec { Vec::::new() => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], vec![vec![], vec![1], vec![2, 3]] => &[ - Token::SeqStart(Some(3)), - Token::SeqSep, - Token::SeqStart(Some(0)), + Token::Seq(Some(3)), + Token::Seq(Some(0)), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, - Token::SeqSep, - Token::SeqStart(Some(2)), - Token::SeqSep, + Token::Seq(Some(2)), Token::I32(2), - - Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::SeqEnd, @@ -184,76 +172,61 @@ declare_tests! { } test_hashset { HashSet::::new() => &[ - Token::SeqStart(Some(0)), + Token::Seq(Some(0)), Token::SeqEnd, ], hashset![1] => &[ - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, ], hashset![FnvHasher @ 1] => &[ - Token::SeqStart(Some(1)), - Token::SeqSep, + Token::Seq(Some(1)), Token::I32(1), Token::SeqEnd, ], } test_tuple { (1,) => &[ - Token::TupleStart(1), - Token::TupleSep, + Token::Tuple(1), Token::I32(1), Token::TupleEnd, ], (1, 2, 3) => &[ - Token::TupleStart(3), - Token::TupleSep, + Token::Tuple(3), Token::I32(1), - - Token::TupleSep, Token::I32(2), - - Token::TupleSep, Token::I32(3), Token::TupleEnd, ], } test_btreemap { btreemap![1 => 2] => &[ - Token::MapStart(Some(1)), - Token::MapSep, + Token::Map(Some(1)), Token::I32(1), Token::I32(2), Token::MapEnd, ], btreemap![1 => 2, 3 => 4] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), Token::I32(2), - Token::MapSep, Token::I32(3), Token::I32(4), Token::MapEnd, ], btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => &[ - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(1), - Token::MapStart(Some(0)), + Token::Map(Some(0)), Token::MapEnd, - Token::MapSep, Token::I32(2), - Token::MapStart(Some(2)), - Token::MapSep, + Token::Map(Some(2)), Token::I32(3), Token::I32(4), - Token::MapSep, Token::I32(5), Token::I32(6), Token::MapEnd, @@ -262,19 +235,17 @@ declare_tests! { } test_hashmap { HashMap::::new() => &[ - Token::MapStart(Some(0)), + Token::Map(Some(0)), Token::MapEnd, ], hashmap![1 => 2] => &[ - Token::MapStart(Some(1)), - Token::MapSep, + Token::Map(Some(1)), Token::I32(1), Token::I32(2), Token::MapEnd, ], hashmap![FnvHasher @ 1 => 2] => &[ - Token::MapStart(Some(1)), - Token::MapSep, + Token::Map(Some(1)), Token::I32(1), Token::I32(2), Token::MapEnd, @@ -285,57 +256,44 @@ declare_tests! { } test_tuple_struct { TupleStruct(1, 2, 3) => &[ - Token::TupleStructStart("TupleStruct", 3), - Token::TupleStructSep, + Token::TupleStruct("TupleStruct", 3), Token::I32(1), - - Token::TupleStructSep, Token::I32(2), - - Token::TupleStructSep, Token::I32(3), Token::TupleStructEnd, ], } test_struct { Struct { a: 1, b: 2, c: 3 } => &[ - Token::StructStart("Struct", 3), - Token::StructSep, + Token::Struct("Struct", 3), Token::Str("a"), Token::I32(1), - Token::StructSep, Token::Str("b"), Token::I32(2), - Token::StructSep, Token::Str("c"), Token::I32(3), Token::StructEnd, ], } test_enum { - Enum::Unit => &[Token::EnumUnit("Enum", "Unit")], - Enum::One(42) => &[Token::EnumNewType("Enum", "One"), Token::I32(42)], + Enum::Unit => &[Token::UnitVariant("Enum", "Unit")], + Enum::One(42) => &[Token::NewtypeVariant("Enum", "One"), Token::I32(42)], Enum::Seq(1, 2) => &[ - Token::EnumSeqStart("Enum", "Seq", 2), - Token::EnumSeqSep, + Token::TupleVariant("Enum", "Seq", 2), Token::I32(1), - - Token::EnumSeqSep, Token::I32(2), - Token::EnumSeqEnd, + Token::TupleVariantEnd, ], Enum::Map { a: 1, b: 2 } => &[ - Token::EnumMapStart("Enum", "Map", 2), - Token::EnumMapSep, + Token::StructVariant("Enum", "Map", 2), Token::Str("a"), Token::I32(1), - Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::EnumMapEnd, + Token::StructVariantEnd, ], } test_box { @@ -343,24 +301,19 @@ declare_tests! { } test_boxed_slice { Box::new([0, 1, 2]) => &[ - Token::SeqArrayStart(3), - Token::SeqSep, + Token::Tuple(3), Token::I32(0), - Token::SeqSep, Token::I32(1), - Token::SeqSep, Token::I32(2), - Token::SeqEnd, + Token::TupleEnd, ], } test_duration { Duration::new(1, 2) => &[ - Token::StructStart("Duration", 2), - Token::StructSep, + Token::Struct("Duration", 2), Token::Str("secs"), Token::U64(1), - Token::StructSep, Token::Str("nanos"), Token::U32(2), Token::StructEnd, @@ -368,12 +321,10 @@ declare_tests! { } test_range { 1u32..2u32 => &[ - Token::StructStart("Range", 2), - Token::StructSep, + Token::Struct("Range", 2), Token::Str("start"), Token::U32(1), - Token::StructSep, Token::Str("end"), Token::U32(2), Token::StructEnd, @@ -424,13 +375,12 @@ fn test_net_ipaddr() { #[test] #[cfg(unix)] fn test_cannot_serialize_paths() { - let path = unsafe { - str::from_utf8_unchecked(b"Hello \xF0\x90\x80World") - }; + let path = unsafe { str::from_utf8_unchecked(b"Hello \xF0\x90\x80World") }; assert_ser_tokens_error( &Path::new(path), &[], - Error::Message("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); @@ -438,7 +388,8 @@ fn test_cannot_serialize_paths() { assert_ser_tokens_error( &path_buf, &[], - Error::Message("path contains invalid UTF-8 characters".to_owned())); + Error::Message("path contains invalid UTF-8 characters".to_owned()), + ); } #[test] @@ -446,17 +397,21 @@ fn test_enum_skipped() { assert_ser_tokens_error( &Enum::SkippedUnit, &[], - Error::Message("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::Message("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::Message("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::Message("the enum variant Enum::SkippedMap cannot be serialized".to_owned())); + Error::Message("the enum variant Enum::SkippedMap cannot be serialized".to_owned(),), + ); } diff --git a/test_suite/tests/test_value.rs b/test_suite/tests/test_value.rs index fc444163..42df751c 100644 --- a/test_suite/tests/test_value.rs +++ b/test_suite/tests/test_value.rs @@ -1,9 +1,17 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[macro_use] extern crate serde_derive; extern crate serde; use serde::Deserialize; -use serde::de::value::{self, ValueDeserializer}; +use serde::de::{value, IntoDeserializer}; #[test] fn test_u32_to_enum() { @@ -13,7 +21,7 @@ fn test_u32_to_enum() { B, } - let deserializer = ValueDeserializer::::into_deserializer(1u32); + let deserializer = IntoDeserializer::::into_deserializer(1u32); let e: E = E::deserialize(deserializer).unwrap(); assert_eq!(E::B, e); } diff --git a/travis.sh b/travis.sh index d5f62d28..fa760b57 100755 --- a/travis.sh +++ b/travis.sh @@ -29,10 +29,10 @@ if [ -n "${CLIPPY}" ]; then fi cd "$DIR/serde" - cargo clippy --features unstable-testing -- -Dclippy + cargo clippy --features 'rc unstable' -- -Dclippy cd "$DIR/serde_derive" - cargo clippy --features unstable-testing -- -Dclippy + cargo clippy -- -Dclippy cd "$DIR/test_suite" cargo clippy --features unstable -- -Dclippy @@ -47,7 +47,7 @@ else channel build --no-default-features channel build --no-default-features --features alloc channel build --no-default-features --features collections - channel test --features unstable-testing + channel test --features 'rc unstable' cd "$DIR/test_suite/deps" channel build cd "$DIR/test_suite" @@ -58,19 +58,23 @@ else CHANNEL=beta cargo clean cd "$DIR/serde" - channel build + channel build --features rc cd "$DIR/test_suite" channel test CHANNEL=stable cargo clean cd "$DIR/serde" - channel build + channel build --features rc channel build --no-default-features + cd "$DIR/serde_test" + channel build CHANNEL=1.13.0 cargo clean cd "$DIR/serde" - channel build + channel build --features rc channel build --no-default-features + cd "$DIR/serde_test" + channel build fi