Compare commits

...

26 Commits

Author SHA1 Message Date
David Tolnay d1306a78ec Release 0.9.6 2017-02-03 08:02:47 -08:00
David Tolnay ce230adf12 Merge pull request #739 from serde-rs/tag
Untagged and internally tagged enums
2017-02-03 07:50:26 -08:00
David Tolnay 066c9a15cf Explain status of content module 2017-02-03 07:43:04 -08:00
Oliver Schneider d60fd84b7e Merge pull request #740 from serde-rs/enumset
Remove the EnumSet impls
2017-02-03 13:38:39 +01:00
David Tolnay 02e6c04e9f Check for sequence end 2017-02-02 22:13:32 -08:00
David Tolnay 9f04b9d6e7 Remove the EnumSet impls 2017-02-02 19:13:55 -08:00
David Tolnay d298da0b4f Require std for deserializing untagged enums 2017-02-02 19:09:38 -08:00
David Tolnay ff21d557c7 Untagged and internally tagged enums 2017-02-02 18:48:30 -08:00
Oliver Schneider faaa494579 Merge pull request #738 from serde-rs/absolute
Use absolute paths to Ok, Err, and other types and methods
2017-02-02 08:16:51 +01:00
David Tolnay 661cdf4e00 Inline the trait docs at the top level 2017-02-01 12:58:24 -08:00
David Tolnay a55d812441 Even more absolute paths 2017-02-01 12:12:39 -08:00
David Tolnay b7ca574bb3 Use absolute paths to Ok and Err 2017-02-01 09:42:12 -08:00
David Tolnay d960571439 Release 0.9.5 2017-02-01 01:01:06 -08:00
David Tolnay 1ccc58e2aa Merge pull request #735 from serde-rs/travis
Allow running travis build locally
2017-02-01 00:43:27 -08:00
David Tolnay 34b39083bc No error if clippy install fails 2017-02-01 00:38:02 -08:00
David Tolnay 48f4deac55 No more travis-cargo 2017-01-31 12:18:57 -08:00
David Tolnay 9a0f05d00d Speed up the travis clippy installation 2017-01-31 12:09:44 -08:00
David Tolnay b47e1a6dc3 Allow clippy failure in travis 2017-01-31 12:07:35 -08:00
David Tolnay 39c7797633 Allow running travis build locally 2017-01-31 12:07:31 -08:00
Oliver Schneider 368784949e move to cargo clippy instead of using the clippy plugin (#733)
* move to cargo clippy instead of using the clippy plugin

fixes #729

* non-exectable scripts must be run with `sh`

* don't build serde in the clippy travis job

* only run clippy tests if installing clippy succeeds

* why is travis so picky?

* no more serde_codegen

* serde_test_suite_deps has no features

* don't use empty loops, llvm optimizes them to undefined behaviour

* abort the clippy job when clippy lints are triggered

* use caches on travis to speed up builds

* why are we even using `travis-cargo`?

* need to reinstall clippy frequently due to nightly updates

* command line tools are hard
2017-01-31 09:09:37 -08:00
Oliver Schneider 74cf80989d Merge pull request #731 from serde-rs/pubtuple
No tuple structs with private fields in public API
2017-01-31 08:56:46 +01:00
David Tolnay f0b4735781 No tuple structs with private fields in public API 2017-01-30 18:10:50 -08:00
David Tolnay 297f373548 Release 0.9.4 2017-01-30 17:42:11 -08:00
David Tolnay 81f28da8e1 Clarify the role of Impossible serializer 2017-01-30 17:41:33 -08:00
David Tolnay d4bb687032 Merge pull request #728 from nox/impossibru
Introduce ser::Impossible (fixes #694)
2017-01-30 17:26:21 -08:00
Anthony Ramine f9bc5037f5 Introduce ser::Impossible (fixes #694) 2017-01-31 02:20:04 +01:00
36 changed files with 2521 additions and 712 deletions
+6 -17
View File
@@ -1,5 +1,6 @@
sudo: false
language: rust
cache: cargo
# run builds for all the trains (and more)
rust:
@@ -8,21 +9,9 @@ rust:
- beta
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
matrix:
include:
- rust: nightly
env: CLIPPY=true
script:
- (cd serde && travis-cargo build)
- (cd serde && travis-cargo --only beta test)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde && travis-cargo build -- --no-default-features)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd test_suite && travis-cargo --only beta test)
- (cd test_suite/deps && travis-cargo --only nightly build && cd .. && travis-cargo --only nightly test -- --features unstable-testing)
- (cd test_suite/no_std && travis-cargo --only nightly build)
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
script: ./travis.sh
+9
View File
@@ -0,0 +1,9 @@
[workspace]
members = [
"serde",
"serde_codegen_internals",
"serde_derive",
"serde_test",
"test_suite",
"test_suite/no_std",
]
+2 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "0.9.3"
version = "0.9.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -22,10 +22,7 @@ std = []
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
unstable-testing = ["clippy", "unstable", "std"]
[dependencies]
clippy = { version = "0.*", optional = true }
unstable-testing = ["unstable", "std"]
[dev-dependencies]
serde_derive = "0.9"
+743
View File
@@ -0,0 +1,743 @@
// 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::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,
};
/// 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<E> {
// Don't mind the PhantomData, just need to use E somewhere.
Bool(bool, PhantomData<E>),
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<u8>),
None,
Some(Box<Content<E>>),
Unit,
Newtype(Box<Content<E>>),
Seq(Vec<Content<E>>),
Map(Vec<(Content<E>, Content<E>)>),
}
impl<E> Deserialize for Content<E> {
fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
// Untagged and internally tagged enums are only supported in
// self-describing formats.
deserializer.deserialize(ContentVisitor::new())
}
}
struct ContentVisitor<E> {
err: PhantomData<E>,
}
impl<E> ContentVisitor<E> {
fn new() -> Self {
ContentVisitor {
err: PhantomData,
}
}
}
impl<E> Visitor for ContentVisitor<E> {
type Value = Content<E>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("any value")
}
fn visit_bool<F>(self, value: bool) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Bool(value, PhantomData))
}
fn visit_i8<F>(self, value: i8) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I8(value))
}
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I16(value))
}
fn visit_i32<F>(self, value: i32) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I32(value))
}
fn visit_i64<F>(self, value: i64) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I64(value))
}
fn visit_u8<F>(self, value: u8) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U8(value))
}
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U16(value))
}
fn visit_u32<F>(self, value: u32) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U32(value))
}
fn visit_u64<F>(self, value: u64) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U64(value))
}
fn visit_f32<F>(self, value: f32) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::F32(value))
}
fn visit_f64<F>(self, value: f64) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::F64(value))
}
fn visit_char<F>(self, value: char) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Char(value))
}
fn visit_str<F>(self, value: &str) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::String(value.into()))
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::String(value))
}
fn visit_bytes<F>(self, value: &[u8]) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Bytes(value.into()))
}
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Bytes(value))
}
fn visit_unit<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Unit)
}
fn visit_none<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v)))
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v)))
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor
{
let mut vec = Vec::with_capacity(visitor.size_hint().0);
while let Some(e) = try!(visitor.visit()) {
vec.push(e);
}
Ok(Content::Seq(vec))
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor
{
let mut vec = Vec::with_capacity(visitor.size_hint().0);
while let Some(kv) = try!(visitor.visit()) {
vec.push(kv);
}
Ok(Content::Map(vec))
}
fn visit_enum<V>(self, _visitor: V) -> Result<Self::Value, V::Error>
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<E> {
Tag,
Content(Content<E>),
}
struct TagOrContentVisitor<E> {
name: &'static str,
err: PhantomData<E>,
}
impl<E> TagOrContentVisitor<E> {
fn new(name: &'static str) -> Self {
TagOrContentVisitor {
name: name,
err: PhantomData,
}
}
}
impl<E> DeserializeSeed for TagOrContentVisitor<E> {
type Value = TagOrContent<E>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
// Internally tagged enums are only supported in self-describing
// formats.
deserializer.deserialize(self)
}
}
impl<E> Visitor for TagOrContentVisitor<E> {
type Value = TagOrContent<E>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "a type tag `{}` or any other value", self.name)
}
fn visit_bool<F>(self, value: bool) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_bool(value).map(TagOrContent::Content)
}
fn visit_i8<F>(self, value: i8) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_i8(value).map(TagOrContent::Content)
}
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_i16(value).map(TagOrContent::Content)
}
fn visit_i32<F>(self, value: i32) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_i32(value).map(TagOrContent::Content)
}
fn visit_i64<F>(self, value: i64) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_i64(value).map(TagOrContent::Content)
}
fn visit_u8<F>(self, value: u8) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_u8(value).map(TagOrContent::Content)
}
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_u16(value).map(TagOrContent::Content)
}
fn visit_u32<F>(self, value: u32) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_u32(value).map(TagOrContent::Content)
}
fn visit_u64<F>(self, value: u64) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_u64(value).map(TagOrContent::Content)
}
fn visit_f32<F>(self, value: f32) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_f32(value).map(TagOrContent::Content)
}
fn visit_f64<F>(self, value: f64) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_f64(value).map(TagOrContent::Content)
}
fn visit_char<F>(self, value: char) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_char(value).map(TagOrContent::Content)
}
fn visit_str<F>(self, value: &str) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name {
Ok(TagOrContent::Tag)
} else {
ContentVisitor::new().visit_str(value).map(TagOrContent::Content)
}
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name {
Ok(TagOrContent::Tag)
} else {
ContentVisitor::new().visit_string(value).map(TagOrContent::Content)
}
}
fn visit_bytes<F>(self, value: &[u8]) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name.as_bytes() {
Ok(TagOrContent::Tag)
} else {
ContentVisitor::new().visit_bytes(value).map(TagOrContent::Content)
}
}
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name.as_bytes() {
Ok(TagOrContent::Tag)
} else {
ContentVisitor::new().visit_byte_buf(value).map(TagOrContent::Content)
}
}
fn visit_unit<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_unit().map(TagOrContent::Content)
}
fn visit_none<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor::new().visit_none().map(TagOrContent::Content)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
ContentVisitor::new().visit_some(deserializer).map(TagOrContent::Content)
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
ContentVisitor::new().visit_newtype_struct(deserializer).map(TagOrContent::Content)
}
fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor
{
ContentVisitor::new().visit_seq(visitor).map(TagOrContent::Content)
}
fn visit_map<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor
{
ContentVisitor::new().visit_map(visitor).map(TagOrContent::Content)
}
fn visit_enum<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: EnumVisitor
{
ContentVisitor::new().visit_enum(visitor).map(TagOrContent::Content)
}
}
/// Used by generated code to deserialize an internally tagged enum.
///
/// Not public API.
pub struct TaggedContent<T, E> {
pub tag: T,
pub content: Content<E>,
}
/// Not public API.
pub struct TaggedContentVisitor<T, E> {
tag_name: &'static str,
tag: PhantomData<T>,
err: PhantomData<E>,
}
impl<T, E> TaggedContentVisitor<T, E> {
/// 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,
err: PhantomData,
}
}
}
impl<T, E> DeserializeSeed for TaggedContentVisitor<T, E>
where T: Deserialize
{
type Value = TaggedContent<T, E>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
// Internally tagged enums are only supported in self-describing
// formats.
deserializer.deserialize(self)
}
}
impl<T, E> Visitor for TaggedContentVisitor<T, E>
where T: Deserialize
{
type Value = TaggedContent<T, E>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("any value")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor
{
let mut tag = None;
let mut vec = Vec::with_capacity(visitor.size_hint().0);
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 when deserializing an internally tagged enum because the content will
/// be used exactly once.
impl<E> Deserializer for Content<E>
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match self {
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(*v),
Content::Newtype(v) => visitor.visit_newtype_struct(*v),
Content::Seq(v) => {
let seq = v.into_iter();
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();
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match self {
Content::None => visitor.visit_none(),
Content::Some(v) => visitor.visit_some(*v),
Content::Unit => visitor.visit_unit(),
_ => visitor.visit_some(self)
}
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
visitor.visit_newtype_struct(self)
}
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 enum ignored_any
}
}
impl<E> de::value::ValueDeserializer<E> for Content<E>
where E: de::Error
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
/// Used when deserializing an untagged enum because the content may need to be
/// used more than once.
impl<'a, E> Deserializer for &'a Content<E>
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match *self {
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(&**v),
Content::Newtype(ref v) => visitor.visit_newtype_struct(&**v),
Content::Seq(ref v) => {
let seq = v.into_iter();
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)| (k, 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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match *self {
Content::None => visitor.visit_none(),
Content::Some(ref v) => visitor.visit_some(&**v),
Content::Unit => visitor.visit_unit(),
_ => visitor.visit_some(self)
}
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
visitor.visit_newtype_struct(self)
}
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 enum ignored_any
}
}
impl<'a, E> de::value::ValueDeserializer<E> for &'a Content<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<V>(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<E>(self) -> Result<(), E>
where E: de::Error
{
Ok(())
}
}
-11
View File
@@ -27,8 +27,6 @@ use std::collections::{
VecDeque,
};
#[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
@@ -481,15 +479,6 @@ seq_impl!(
BTreeSet::new(),
BTreeSet::insert);
#[cfg(feature = "collections")]
seq_impl!(
EnumSet<T>,
EnumSetVisitor<T: Deserialize + CLike>,
visitor,
EnumSet::new(),
EnumSet::new(),
EnumSet::insert);
#[cfg(any(feature = "std", feature = "collections"))]
seq_impl!(
LinkedList<T>,
+6 -4
View File
@@ -115,6 +115,8 @@ mod from_primitive;
// Helpers used by generated code. Not public API.
#[doc(hidden)]
pub mod private;
#[cfg(any(feature = "std", feature = "collections"))]
mod content;
///////////////////////////////////////////////////////////////////////////////
@@ -488,8 +490,8 @@ impl<'a> Display for Expected + 'a {
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data structure** that can be
/// deserialized from any data format supported by Serde.
/// A **data structure** that can be deserialized from any data format supported
/// by Serde.
///
/// Serde provides `Deserialize` implementations for many Rust primitive and
/// standard library types. The complete list is [here][de]. All of these can
@@ -687,8 +689,8 @@ impl<T> DeserializeSeed for PhantomData<T>
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data format** that can deserialize
/// any data structure supported by Serde.
/// 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
+8
View File
@@ -2,6 +2,14 @@ use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{
Content,
TaggedContentVisitor,
InternallyTaggedUnitVisitor,
UntaggedUnitVisitor,
};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
+91 -39
View File
@@ -51,7 +51,9 @@ use bytes;
/// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)]
pub struct Error(ErrorImpl);
pub struct Error {
err: ErrorImpl,
}
#[cfg(any(feature = "std", feature = "collections"))]
type ErrorImpl = Box<str>;
@@ -61,19 +63,23 @@ type ErrorImpl = ();
impl de::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Display>(msg: T) -> Self {
Error(msg.to_string().into_boxed_str())
Error {
err: msg.to_string().into_boxed_str(),
}
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn custom<T: Display>(_msg: T) -> Self {
Error(())
Error {
err: (),
}
}
}
impl Display for Error {
#[cfg(any(feature = "std", feature = "collections"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(&self.0)
formatter.write_str(&self.err)
}
#[cfg(not(any(feature = "std", feature = "collections")))]
@@ -85,7 +91,7 @@ impl Display for Error {
impl error::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))]
fn description(&self) -> &str {
&self.0
&self.err
}
#[cfg(not(any(feature = "std", feature = "collections")))]
@@ -113,12 +119,16 @@ impl<E> ValueDeserializer<E> for ()
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer(PhantomData)
UnitDeserializer {
marker: PhantomData,
}
}
}
/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer<E>(PhantomData<E>);
pub struct UnitDeserializer<E> {
marker: PhantomData<E>,
}
impl<E> de::Deserializer for UnitDeserializer<E>
where E: de::Error
@@ -149,7 +159,10 @@ impl<E> de::Deserializer for UnitDeserializer<E>
macro_rules! primitive_deserializer {
($ty:ty, $name:ident, $method:ident $($cast:tt)*) => {
/// A helper deserializer that deserializes a number.
pub struct $name<E>($ty, PhantomData<E>);
pub struct $name<E> {
value: $ty,
marker: PhantomData<E>
}
impl<E> ValueDeserializer<E> for $ty
where E: de::Error,
@@ -157,7 +170,10 @@ macro_rules! primitive_deserializer {
type Deserializer = $name<E>;
fn into_deserializer(self) -> $name<E> {
$name(self, PhantomData)
$name {
value: self,
marker: PhantomData,
}
}
}
@@ -175,7 +191,7 @@ macro_rules! primitive_deserializer {
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.$method(self.0 $($cast)*)
visitor.$method(self.value $($cast)*)
}
}
}
@@ -199,7 +215,10 @@ primitive_deserializer!(char, CharDeserializer, visit_char);
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a, E>(&'a str, PhantomData<E>);
pub struct StrDeserializer<'a, E> {
value: &'a str,
marker: PhantomData<E>,
}
impl<'a, E> ValueDeserializer<E> for &'a str
where E: de::Error,
@@ -207,7 +226,10 @@ impl<'a, E> ValueDeserializer<E> for &'a str
type Deserializer = StrDeserializer<'a, E>;
fn into_deserializer(self) -> StrDeserializer<'a, E> {
StrDeserializer(self, PhantomData)
StrDeserializer {
value: self,
marker: PhantomData,
}
}
}
@@ -219,7 +241,7 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_str(self.0)
visitor.visit_str(self.value)
}
fn deserialize_enum<V>(self,
@@ -255,7 +277,10 @@ impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E>
/// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct StringDeserializer<E>(String, PhantomData<E>);
pub struct StringDeserializer<E> {
value: String,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> ValueDeserializer<E> for String
@@ -264,7 +289,10 @@ impl<E> ValueDeserializer<E> for String
type Deserializer = StringDeserializer<E>;
fn into_deserializer(self) -> StringDeserializer<E> {
StringDeserializer(self, PhantomData)
StringDeserializer {
value: self,
marker: PhantomData,
}
}
}
@@ -277,7 +305,7 @@ impl<E> de::Deserializer for StringDeserializer<E>
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_string(self.0)
visitor.visit_string(self.value)
}
fn deserialize_enum<V>(self,
@@ -314,7 +342,10 @@ impl<'a, E> de::EnumVisitor for StringDeserializer<E>
/// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct CowStrDeserializer<'a, E>(Cow<'a, str>, PhantomData<E>);
pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
@@ -323,7 +354,10 @@ impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
type Deserializer = CowStrDeserializer<'a, E>;
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
CowStrDeserializer(self, PhantomData)
CowStrDeserializer {
value: self,
marker: PhantomData,
}
}
}
@@ -336,7 +370,7 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0 {
match self.value {
Cow::Borrowed(string) => visitor.visit_str(string),
Cow::Owned(string) => visitor.visit_string(string),
}
@@ -394,7 +428,9 @@ impl<I, E> SeqDeserializer<I, E>
}
}
fn end(&mut self) -> Result<(), E> {
/// Check for remaining elements after passing a `SeqDeserializer` to
/// `Visitor::visit_seq`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0;
while self.iter.next().is_some() {
remaining += 1;
@@ -576,17 +612,9 @@ impl<I, E> MapDeserializer<I, E>
}
}
fn next_pair(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
match self.iter.next() {
Some(kv) => {
self.count += 1;
Some(private::Pair::split(kv))
}
None => None,
}
}
fn end(&mut self) -> Result<(), E> {
/// Check for remaining elements after passing a `MapDeserializer` to
/// `Visitor::visit_map`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0;
while self.iter.next().is_some() {
remaining += 1;
@@ -599,6 +627,16 @@ impl<I, E> MapDeserializer<I, E>
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)))
}
}
fn next_pair(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
match self.iter.next() {
Some(kv) => {
self.count += 1;
Some(private::Pair::split(kv))
}
None => None,
}
}
}
impl<I, E> de::Deserializer for MapDeserializer<I, E>
@@ -885,12 +923,18 @@ impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
type Deserializer = BytesDeserializer<'a, E>;
fn into_deserializer(self) -> BytesDeserializer<'a, E> {
BytesDeserializer(self.into(), PhantomData)
BytesDeserializer {
value: self.into(),
marker: PhantomData,
}
}
}
/// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a, E>(&'a [u8], PhantomData<E>);
pub struct BytesDeserializer<'a, E> {
value: &'a [u8],
marker: PhantomData<E>,
}
impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
where E: de::Error
@@ -900,7 +944,7 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_bytes(self.0)
visitor.visit_bytes(self.value)
}
forward_to_deserialize! {
@@ -919,13 +963,19 @@ impl<E> ValueDeserializer<E> for bytes::ByteBuf
type Deserializer = ByteBufDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(self.into(), PhantomData)
ByteBufDeserializer {
value: self.into(),
marker: PhantomData,
}
}
}
/// A helper deserializer that deserializes a `Vec<u8>`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct ByteBufDeserializer<E>(Vec<u8>, PhantomData<E>);
pub struct ByteBufDeserializer<E> {
value: Vec<u8>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<E> de::Deserializer for ByteBufDeserializer<E>
@@ -936,7 +986,7 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
visitor.visit_byte_buf(self.0)
visitor.visit_byte_buf(self.value)
}
forward_to_deserialize! {
@@ -952,10 +1002,12 @@ mod private {
use de::{self, Unexpected};
use core::marker::PhantomData;
pub struct UnitOnly<E>(PhantomData<E>);
pub struct UnitOnly<E> {
marker: PhantomData<E>,
}
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
(t, UnitOnly(PhantomData))
(t, UnitOnly { marker: PhantomData })
}
impl<E> de::VariantVisitor for UnitOnly<E>
+2 -1
View File
@@ -9,7 +9,8 @@ use collections::borrow::Cow;
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::result::Result;
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<str> {
+5 -5
View File
@@ -63,10 +63,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(nonzero, inclusive_range, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![deny(missing_docs)]
#[cfg(feature = "collections")]
@@ -81,12 +79,14 @@ extern crate core as actual_core;
#[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};
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option};
#[cfg(feature = "unstable")]
pub use actual_core::nonzero;
}
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[macro_use]
+1 -10
View File
@@ -24,8 +24,6 @@ use collections::{
Vec,
};
#[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
@@ -231,7 +229,7 @@ impl<'a, I> Serialize for Iterator<I>
where S: Serializer,
{
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
let iter = match self.0.borrow_mut().take() {
let iter = match self.data.borrow_mut().take() {
Some(iter) => iter.into_iter(),
None => return Err(Error::custom("Iterator used twice")),
};
@@ -278,13 +276,6 @@ impl<T> Serialize for BTreeSet<T>
serialize_seq!();
}
#[cfg(feature = "collections")]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
{
serialize_seq!();
}
#[cfg(feature = "std")]
impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash,
+177
View File
@@ -0,0 +1,177 @@
//! This module contains `Impossible` serializer and its implementations.
use core::marker::PhantomData;
use ser::{
self,
Serialize,
SerializeSeq,
SerializeTuple,
SerializeTupleStruct,
SerializeTupleVariant,
SerializeMap,
SerializeStruct,
SerializeStructVariant,
};
/// Helper type for implementing a `Serializer` that does not support
/// 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`.
///
/// ```rust,ignore
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// type SerializeSeq = Impossible<(), Error>;
/// /* other associated types */
///
/// /// This data format does not support serializing sequences.
/// fn serialize_seq(self,
/// len: Option<usize>)
/// -> Result<Self::SerializeSeq, Error> {
/// // Given Impossible cannot be instantiated, the only
/// // thing we can do here is to return an error.
/// Err(...)
/// }
///
/// /* other Serializer methods */
/// }
/// ```
pub struct Impossible<Ok, E> {
void: Void,
_marker: PhantomData<(Ok, E)>,
}
enum Void {}
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeMap for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self,
_key: &T)
-> Result<(), E> {
match self.void {}
}
fn serialize_value<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
+18 -7
View File
@@ -104,6 +104,13 @@ use core::cell::RefCell;
use core::fmt::Display;
mod impls;
mod impossible;
// Helpers used by generated code. Not public API.
#[doc(hidden)]
pub mod private;
pub use self::impossible::Impossible;
///////////////////////////////////////////////////////////////////////////////
@@ -138,8 +145,8 @@ pub trait Error: Sized + error::Error {
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data structure** that can be
/// serialized into any data format supported by Serde.
/// A **data structure** that can be serialized into any data format supported
/// by Serde.
///
/// Serde provides `Serialize` implementations for many Rust primitive and
/// standard library types. The complete list is [here][ser]. All of these can
@@ -175,8 +182,7 @@ pub trait Serialize {
///////////////////////////////////////////////////////////////////////////////
/// An implementation of this trait is a **data format** that can serialize any
/// data structure supported by Serde.
/// 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
@@ -802,9 +808,12 @@ pub trait SerializeStructVariant {
/// of this with the `serde::ser::iterator` function every time you want to
/// serialize an iterator.
#[cfg(feature = "unstable")]
pub struct Iterator<I>(RefCell<Option<I>>)
pub struct Iterator<I>
where <I as IntoIterator>::Item: Serialize,
I: IntoIterator;
I: IntoIterator
{
data: RefCell<Option<I>>,
}
/// Create a wrapper type that can be passed to any function expecting a
/// `Serialize` and will serialize the given iterator as a sequence.
@@ -813,5 +822,7 @@ pub fn iterator<I>(iter: I) -> Iterator<I>
where <I as IntoIterator>::Item: Serialize,
I: IntoIterator
{
Iterator(RefCell::new(Some(iter)))
Iterator {
data: RefCell::new(Some(iter)),
}
}
+235
View File
@@ -0,0 +1,235 @@
use core::fmt::{self, Display};
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct};
/// Not public API.
pub fn serialize_tagged_newtype<S, T>(
serializer: S,
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
value: T,
) -> Result<S::Ok, S::Error>
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<S> {
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,
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"),
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<S> TaggedSerializer<S>
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<S> Serializer for TaggedSerializer<S>
where S: Serializer
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = S::SerializeSeq;
type SerializeTuple = S::SerializeTuple;
type SerializeTupleStruct = S::SerializeTupleStruct;
type SerializeTupleVariant = S::SerializeTupleVariant;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
type SerializeStructVariant = S::SerializeStructVariant;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(self, _: &'static str, _: usize, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_newtype_struct<T: ?Sized>(self, _: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self, _: &'static str, _: usize, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_seq_fixed_size(self, _: usize) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
fn serialize_tuple_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
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<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
fn serialize_struct_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
}
+1 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_codegen_internals"
version = "0.12.0"
version = "0.13.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
@@ -10,11 +10,7 @@ documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable-testing = ["clippy"]
[dependencies]
clippy = { version = "0.*", optional = true }
syn = "0.11"
[badges]
+85
View File
@@ -92,6 +92,32 @@ pub struct Item {
deny_unknown_fields: bool,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
tag: EnumTag,
}
/// Styles of representing an enum.
#[derive(Debug)]
pub enum EnumTag {
/// The default.
///
/// ```json
/// {"variant1": {"key1": "value1", "key2": "value2"}}
/// ```
External,
/// `#[serde(tag = "type")]`
///
/// ```json
/// {"type": "variant1", "key1": "value1", "key2": "value2"}
/// ```
Internal(String),
/// `#[serde(untagged)]`
///
/// ```json
/// {"key1": "value1", "key2": "value2"}
/// ```
None,
}
impl Item {
@@ -102,6 +128,8 @@ impl Item {
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let mut untagged = BoolAttr::none(cx, "untagged");
let mut internal_tag = Attr::none(cx, "tag");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
@@ -143,6 +171,32 @@ impl Item {
}
}
// Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => {
match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
}
}
// Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
internal_tag.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(tag = \"...\")] can only be used on enums")
}
}
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
@@ -155,6 +209,32 @@ impl Item {
}
}
let tag = match (untagged.get(), internal_tag.get()) {
(false, None) => EnumTag::External,
(true, None) => EnumTag::None,
(false, Some(tag)) => {
// 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)
}
(true, Some(_)) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
};
Item {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
@@ -163,6 +243,7 @@ impl Item {
deny_unknown_fields: deny_unknown_fields.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
tag: tag,
}
}
@@ -181,6 +262,10 @@ impl Item {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn tag(&self) -> &EnumTag {
&self.tag
}
}
/// Represents variant attribute information
-3
View File
@@ -1,6 +1,3 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
extern crate syn;
pub mod ast;
+2 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "0.9.3"
version = "0.9.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -12,7 +12,6 @@ include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable = []
unstable-testing = ["clippy", "serde_codegen_internals/unstable-testing"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
@@ -22,7 +21,6 @@ name = "serde_derive"
proc-macro = true
[dependencies]
clippy = { version = "0.*", optional = true }
quote = "0.3.8"
serde_codegen_internals = { version = "=0.12.0", default-features = false, path = "../serde_codegen_internals" }
serde_codegen_internals = { version = "=0.13.0", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.11", features = ["aster", "visit"] }
+355 -65
View File
@@ -110,7 +110,8 @@ fn deserialize_body(
impl_generics,
ty,
fields,
&item.attrs)
&item.attrs,
None)
}
Body::Struct(Style::Tuple, ref fields) |
Body::Struct(Style::Newtype, ref fields) => {
@@ -124,7 +125,8 @@ fn deserialize_body(
impl_generics,
ty,
fields,
&item.attrs)
&item.attrs,
None)
}
Body::Struct(Style::Unit, _) => {
deserialize_unit_struct(
@@ -209,21 +211,21 @@ fn deserialize_unit_struct(
type Value = #type_ident;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting)
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
}
#[inline]
fn visit_unit<__E>(self) -> _serde::export::Result<#type_ident, __E>
where __E: _serde::de::Error,
{
Ok(#type_ident)
_serde::export::Ok(#type_ident)
}
#[inline]
fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#type_ident, __V::Error>
where __V: _serde::de::SeqVisitor,
{
Ok(#type_ident)
_serde::export::Ok(#type_ident)
}
}
@@ -238,6 +240,7 @@ fn deserialize_tuple(
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
deserializer: Option<Tokens>,
) -> Tokens {
let where_clause = &impl_generics.where_clause;
@@ -274,14 +277,16 @@ fn deserialize_tuple(
false,
);
let dispatch = if is_enum {
let dispatch = if let Some(deserializer) = deserializer {
quote!(_serde::Deserializer::deserialize(#deserializer, #visitor_expr))
} else if is_enum {
quote!(_serde::de::VariantVisitor::visit_tuple(visitor, #nfields, #visitor_expr))
} else if nfields == 1 {
let type_name = item_attrs.name().deserialize_name();
quote!(deserializer.deserialize_newtype_struct(#type_name, #visitor_expr))
quote!(_serde::Deserializer::deserialize_newtype_struct(deserializer, #type_name, #visitor_expr))
} else {
let type_name = item_attrs.name().deserialize_name();
quote!(deserializer.deserialize_tuple_struct(#type_name, #nfields, #visitor_expr))
quote!(_serde::Deserializer::deserialize_tuple_struct(deserializer, #type_name, #nfields, #visitor_expr))
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
@@ -298,7 +303,7 @@ fn deserialize_tuple(
type Value = #ty;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting)
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
}
#visit_newtype_struct
@@ -341,7 +346,7 @@ fn deserialize_seq(
let visit = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote!(try!(visitor.visit::<#field_ty>()))
quote!(try!(_serde::de::SeqVisitor::visit::<#field_ty>(&mut visitor)))
}
Some(path) => {
let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with(
@@ -349,7 +354,8 @@ fn deserialize_seq(
quote!({
#wrapper
#wrapper_impl
try!(visitor.visit::<#wrapper_ty>()).map(|wrap| wrap.value)
try!(_serde::de::SeqVisitor::visit::<#wrapper_ty>(&mut visitor))
.map(|wrap| wrap.value)
})
}
};
@@ -357,7 +363,7 @@ fn deserialize_seq(
let #var = match #visit {
Some(value) => { value },
None => {
return Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
}
};
};
@@ -379,7 +385,7 @@ fn deserialize_seq(
quote! {
#(#let_values)*
Ok(#result)
_serde::export::Ok(#result)
}
}
@@ -411,7 +417,7 @@ fn deserialize_newtype_struct(
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer,
{
Ok(#type_path(#value))
_serde::export::Ok(#type_path(#value))
}
}
}
@@ -423,7 +429,11 @@ fn deserialize_struct(
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
deserializer: Option<Tokens>,
) -> Tokens {
let is_enum = variant_ident.is_some();
let is_untagged = deserializer.is_some();
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics);
@@ -453,15 +463,18 @@ fn deserialize_struct(
item_attrs,
);
let is_enum = variant_ident.is_some();
let dispatch = if is_enum {
let dispatch = if let Some(deserializer) = deserializer {
quote! {
_serde::Deserializer::deserialize(#deserializer, #visitor_expr)
}
} else if is_enum {
quote! {
_serde::de::VariantVisitor::visit_struct(visitor, FIELDS, #visitor_expr)
}
} else {
let type_name = item_attrs.name().deserialize_name();
quote! {
deserializer.deserialize_struct(#type_name, FIELDS, #visitor_expr)
_serde::Deserializer::deserialize_struct(deserializer, #type_name, FIELDS, #visitor_expr)
}
};
@@ -472,6 +485,20 @@ fn deserialize_struct(
quote!(mut visitor)
};
let visit_seq = if is_untagged {
// untagged struct variants do not get a visit_seq method
None
} else {
Some(quote! {
#[inline]
fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::SeqVisitor
{
#visit_seq
}
})
};
quote!({
#field_visitor
@@ -481,15 +508,10 @@ fn deserialize_struct(
type Value = #ty;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting)
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
}
#[inline]
fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::SeqVisitor
{
#visit_seq
}
#visit_seq
#[inline]
fn visit_map<__V>(self, mut visitor: __V) -> _serde::export::Result<#ty, __V::Error>
@@ -511,6 +533,45 @@ fn deserialize_item_enum(
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item
) -> Tokens {
match *item_attrs.tag() {
attr::EnumTag::External => {
deserialize_externally_tagged_enum(
type_ident,
impl_generics,
ty,
variants,
item_attrs,
)
}
attr::EnumTag::Internal(ref tag) => {
deserialize_internally_tagged_enum(
type_ident,
impl_generics,
ty,
variants,
item_attrs,
tag,
)
}
attr::EnumTag::None => {
deserialize_untagged_enum(
type_ident,
impl_generics,
ty,
variants,
item_attrs,
)
}
}
}
fn deserialize_externally_tagged_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> Tokens {
let where_clause = &impl_generics.where_clause;
@@ -544,7 +605,7 @@ fn deserialize_item_enum(
.map(|(i, variant)| {
let variant_name = field_i(i);
let block = deserialize_variant(
let block = deserialize_externally_tagged_variant(
type_ident,
impl_generics,
ty.clone(),
@@ -563,13 +624,14 @@ fn deserialize_item_enum(
// all variants have `#[serde(skip_deserializing)]`.
quote! {
// FIXME: Once we drop support for Rust 1.15:
// let Err(err) = visitor.visit_variant::<__Field>();
// Err(err)
visitor.visit_variant::<__Field>().map(|(impossible, _)| match impossible {})
// let _serde::export::Err(err) = _serde::de::EnumVisitor::visit_variant::<__Field>(visitor);
// _serde::export::Err(err)
_serde::de::EnumVisitor::visit_variant::<__Field>(visitor)
.map(|(impossible, _)| match impossible {})
}
} else {
quote! {
match try!(visitor.visit_variant()) {
match try!(_serde::de::EnumVisitor::visit_variant(visitor)) {
#(#variant_arms)*
}
}
@@ -586,7 +648,7 @@ fn deserialize_item_enum(
type Value = #ty;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting)
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
}
fn visit_enum<__V>(self, visitor: __V) -> _serde::export::Result<#ty, __V::Error>
@@ -598,11 +660,115 @@ fn deserialize_item_enum(
#variants_stmt
deserializer.deserialize_enum(#type_name, VARIANTS, #visitor_expr)
_serde::Deserializer::deserialize_enum(deserializer, #type_name, VARIANTS, #visitor_expr)
})
}
fn deserialize_variant(
fn deserialize_internally_tagged_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
tag: &str,
) -> Tokens {
let variant_names_idents: Vec<_> = variants.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
.collect();
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = deserialize_field_visitor(
variant_names_idents,
item_attrs,
true,
);
// 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 block = deserialize_internally_tagged_variant(
type_ident,
impl_generics,
ty.clone(),
variant,
item_attrs,
quote!(_tagged.content),
);
quote! {
__Field::#variant_name => #block
}
});
quote!({
#variant_visitor
#variants_stmt
let _tagged = try!(_serde::Deserializer::deserialize(
deserializer,
_serde::de::private::TaggedContentVisitor::<__Field, __D::Error>::new(#tag)));
match _tagged.tag {
#(#variant_arms)*
}
})
}
fn deserialize_untagged_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> Tokens {
let attempts = variants.iter()
.filter(|variant| !variant.attrs.skip_deserializing())
.map(|variant| {
deserialize_untagged_variant(
type_ident,
impl_generics,
ty.clone(),
variant,
item_attrs,
quote!(&_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
// processed before an error, and use the error that happened after the
// 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 {}", type_ident);
quote!({
let _content = try!(<_serde::de::private::Content<__D::Error> as _serde::Deserialize>::deserialize(deserializer));
#(
if let _serde::export::Ok(ok) = #attempts {
return _serde::export::Ok(ok);
}
)*
_serde::export::Err(_serde::de::Error::custom(#fallthrough_msg))
})
}
fn deserialize_externally_tagged_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
@@ -615,11 +781,11 @@ fn deserialize_variant(
Style::Unit => {
quote!({
try!(_serde::de::VariantVisitor::visit_unit(visitor));
Ok(#type_ident::#variant_ident)
_serde::export::Ok(#type_ident::#variant_ident)
})
}
Style::Newtype => {
deserialize_newtype_variant(
deserialize_externally_tagged_newtype_variant(
type_ident,
variant_ident,
generics,
@@ -634,6 +800,7 @@ fn deserialize_variant(
ty,
&variant.fields,
item_attrs,
None,
)
}
Style::Struct => {
@@ -644,22 +811,115 @@ fn deserialize_variant(
ty,
&variant.fields,
item_attrs,
None,
)
}
}
}
fn deserialize_newtype_variant(
fn deserialize_internally_tagged_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
deserializer: Tokens,
) -> Tokens {
let variant_ident = &variant.ident;
match variant.style {
Style::Unit => {
let type_name = type_ident.as_ref();
let variant_name = variant.ident.as_ref();
quote!({
try!(_serde::Deserializer::deserialize(#deserializer, _serde::de::private::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::export::Ok(#type_ident::#variant_ident)
})
}
Style::Newtype | Style::Struct => {
deserialize_untagged_variant(
type_ident,
generics,
ty,
variant,
item_attrs,
deserializer,
)
}
Style::Tuple => unreachable!("checked in serde_codegen_internals"),
}
}
fn deserialize_untagged_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
deserializer: Tokens,
) -> Tokens {
let variant_ident = &variant.ident;
match variant.style {
Style::Unit => {
let type_name = type_ident.as_ref();
let variant_name = variant.ident.as_ref();
quote! {
_serde::export::Result::map(
_serde::Deserializer::deserialize(
#deserializer,
_serde::de::private::UntaggedUnitVisitor::new(#type_name, #variant_name)
),
|()| #type_ident::#variant_ident)
}
}
Style::Newtype => {
deserialize_untagged_newtype_variant(
type_ident,
variant_ident,
generics,
&variant.fields[0],
deserializer,
)
}
Style::Tuple => {
deserialize_tuple(
type_ident,
Some(variant_ident),
generics,
ty,
&variant.fields,
item_attrs,
Some(deserializer),
)
}
Style::Struct => {
deserialize_struct(
type_ident,
Some(variant_ident),
generics,
ty,
&variant.fields,
item_attrs,
Some(deserializer),
)
}
}
}
fn deserialize_externally_tagged_newtype_variant(
type_ident: &syn::Ident,
variant_ident: &syn::Ident,
impl_generics: &syn::Generics,
field: &Field,
) -> Tokens {
let visit = match field.attrs.deserialize_with() {
match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote! {
try!(_serde::de::VariantVisitor::visit_newtype::<#field_ty>(visitor))
_serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#field_ty>(visitor),
#type_ident::#variant_ident),
}
}
Some(path) => {
@@ -668,12 +928,41 @@ fn deserialize_newtype_variant(
quote!({
#wrapper
#wrapper_impl
try!(_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(visitor)).value
_serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(visitor),
|_wrapper| #type_ident::#variant_ident(_wrapper.value))
})
}
}
}
fn deserialize_untagged_newtype_variant(
type_ident: &syn::Ident,
variant_ident: &syn::Ident,
impl_generics: &syn::Generics,
field: &Field,
deserializer: Tokens,
) -> Tokens {
match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote!({
_serde::export::Result::map(
<#field_ty as _serde::Deserialize>::deserialize(#deserializer),
#type_ident::#variant_ident)
})
}
Some(path) => {
let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with(
type_ident, impl_generics, field.ty, path);
quote!({
#wrapper
#wrapper_impl
_serde::export::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer),
|_wrapper| #type_ident::#variant_ident(_wrapper.value))
})
}
};
quote! {
Ok(#type_ident::#variant_ident(#visit)),
}
}
@@ -701,9 +990,9 @@ fn deserialize_field_visitor(
{
match value {
#(
#variant_indices => Ok(__Field::#field_idents),
#variant_indices => _serde::export::Ok(__Field::#field_idents),
)*
_ => Err(_serde::de::Error::invalid_value(
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(value as u64),
&#fallthrough_msg))
}
@@ -715,15 +1004,15 @@ fn deserialize_field_visitor(
let fallthrough_arm = if is_variant {
quote! {
Err(_serde::de::Error::unknown_variant(value, VARIANTS))
_serde::export::Err(_serde::de::Error::unknown_variant(value, VARIANTS))
}
} else if item_attrs.deny_unknown_fields() {
quote! {
Err(_serde::de::Error::unknown_field(value, FIELDS))
_serde::export::Err(_serde::de::Error::unknown_field(value, FIELDS))
}
} else {
quote! {
Ok(__Field::__ignore)
_serde::export::Ok(__Field::__ignore)
}
};
@@ -755,7 +1044,7 @@ fn deserialize_field_visitor(
type Value = __Field;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str("field name")
_serde::export::fmt::Formatter::write_str(formatter, "field name")
}
#visit_index
@@ -765,7 +1054,7 @@ fn deserialize_field_visitor(
{
match value {
#(
#field_strs => Ok(__Field::#field_idents),
#field_strs => _serde::export::Ok(__Field::#field_idents),
)*
_ => #fallthrough_arm
}
@@ -776,7 +1065,7 @@ fn deserialize_field_visitor(
{
match value {
#(
#field_bytes => Ok(__Field::#field_idents),
#field_bytes => _serde::export::Ok(__Field::#field_idents),
)*
_ => {
#bytes_to_str
@@ -786,7 +1075,7 @@ fn deserialize_field_visitor(
}
}
deserializer.deserialize_struct_field(__FieldVisitor)
_serde::Deserializer::deserialize_struct_field(deserializer, __FieldVisitor)
}
}
}
@@ -848,7 +1137,7 @@ fn deserialize_map(
.map(|&(field, ref name)| {
let field_ty = &field.ty;
quote! {
let mut #name: Option<#field_ty> = None;
let mut #name: _serde::export::Option<#field_ty> = _serde::export::None;
}
});
@@ -862,7 +1151,7 @@ fn deserialize_map(
None => {
let field_ty = &field.ty;
quote! {
try!(visitor.visit_value::<#field_ty>())
try!(_serde::de::MapVisitor::visit_value::<#field_ty>(&mut visitor))
}
}
Some(path) => {
@@ -871,16 +1160,16 @@ fn deserialize_map(
quote!({
#wrapper
#wrapper_impl
try!(visitor.visit_value::<#wrapper_ty>()).value
try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut visitor)).value
})
}
};
quote! {
__Field::#name => {
if #name.is_some() {
return Err(<__V::Error as _serde::de::Error>::duplicate_field(#deser_name));
if _serde::export::Option::is_some(&#name) {
return _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#deser_name));
}
#name = Some(#visit);
#name = _serde::export::Some(#visit);
}
}
});
@@ -890,7 +1179,7 @@ fn deserialize_map(
None
} else {
Some(quote! {
_ => { let _ = try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); }
_ => { let _ = try!(_serde::de::MapVisitor::visit_value::<_serde::de::impls::IgnoredAny>(&mut visitor)); }
})
};
@@ -898,12 +1187,13 @@ fn deserialize_map(
let match_keys = if item_attrs.deny_unknown_fields() && all_skipped {
quote! {
// FIXME: Once we drop support for Rust 1.15:
// let None::<__Field> = try!(visitor.visit_key());
try!(visitor.visit_key::<__Field>()).map(|impossible| match impossible {});
// let _serde::export::None::<__Field> = try!(_serde::de::MapVisitor::visit_key(&mut visitor));
try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut visitor))
.map(|impossible| match impossible {});
}
} else {
quote! {
while let Some(key) = try!(visitor.visit_key::<__Field>()) {
while let _serde::export::Some(key) = try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut visitor)) {
match key {
#(#value_arms)*
#ignored_arm
@@ -919,8 +1209,8 @@ fn deserialize_map(
quote! {
let #name = match #name {
Some(#name) => #name,
None => #missing_expr
_serde::export::Some(#name) => #name,
_serde::export::None => #missing_expr
};
}
});
@@ -943,7 +1233,7 @@ fn deserialize_map(
#(#extract_values)*
Ok(#struct_path { #(#result),* })
_serde::export::Ok(#struct_path { #(#result),* })
}
}
@@ -990,7 +1280,7 @@ fn wrap_deserialize_with(
where __D: _serde::Deserializer
{
let value = try!(#deserialize_with(__d));
Ok(__SerdeDeserializeWithStruct {
_serde::export::Ok(__SerdeDeserializeWithStruct {
value: value,
phantom: _serde::export::PhantomData,
})
@@ -1021,7 +1311,7 @@ fn expr_is_missing(attrs: &attr::Field) -> Tokens {
}
Some(_) => {
quote! {
return Err(<__V::Error as _serde::de::Error>::missing_field(#name))
return _serde::export::Err(<__V::Error as _serde::de::Error>::missing_field(#name))
}
}
}
+2 -4
View File
@@ -1,7 +1,5 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
+335 -94
View File
@@ -125,7 +125,7 @@ fn serialize_unit_struct(item_attrs: &attr::Item) -> Tokens {
let type_name = item_attrs.name().serialize_name();
quote! {
_serializer.serialize_unit_struct(#type_name)
_serde::Serializer::serialize_unit_struct(_serializer, #type_name)
}
}
@@ -144,7 +144,7 @@ fn serialize_newtype_struct(
}
quote! {
_serializer.serialize_newtype_struct(#type_name, #field_expr)
_serde::Serializer::serialize_newtype_struct(_serializer, #type_name, #field_expr)
}
}
@@ -167,7 +167,7 @@ fn serialize_tuple_struct(
let let_mut = mut_if(len > 0);
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len));
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(_serializer, #type_name, #len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
@@ -208,7 +208,7 @@ fn serialize_struct(
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len));
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(_serializer, #type_name, #len));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
@@ -251,16 +251,13 @@ fn serialize_variant(
variant_index: usize,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_ident = variant.ident.clone();
let variant_name = variant.attrs.name().serialize_name();
if variant.attrs.skip_serializing() {
let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
type_ident, variant_ident);
type_ident, variant_ident);
let skipped_err = quote! {
Err(_serde::ser::Error::custom(#skipped_msg))
_serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
@@ -271,139 +268,351 @@ fn serialize_variant(
#type_ident::#variant_ident #fields_pat => #skipped_err,
}
} else { // variant wasn't skipped
match variant.style {
let case = match variant.style {
Style::Unit => {
quote! {
#type_ident::#variant_ident =>
_serde::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
#type_ident::#variant_ident
}
},
}
Style::Newtype => {
let block = serialize_newtype_variant(
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote! {
#type_ident::#variant_ident(ref __simple_value) => #block,
#type_ident::#variant_ident(ref __simple_value)
}
},
}
Style::Tuple => {
let field_names = (0 .. variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)));
let block = serialize_tuple_variant(
type_name,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
);
quote! {
#type_ident::#variant_ident(#(ref #field_names),*) => { #block }
#type_ident::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let fields = variant.fields.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
quote! {
#type_ident::#variant_ident { #(ref #fields),* }
}
}
};
let block = serialize_struct_variant(
variant_index,
variant_name,
let body = match *item_attrs.tag() {
attr::EnumTag::External => {
serialize_externally_tagged_variant(
generics,
ty,
&variant.fields,
variant,
variant_index,
item_attrs,
);
)
}
attr::EnumTag::Internal(ref tag) => {
serialize_internally_tagged_variant(
type_ident.as_ref(),
variant_ident.as_ref(),
generics,
ty,
variant,
item_attrs,
tag,
)
}
attr::EnumTag::None => {
serialize_untagged_variant(
generics,
ty,
variant,
item_attrs,
)
}
};
quote! {
#type_ident::#variant_ident { #(ref #fields),* } => { #block }
}
quote! {
#case => #body
}
}
}
fn serialize_externally_tagged_variant(
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
match variant.style {
Style::Unit => {
quote! {
_serde::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::Serializer::serialize_newtype_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
),
}
}
Style::Tuple => {
let block = serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
},
generics,
ty,
&variant.fields,
);
quote! {
{ #block }
}
}
Style::Struct => {
let block = serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
{ #block }
}
}
}
}
fn serialize_newtype_variant(
type_name: String,
variant_index: usize,
variant_name: String,
item_ty: syn::Ty,
fn serialize_internally_tagged_variant(
type_ident: &str,
variant_ident: &str,
generics: &syn::Generics,
field: &Field,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
tag: &str,
) -> Tokens {
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&item_ty, generics, field.ty, path, field_expr);
}
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
quote! {
_serde::Serializer::serialize_newtype_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
)
match variant.style {
Style::Unit => {
quote!({
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!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::ser::private::serialize_tagged_newtype(
_serializer,
#type_ident,
#variant_ident,
#tag,
#variant_name,
#field_expr,
),
}
}
Style::Struct => {
let block = serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
{ #block }
}
}
Style::Tuple => unreachable!("checked in serde_codegen_internals"),
}
}
fn serialize_untagged_variant(
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
) -> Tokens {
match variant.style {
Style::Unit => {
quote! {
_serde::Serializer::serialize_unit(_serializer),
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::Serialize::serialize(#field_expr, _serializer),
}
}
Style::Tuple => {
let block = serialize_tuple_variant(
TupleVariant::Untagged,
generics,
ty,
&variant.fields,
);
quote! {
{ #block }
}
}
Style::Struct => {
let block = serialize_struct_variant(
StructVariant::Untagged,
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
{ #block }
}
}
}
}
enum TupleVariant {
ExternallyTagged {
type_name: String,
variant_index: usize,
variant_name: String,
},
Untagged,
}
fn serialize_tuple_variant(
type_name: String,
variant_index: usize,
variant_name: String,
context: TupleVariant,
generics: &syn::Generics,
structure_ty: syn::Ty,
fields: &[Field],
) -> Tokens {
let method = match context {
TupleVariant::ExternallyTagged{..} => {
quote!(_serde::ser::SerializeTupleVariant::serialize_field)
}
TupleVariant::Untagged => {
quote!(_serde::ser::SerializeTuple::serialize_element)
}
};
let serialize_stmts = serialize_tuple_struct_visitor(
structure_ty,
fields,
generics,
true,
quote!(_serde::ser::SerializeTupleVariant::serialize_field),
method,
);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_variant(
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
match context {
TupleVariant::ExternallyTagged { type_name, variant_index, variant_name } => {
quote! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
TupleVariant::Untagged => {
quote! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
_serializer,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
}
}
}
}
fn serialize_struct_variant(
variant_index: usize,
variant_name: String,
enum StructVariant<'a> {
ExternallyTagged {
variant_index: usize,
variant_name: String,
},
InternallyTagged {
tag: &'a str,
variant_name: String,
},
Untagged,
}
fn serialize_struct_variant<'a>(
context: StructVariant<'a>,
generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let method = match context {
StructVariant::ExternallyTagged{..} => {
quote!(_serde::ser::SerializeStructVariant::serialize_field)
}
StructVariant::InternallyTagged{..} | StructVariant::Untagged => {
quote!(_serde::ser::SerializeStruct::serialize_field)
}
};
let serialize_fields = serialize_struct_visitor(
ty.clone(),
fields,
generics,
true,
quote!(_serde::ser::SerializeStructVariant::serialize_field),
method,
);
let item_name = item_attrs.name().serialize_name();
@@ -425,15 +634,47 @@ fn serialize_struct_variant(
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct_variant(
#item_name,
#variant_index,
#variant_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
match context {
StructVariant::ExternallyTagged { variant_index, variant_name } => {
quote! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
_serializer,
#item_name,
#variant_index,
#variant_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
#item_name,
#len + 1,
));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
StructVariant::Untagged => {
quote! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
#item_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
}
}
@@ -537,7 +778,7 @@ fn wrap_serialize_with(
quote!({
struct __SerializeWith #wrapper_generics #where_clause {
value: &'__a #field_ty,
phantom: ::std::marker::PhantomData<#item_ty>,
phantom: _serde::export::PhantomData<#item_ty>,
}
impl #wrapper_generics _serde::Serialize for #wrapper_ty #where_clause {
@@ -550,7 +791,7 @@ fn wrap_serialize_with(
&__SerializeWith {
value: #value,
phantom: ::std::marker::PhantomData::<#item_ty>,
phantom: _serde::export::PhantomData::<#item_ty>,
}
})
}
+1 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "0.9.3"
version = "0.9.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
@@ -11,11 +11,7 @@ readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable-testing = ["clippy"]
[dependencies]
clippy = { version = "0.*", optional = true }
serde = { version = "0.9", path = "../serde" }
[badges]
+54 -414
View File
@@ -47,91 +47,29 @@ impl<I> Deserializer<I>
}
}
fn visit_seq<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
fn visit_seq<V>(&mut self, len: Option<usize>, sep: Token<'static>, end: Token<'static>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
sep: sep,
end: end.clone(),
}));
try!(self.expect_token(Token::SeqEnd));
try!(self.expect_token(end));
Ok(value)
}
fn visit_array<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerArrayVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::SeqEnd));
Ok(value)
}
fn visit_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerTupleVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::TupleEnd));
Ok(value)
}
fn visit_tuple_struct<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerTupleStructVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::TupleStructEnd));
Ok(value)
}
fn visit_variant_seq<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerVariantSeqVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::EnumSeqEnd));
Ok(value)
}
fn visit_map<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
fn visit_map<V>(&mut self, len: Option<usize>, sep: Token<'static>, end: Token<'static>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
sep: sep,
end: end.clone(),
}));
try!(self.expect_token(Token::MapEnd));
Ok(value)
}
fn visit_struct<V>(&mut self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_map(DeserializerStructVisitor {
de: self,
len: fields.len(),
}));
try!(self.expect_token(Token::StructEnd));
Ok(value)
}
fn visit_variant_map<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_map(DeserializerVariantMapVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::EnumMapEnd));
try!(self.expect_token(end));
Ok(value)
}
}
@@ -141,89 +79,9 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
{
type Error = Error;
fn deserialize_seq<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct_field<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_map<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bytes<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_byte_buf<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_ignored_any<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_string<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_str<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_char<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i16<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i8<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u16<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u8<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bool<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
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
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -251,16 +109,22 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(_name)) => visitor.visit_unit(),
Some(Token::SeqStart(len)) => {
self.visit_seq(len, visitor)
self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor)
}
Some(Token::SeqArrayStart(len))| Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(Some(len), visitor)
Some(Token::SeqArrayStart(len)) => {
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(Token::TupleStart(len)) => {
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(Some(len), Token::TupleStructSep, Token::TupleStructEnd, visitor)
}
Some(Token::MapStart(len)) => {
self.visit_map(len, visitor)
self.visit_map(len, Token::MapSep, Token::MapEnd, visitor)
}
Some(Token::StructStart(_, len)) => {
self.visit_map(Some(len), visitor)
self.visit_map(Some(len), Token::StructSep, Token::StructEnd, visitor)
}
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfTokens),
@@ -360,7 +224,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
match self.tokens.peek() {
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
@@ -379,19 +243,19 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), visitor)
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_tuple(len, visitor)
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(&Token::TupleStructStart(_, _)) => {
self.tokens.next();
self.visit_tuple_struct(len, visitor)
self.visit_seq(Some(len), Token::TupleStructSep, Token::TupleStructEnd, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
@@ -419,20 +283,20 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), visitor)
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_tuple(len, visitor)
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_tuple_struct(len, visitor)
self.visit_seq(Some(len), Token::TupleStructSep, Token::TupleStructEnd, visitor)
} else {
Err(Error::InvalidName(n))
}
@@ -452,14 +316,14 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
Some(&Token::StructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_struct(fields, visitor)
self.visit_map(Some(fields.len()), Token::StructSep, Token::StructEnd, visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::MapStart(_)) => {
self.tokens.next();
self.visit_map(Some(fields.len()), visitor)
self.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens),
@@ -472,6 +336,8 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
struct DeserializerSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
}
impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
@@ -482,158 +348,15 @@ impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
if self.de.tokens.peek() == Some(&self.end) {
return Ok(None);
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerArrayVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerArrayVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len -= 1;
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(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerTupleVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::TupleSep) => {
self.de.tokens.next();
self.len -= 1;
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::TupleEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerTupleStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::TupleStructSep) => {
self.de.tokens.next();
self.len -= 1;
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::TupleStructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::EnumSeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
Some(other) => Err(Error::UnexpectedToken(other)),
None => Err(Error::EndOfTokens),
}
}
@@ -649,6 +372,8 @@ impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I>
struct DeserializerMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
}
impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
@@ -659,17 +384,15 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::MapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
if self.de.tokens.peek() == 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(&Token::MapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
Some(other) => Err(Error::UnexpectedToken(other)),
None => Err(Error::EndOfTokens),
}
}
@@ -688,47 +411,6 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
//////////////////////////////////////////////////////////////////////////
struct DeserializerStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> MapVisitor for DeserializerStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::StructSep) => {
self.de.tokens.next();
self.len = self.len.saturating_sub(1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::StructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerEnumVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
}
@@ -803,7 +485,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_variant_seq(Some(len), visitor)
self.de.visit_seq(Some(len), Token::EnumSeqSep, Token::EnumSeqEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
@@ -812,7 +494,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap();
if len == enum_len {
self.de.visit_seq(Some(len), visitor)
self.de.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
@@ -834,7 +516,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_variant_map(Some(fields.len()), visitor)
self.de.visit_map(Some(fields.len()), Token::EnumMapSep, Token::EnumMapEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
@@ -843,7 +525,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), visitor)
self.de.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
} else {
Err(Error::UnexpectedToken(token))
}
@@ -855,45 +537,3 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
}
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> MapVisitor for DeserializerVariantMapVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::EnumMapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
+1 -3
View File
@@ -1,6 +1,4 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#[macro_use]
extern crate serde;
mod assert;
-4
View File
@@ -13,11 +13,8 @@ publish = false
[features]
unstable-testing = [
"clippy",
"compiletest_rs",
"serde/unstable-testing",
"serde_derive/unstable-testing",
"serde_test/unstable-testing",
]
[dev-dependencies]
@@ -28,7 +25,6 @@ serde_derive = { path = "../serde_derive" }
serde_test = { path = "../serde_test" }
[dependencies]
clippy = { version = "0.*", optional = true }
compiletest_rs = { version = "0.2", optional = true }
[[test]]
+2
View File
@@ -4,6 +4,8 @@ version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
+3 -1
View File
@@ -21,7 +21,9 @@ pub extern fn rust_eh_unwind_resume() {}
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32) -> ! {
loop {}
unsafe {
libc::abort()
}
}
//////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] cannot be used with tuple variants
enum E {
Tuple(u8, u8),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] can only be used on enums
struct S;
fn main() {}
@@ -0,0 +1,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[serde(untagged)]
#[serde(tag = "type")] //~^^ HELP: enum cannot be both untagged and internally tagged
enum E {
A(u8),
B(String),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[serde(untagged)] //~^ HELP: #[serde(untagged)] can only be used on enums
struct S;
fn main() {}
-3
View File
@@ -1,6 +1,3 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "unstable-testing", feature(test, non_ascii_idents))]
#[cfg(feature = "unstable-testing")]
+7 -7
View File
@@ -225,7 +225,7 @@ declare_tests! {
],
() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_unit_struct {
@@ -330,7 +330,7 @@ declare_tests! {
],
BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_hashset {
@@ -358,7 +358,7 @@ declare_tests! {
],
HashSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
hashset![FnvHasher @ 1, 2, 3] => &[
Token::SeqStart(Some(3)),
@@ -408,7 +408,7 @@ declare_tests! {
],
Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_array {
@@ -472,7 +472,7 @@ declare_tests! {
],
[0; 0] => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
Token::TupleStructEnd,
],
}
test_tuple {
@@ -564,7 +564,7 @@ declare_tests! {
],
BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0),
Token::MapEnd,
Token::StructEnd,
],
}
test_hashmap {
@@ -618,7 +618,7 @@ declare_tests! {
],
HashMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0),
Token::MapEnd,
Token::StructEnd,
],
hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
+5 -1
View File
@@ -8,11 +8,15 @@ use self::serde::de::{Deserialize, Deserializer};
use std::borrow::Cow;
use std::marker::PhantomData;
use std::result::Result as StdResult;
// Try to trip up the generated code if it fails to use fully qualified paths.
#[allow(dead_code)]
struct Result;
use std::result::Result as StdResult;
#[allow(dead_code)]
struct Ok;
#[allow(dead_code)]
struct Err;
//////////////////////////////////////////////////////////////////////////
+256
View File
@@ -1,11 +1,14 @@
extern crate serde_test;
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;
// That tests that the derived Serialize implementation doesn't trigger
@@ -625,3 +628,256 @@ fn test_enum_state_field() {
]
);
}
#[test]
fn test_untagged_enum() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum Untagged {
A {
a: u8,
},
B {
b: u8,
},
C,
D(u8),
E(String),
F(u8, u8),
}
assert_tokens(
&Untagged::A { a: 1 },
&[
Token::StructStart("Untagged", 1),
Token::StructSep,
Token::Str("a"),
Token::U8(1),
Token::StructEnd,
]
);
assert_tokens(
&Untagged::B { b: 2 },
&[
Token::StructStart("Untagged", 1),
Token::StructSep,
Token::Str("b"),
Token::U8(2),
Token::StructEnd,
]
);
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::F(1, 2),
&[
Token::TupleStart(2),
Token::TupleSep,
Token::U8(1),
Token::TupleSep,
Token::U8(2),
Token::TupleEnd,
]
);
assert_de_tokens_error::<Untagged>(
&[
Token::Option(false),
],
Error::Message("data did not match any variant of untagged enum Untagged".to_owned()),
);
assert_de_tokens_error::<Untagged>(
&[
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::<Untagged>(
&[
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()),
);
}
#[test]
fn test_internally_tagged_enum() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Newtype(BTreeMap<String, String>);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Struct {
f: u8,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
enum InternallyTagged {
A {
a: u8,
},
B {
b: u8,
},
C,
D(BTreeMap<String, String>),
E(Newtype),
F(Struct),
}
assert_tokens(
&InternallyTagged::A { a: 1 },
&[
Token::StructStart("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::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::StructSep,
Token::Str("type"),
Token::Str("C"),
Token::StructEnd,
]
);
assert_tokens(
&InternallyTagged::D(BTreeMap::new()),
&[
Token::MapStart(Some(1)),
Token::MapSep,
Token::Str("type"),
Token::Str("D"),
Token::MapEnd,
]
);
assert_tokens(
&InternallyTagged::E(Newtype(BTreeMap::new())),
&[
Token::MapStart(Some(1)),
Token::MapSep,
Token::Str("type"),
Token::Str("E"),
Token::MapEnd,
]
);
assert_tokens(
&InternallyTagged::F(Struct { f: 6 }),
&[
Token::StructStart("Struct", 2),
Token::StructSep,
Token::Str("type"),
Token::Str("F"),
Token::StructSep,
Token::Str("f"),
Token::U8(6),
Token::StructEnd,
]
);
assert_de_tokens_error::<InternallyTagged>(
&[
Token::MapStart(Some(0)),
Token::MapEnd,
],
Error::Message("missing field `type`".to_owned()),
);
assert_de_tokens_error::<InternallyTagged>(
&[
Token::MapStart(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()),
);
}
Executable
+71
View File
@@ -0,0 +1,71 @@
#!/bin/bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
channel() {
if [ -n "${TRAVIS}" ]; then
if [ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" ]; then
pwd
(set -x; cargo "$@")
fi
else
pwd
(set -x; cargo "+${CHANNEL}" "$@")
fi
}
if [ -n "${CLIPPY}" ]; then
# cached installation will not work on a later nightly
if [ -n "${TRAVIS}" ] && ! cargo install clippy --debug --force; then
echo "COULD NOT COMPILE CLIPPY, IGNORING CLIPPY TESTS"
exit
fi
cd "$DIR/serde"
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/serde_derive"
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/test_suite"
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/test_suite/no_std"
cargo clippy -- -Dclippy
else
CHANNEL=nightly
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
channel build --no-default-features --features alloc
channel build --no-default-features --features collections
channel test --features unstable-testing
cd "$DIR/test_suite/deps"
channel build
cd "$DIR/test_suite"
channel test --features unstable-testing
cd "$DIR/test_suite/no_std"
channel build
CHANNEL=beta
cargo clean
cd "$DIR/serde"
channel build
cd "$DIR/test_suite"
channel test
CHANNEL=stable
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
CHANNEL=1.13.0
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
fi