mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-28 16:07:57 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9956589ed5 | |||
| 81a3f66d78 | |||
| a8247bc619 | |||
| 66a9ccb10e | |||
| 53fe1b328e | |||
| 2753ec757b | |||
| dcd2232f69 | |||
| 0156f1355a | |||
| 61bf901048 | |||
| 7870b58356 | |||
| 8cc7e6aa90 | |||
| 7b50388fef | |||
| e704990322 | |||
| 2a4b8ce42d | |||
| 108cca687c | |||
| bca8c115c7 | |||
| b49bd52a53 | |||
| 27bd640812 | |||
| 8d5cda8464 | |||
| 389b9b5fe7 | |||
| 27478b6f71 | |||
| 480f858fc3 | |||
| 7d752c5a60 | |||
| 33b7841300 | |||
| 2244b92eb0 | |||
| d0464fbff7 | |||
| 98eddf9b29 | |||
| d23a40c1bb | |||
| 55cecace29 | |||
| 3da0deaa50 | |||
| 585550a5be | |||
| 5b7b8abf9f | |||
| 2aab0ce2f6 | |||
| a157c56d7d | |||
| 6c45593ee4 | |||
| 1175d54fb7 | |||
| cfdbbee845 | |||
| c1583bf2b8 | |||
| 7385b50249 | |||
| db6aaf5110 | |||
| c4a4501d71 | |||
| a3ae14d090 | |||
| dc4bb0bf08 | |||
| c69a3e083f | |||
| c790bd2a69 |
@@ -18,5 +18,8 @@ matrix:
|
|||||||
include:
|
include:
|
||||||
- rust: nightly
|
- rust: nightly
|
||||||
env: CLIPPY=true
|
env: CLIPPY=true
|
||||||
|
- rust: nightly
|
||||||
|
env: EMSCRIPTEN=true
|
||||||
|
script: nvm install 9 && ./travis.sh
|
||||||
|
|
||||||
script: ./travis.sh
|
script: ./travis.sh
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.72" # remember to update html_root_url
|
version = "1.0.79" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
|
|||||||
+7
-1
@@ -11,6 +11,9 @@ fn main() {
|
|||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let target = env::var("TARGET").unwrap();
|
||||||
|
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
|
||||||
|
|
||||||
// CString::into_boxed_c_str stabilized in Rust 1.20:
|
// CString::into_boxed_c_str stabilized in Rust 1.20:
|
||||||
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
|
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
|
||||||
if minor >= 20 {
|
if minor >= 20 {
|
||||||
@@ -32,7 +35,10 @@ fn main() {
|
|||||||
|
|
||||||
// 128-bit integers stabilized in Rust 1.26:
|
// 128-bit integers stabilized in Rust 1.26:
|
||||||
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
|
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
|
||||||
if minor >= 26 {
|
//
|
||||||
|
// Disabled on Emscripten targets as Emscripten doesn't
|
||||||
|
// currently support integers larger than 64 bits.
|
||||||
|
if minor >= 26 && !emscripten {
|
||||||
println!("cargo:rustc-cfg=integer128");
|
println!("cargo:rustc-cfg=integer128");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2242,10 +2242,17 @@ nonzero_integers! {
|
|||||||
NonZeroU16,
|
NonZeroU16,
|
||||||
NonZeroU32,
|
NonZeroU32,
|
||||||
NonZeroU64,
|
NonZeroU64,
|
||||||
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
|
|
||||||
NonZeroUsize,
|
NonZeroUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Currently 128-bit integers do not work on Emscripten targets so we need an
|
||||||
|
// additional `#[cfg]`
|
||||||
|
serde_if_integer128! {
|
||||||
|
nonzero_integers! {
|
||||||
|
NonZeroU128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<'de, T, E> Deserialize<'de> for Result<T, E>
|
impl<'de, T, E> Deserialize<'de> for Result<T, E>
|
||||||
|
|||||||
+2
-1
@@ -82,7 +82,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.72")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.79")]
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
@@ -91,6 +91,7 @@
|
|||||||
// https://github.com/serde-rs/serde/issues/812
|
// https://github.com/serde-rs/serde/issues/812
|
||||||
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
|
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
|
||||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
|
|||||||
@@ -231,8 +231,8 @@ mod content {
|
|||||||
|
|
||||||
use super::size_hint;
|
use super::size_hint;
|
||||||
use de::{
|
use de::{
|
||||||
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, MapAccess,
|
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
||||||
SeqAccess, Unexpected, Visitor,
|
MapAccess, SeqAccess, Unexpected, Visitor,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Used from generated code to buffer the contents of the Deserializer when
|
/// Used from generated code to buffer the contents of the Deserializer when
|
||||||
@@ -2470,10 +2470,11 @@ mod content {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<M>(self, _: M) -> Result<(), M::Error>
|
fn visit_map<M>(self, mut access: M) -> Result<(), M::Error>
|
||||||
where
|
where
|
||||||
M: MapAccess<'de>,
|
M: MapAccess<'de>,
|
||||||
{
|
{
|
||||||
|
while let Some(_) = try!(access.next_entry::<IgnoredAny, IgnoredAny>()) {}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2915,18 +2916,17 @@ where
|
|||||||
where
|
where
|
||||||
T: DeserializeSeed<'de>,
|
T: DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.iter.next() {
|
while let Some(item) = self.iter.next() {
|
||||||
Some(item) => {
|
if let Some((ref key, ref content)) = *item {
|
||||||
// Do not take(), instead borrow this entry. The internally tagged
|
// Do not take(), instead borrow this entry. The internally tagged
|
||||||
// enum does its own buffering so we can't tell whether this entry
|
// enum does its own buffering so we can't tell whether this entry
|
||||||
// is going to be consumed. Borrowing here leaves the entry
|
// is going to be consumed. Borrowing here leaves the entry
|
||||||
// available for later flattened fields.
|
// available for later flattened fields.
|
||||||
let (ref key, ref content) = *item.as_ref().unwrap();
|
|
||||||
self.pending = Some(content);
|
self.pending = Some(content);
|
||||||
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
|
return seed.deserialize(ContentRefDeserializer::new(key)).map(Some);
|
||||||
}
|
}
|
||||||
None => Ok(None),
|
|
||||||
}
|
}
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||||
|
|||||||
@@ -469,10 +469,17 @@ nonzero_integers! {
|
|||||||
NonZeroU16,
|
NonZeroU16,
|
||||||
NonZeroU32,
|
NonZeroU32,
|
||||||
NonZeroU64,
|
NonZeroU64,
|
||||||
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
|
|
||||||
NonZeroUsize,
|
NonZeroUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Currently 128-bit integers do not work on Emscripten targets so we need an
|
||||||
|
// additional `#[cfg]`
|
||||||
|
serde_if_integer128! {
|
||||||
|
nonzero_integers! {
|
||||||
|
NonZeroU128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Serialize for Cell<T>
|
impl<T> Serialize for Cell<T>
|
||||||
where
|
where
|
||||||
T: Serialize + Copy,
|
T: Serialize + Copy,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.72" # remember to update html_root_url
|
version = "1.0.79" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
@@ -25,8 +25,8 @@ proc-macro = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "0.4"
|
proc-macro2 = "0.4"
|
||||||
quote = "0.6"
|
quote = "0.6.3"
|
||||||
syn = { version = "0.14", features = ["visit"] }
|
syn = { version = "0.15", features = ["visit"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde = { version = "1.0", path = "../serde" }
|
serde = { version = "1.0", path = "../serde" }
|
||||||
|
|||||||
+25
-4
@@ -30,8 +30,9 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream
|
|||||||
let ident = &cont.ident;
|
let ident = &cont.ident;
|
||||||
let params = Parameters::new(&cont);
|
let params = Parameters::new(&cont);
|
||||||
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms);
|
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms);
|
||||||
|
let suffix = ident.to_string().trim_left_matches("r#").to_owned();
|
||||||
let dummy_const = Ident::new(
|
let dummy_const = Ident::new(
|
||||||
&format!("_IMPL_DESERIALIZE_FOR_{}", ident),
|
&format!("_IMPL_DESERIALIZE_FOR_{}", suffix),
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
);
|
);
|
||||||
let body = Stmts(deserialize_body(&cont, ¶ms));
|
let body = Stmts(deserialize_body(&cont, ¶ms));
|
||||||
@@ -1156,6 +1157,10 @@ fn deserialize_externally_tagged_enum(
|
|||||||
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
|
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let other_idx = variants
|
||||||
|
.iter()
|
||||||
|
.position(|ref variant| variant.attrs.other());
|
||||||
|
|
||||||
let variants_stmt = {
|
let variants_stmt = {
|
||||||
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
|
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
|
||||||
quote! {
|
quote! {
|
||||||
@@ -1167,6 +1172,7 @@ fn deserialize_externally_tagged_enum(
|
|||||||
&variant_names_idents,
|
&variant_names_idents,
|
||||||
cattrs,
|
cattrs,
|
||||||
true,
|
true,
|
||||||
|
other_idx,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Match arms to extract a variant from a string
|
// Match arms to extract a variant from a string
|
||||||
@@ -1254,6 +1260,10 @@ fn deserialize_internally_tagged_enum(
|
|||||||
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
|
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let other_idx = variants
|
||||||
|
.iter()
|
||||||
|
.position(|ref variant| variant.attrs.other());
|
||||||
|
|
||||||
let variants_stmt = {
|
let variants_stmt = {
|
||||||
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
|
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
|
||||||
quote! {
|
quote! {
|
||||||
@@ -1265,6 +1275,7 @@ fn deserialize_internally_tagged_enum(
|
|||||||
&variant_names_idents,
|
&variant_names_idents,
|
||||||
cattrs,
|
cattrs,
|
||||||
true,
|
true,
|
||||||
|
other_idx,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Match arms to extract a variant from a string
|
// Match arms to extract a variant from a string
|
||||||
@@ -1323,6 +1334,10 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
|
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let other_idx = variants
|
||||||
|
.iter()
|
||||||
|
.position(|ref variant| variant.attrs.other());
|
||||||
|
|
||||||
let variants_stmt = {
|
let variants_stmt = {
|
||||||
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
|
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
|
||||||
quote! {
|
quote! {
|
||||||
@@ -1334,6 +1349,7 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
&variant_names_idents,
|
&variant_names_idents,
|
||||||
cattrs,
|
cattrs,
|
||||||
true,
|
true,
|
||||||
|
other_idx,
|
||||||
));
|
));
|
||||||
|
|
||||||
let variant_arms: &Vec<_> = &variants
|
let variant_arms: &Vec<_> = &variants
|
||||||
@@ -1841,6 +1857,7 @@ fn deserialize_generated_identifier(
|
|||||||
fields: &[(String, Ident)],
|
fields: &[(String, Ident)],
|
||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
is_variant: bool,
|
is_variant: bool,
|
||||||
|
other_idx: Option<usize>,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let this = quote!(__Field);
|
let this = quote!(__Field);
|
||||||
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
|
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
|
||||||
@@ -1849,6 +1866,10 @@ fn deserialize_generated_identifier(
|
|||||||
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
|
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
|
||||||
let fallthrough = quote!(_serde::export::Ok(__Field::__other(__value)));
|
let fallthrough = quote!(_serde::export::Ok(__Field::__other(__value)));
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
} else if let Some(other_idx) = other_idx {
|
||||||
|
let ignore_variant = fields[other_idx].1.clone();
|
||||||
|
let fallthrough = quote!(_serde::export::Ok(__Field::#ignore_variant));
|
||||||
|
(None, Some(fallthrough))
|
||||||
} else if is_variant || cattrs.deny_unknown_fields() {
|
} else if is_variant || cattrs.deny_unknown_fields() {
|
||||||
(None, None)
|
(None, None)
|
||||||
} else {
|
} else {
|
||||||
@@ -2271,7 +2292,7 @@ fn deserialize_struct_as_struct_visitor(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false);
|
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
|
||||||
|
|
||||||
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
|
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
|
||||||
|
|
||||||
@@ -2291,7 +2312,7 @@ fn deserialize_struct_as_map_visitor(
|
|||||||
.map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i)))
|
.map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false);
|
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
|
||||||
|
|
||||||
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
|
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
|
||||||
|
|
||||||
@@ -2526,7 +2547,7 @@ fn deserialize_struct_as_struct_in_place_visitor(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false);
|
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
|
||||||
|
|
||||||
let visit_map = deserialize_map_in_place(params, fields, cattrs);
|
let visit_map = deserialize_map_in_place(params, fields, cattrs);
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use proc_macro2::{Group, Span, TokenStream, TokenTree};
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use syn;
|
use syn;
|
||||||
|
use syn::parse::{self, Parse, ParseStream};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::synom::{ParseError, Synom};
|
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
use syn::Meta::{List, NameValue, Word};
|
use syn::Meta::{List, NameValue, Word};
|
||||||
use syn::NestedMeta::{Literal, Meta};
|
use syn::NestedMeta::{Literal, Meta};
|
||||||
@@ -90,6 +90,10 @@ pub struct Name {
|
|||||||
deserialize: String,
|
deserialize: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unraw(ident: &Ident) -> String {
|
||||||
|
ident.to_string().trim_left_matches("r#").to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
impl Name {
|
impl Name {
|
||||||
/// Return the container name for the container when serializing.
|
/// Return the container name for the container when serializing.
|
||||||
pub fn serialize_name(&self) -> String {
|
pub fn serialize_name(&self) -> String {
|
||||||
@@ -380,8 +384,8 @@ impl Container {
|
|||||||
|
|
||||||
Container {
|
Container {
|
||||||
name: Name {
|
name: Name {
|
||||||
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
|
serialize: ser_name.get().unwrap_or_else(|| unraw(&item.ident)),
|
||||||
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
|
deserialize: de_name.get().unwrap_or_else(|| unraw(&item.ident)),
|
||||||
},
|
},
|
||||||
transparent: transparent.get(),
|
transparent: transparent.get(),
|
||||||
deny_unknown_fields: deny_unknown_fields.get(),
|
deny_unknown_fields: deny_unknown_fields.get(),
|
||||||
@@ -697,8 +701,8 @@ impl Variant {
|
|||||||
let de_renamed = de_name.is_some();
|
let de_renamed = de_name.is_some();
|
||||||
Variant {
|
Variant {
|
||||||
name: Name {
|
name: Name {
|
||||||
serialize: ser_name.unwrap_or_else(|| variant.ident.to_string()),
|
serialize: ser_name.unwrap_or_else(|| unraw(&variant.ident)),
|
||||||
deserialize: de_name.unwrap_or_else(|| variant.ident.to_string()),
|
deserialize: de_name.unwrap_or_else(|| unraw(&variant.ident)),
|
||||||
},
|
},
|
||||||
ser_renamed: ser_renamed,
|
ser_renamed: ser_renamed,
|
||||||
de_renamed: de_renamed,
|
de_renamed: de_renamed,
|
||||||
@@ -822,7 +826,7 @@ impl Field {
|
|||||||
let mut flatten = BoolAttr::none(cx, "flatten");
|
let mut flatten = BoolAttr::none(cx, "flatten");
|
||||||
|
|
||||||
let ident = match field.ident {
|
let ident = match field.ident {
|
||||||
Some(ref ident) => ident.to_string(),
|
Some(ref ident) => unraw(ident),
|
||||||
None => index.to_string(),
|
None => index.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1296,11 +1300,10 @@ fn parse_lit_into_lifetimes(
|
|||||||
|
|
||||||
struct BorrowedLifetimes(Punctuated<syn::Lifetime, Token![+]>);
|
struct BorrowedLifetimes(Punctuated<syn::Lifetime, Token![+]>);
|
||||||
|
|
||||||
impl Synom for BorrowedLifetimes {
|
impl Parse for BorrowedLifetimes {
|
||||||
named!(parse -> Self, map!(
|
fn parse(input: ParseStream) -> parse::Result<Self> {
|
||||||
call!(Punctuated::parse_separated_nonempty),
|
Punctuated::parse_separated_nonempty(input).map(BorrowedLifetimes)
|
||||||
BorrowedLifetimes
|
}
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
|
if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
|
||||||
@@ -1509,7 +1512,8 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
|||||||
syn::GenericArgument::Binding(ref binding) => {
|
syn::GenericArgument::Binding(ref binding) => {
|
||||||
collect_lifetimes(&binding.ty, out);
|
collect_lifetimes(&binding.ty, out);
|
||||||
}
|
}
|
||||||
syn::GenericArgument::Const(_) => {}
|
syn::GenericArgument::Constraint(_)
|
||||||
|
| syn::GenericArgument::Const(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1531,15 +1535,15 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_lit_str<T>(s: &syn::LitStr) -> Result<T, ParseError>
|
fn parse_lit_str<T>(s: &syn::LitStr) -> parse::Result<T>
|
||||||
where
|
where
|
||||||
T: Synom,
|
T: Parse,
|
||||||
{
|
{
|
||||||
let tokens = try!(spanned_tokens(s));
|
let tokens = try!(spanned_tokens(s));
|
||||||
syn::parse2(tokens)
|
syn::parse2(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spanned_tokens(s: &syn::LitStr) -> Result<TokenStream, ParseError> {
|
fn spanned_tokens(s: &syn::LitStr) -> parse::Result<TokenStream> {
|
||||||
let stream = try!(syn::parse_str(&s.value()));
|
let stream = try!(syn::parse_str(&s.value()));
|
||||||
Ok(respan_token_stream(stream, s.span()))
|
Ok(respan_token_stream(stream, s.span()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The `other` attribute must be used at most once and it must be the last
|
/// The `other` attribute must be used at most once and it must be the last
|
||||||
/// variant of an enum that has the `field_identifier` attribute.
|
/// variant of an enum.
|
||||||
///
|
///
|
||||||
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
|
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
|
||||||
/// `field_identifier` all but possibly one variant must be unit variants. The
|
/// `field_identifier` all but possibly one variant must be unit variants. The
|
||||||
@@ -111,42 +111,48 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
|
|||||||
variant.style,
|
variant.style,
|
||||||
cont.attrs.identifier(),
|
cont.attrs.identifier(),
|
||||||
variant.attrs.other(),
|
variant.attrs.other(),
|
||||||
|
cont.attrs.tag(),
|
||||||
) {
|
) {
|
||||||
// The `other` attribute may only be used in a field_identifier.
|
// The `other` attribute may not be used in a variant_identifier.
|
||||||
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
|
(_, Identifier::Variant, true, _) => {
|
||||||
cx.error("#[serde(other)] may only be used inside a field_identifier");
|
cx.error("#[serde(other)] may not be used on a variant_identifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variant with `other` attribute cannot appear in untagged enum
|
||||||
|
(_, Identifier::No, true, &EnumTag::None) => {
|
||||||
|
cx.error("#[serde(other)] cannot appear on untagged enum");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variant with `other` attribute must be the last one.
|
// Variant with `other` attribute must be the last one.
|
||||||
(Style::Unit, Identifier::Field, true) => {
|
(Style::Unit, Identifier::Field, true, _) | (Style::Unit, Identifier::No, true, _) => {
|
||||||
if i < variants.len() - 1 {
|
if i < variants.len() - 1 {
|
||||||
cx.error("#[serde(other)] must be the last variant");
|
cx.error("#[serde(other)] must be the last variant");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variant with `other` attribute must be a unit variant.
|
// Variant with `other` attribute must be a unit variant.
|
||||||
(_, Identifier::Field, true) => {
|
(_, Identifier::Field, true, _) | (_, Identifier::No, true, _) => {
|
||||||
cx.error("#[serde(other)] must be on a unit variant");
|
cx.error("#[serde(other)] must be on a unit variant");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any sort of variant is allowed if this is not an identifier.
|
// Any sort of variant is allowed if this is not an identifier.
|
||||||
(_, Identifier::No, false) => {}
|
(_, Identifier::No, false, _) => {}
|
||||||
|
|
||||||
// Unit variant without `other` attribute is always fine.
|
// Unit variant without `other` attribute is always fine.
|
||||||
(Style::Unit, _, false) => {}
|
(Style::Unit, _, false, _) => {}
|
||||||
|
|
||||||
// The last field is allowed to be a newtype catch-all.
|
// The last field is allowed to be a newtype catch-all.
|
||||||
(Style::Newtype, Identifier::Field, false) => {
|
(Style::Newtype, Identifier::Field, false, _) => {
|
||||||
if i < variants.len() - 1 {
|
if i < variants.len() - 1 {
|
||||||
cx.error(format!("`{}` must be the last variant", variant.ident));
|
cx.error(format!("`{}` must be the last variant", variant.ident));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, Identifier::Field, false) => {
|
(_, Identifier::Field, false, _) => {
|
||||||
cx.error("field_identifier may only contain unit variants");
|
cx.error("field_identifier may only contain unit variants");
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, Identifier::Variant, false) => {
|
(_, Identifier::Variant, false, _) => {
|
||||||
cx.error("variant_identifier may only contain unit variants");
|
cx.error("variant_identifier may only contain unit variants");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-14
@@ -22,35 +22,37 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.72")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.79")]
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
allow(
|
allow(
|
||||||
|
cyclomatic_complexity,
|
||||||
enum_variant_names,
|
enum_variant_names,
|
||||||
|
needless_pass_by_value,
|
||||||
redundant_field_names,
|
redundant_field_names,
|
||||||
too_many_arguments,
|
too_many_arguments,
|
||||||
used_underscore_binding,
|
used_underscore_binding,
|
||||||
cyclomatic_complexity,
|
|
||||||
needless_pass_by_value
|
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
// Whitelisted clippy_pedantic lints
|
// Whitelisted clippy_pedantic lints
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
allow(
|
allow(
|
||||||
items_after_statements,
|
|
||||||
doc_markdown,
|
|
||||||
stutter,
|
|
||||||
similar_names,
|
|
||||||
use_self,
|
|
||||||
single_match_else,
|
|
||||||
enum_glob_use,
|
|
||||||
match_same_arms,
|
|
||||||
filter_map,
|
|
||||||
cast_possible_truncation,
|
cast_possible_truncation,
|
||||||
|
doc_markdown,
|
||||||
|
enum_glob_use,
|
||||||
|
filter_map,
|
||||||
indexing_slicing,
|
indexing_slicing,
|
||||||
|
items_after_statements,
|
||||||
|
match_same_arms,
|
||||||
|
similar_names,
|
||||||
|
single_match_else,
|
||||||
|
stutter,
|
||||||
|
unseparated_literal_suffix,
|
||||||
|
use_self,
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
// The `quote!` macro requires deep recursion.
|
// The `quote!` macro requires deep recursion.
|
||||||
@@ -81,7 +83,7 @@ mod try;
|
|||||||
|
|
||||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||||
let input: DeriveInput = syn::parse(input).unwrap();
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
ser::expand_derive_serialize(&input)
|
ser::expand_derive_serialize(&input)
|
||||||
.unwrap_or_else(compile_error)
|
.unwrap_or_else(compile_error)
|
||||||
.into()
|
.into()
|
||||||
@@ -89,7 +91,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||||
let input: DeriveInput = syn::parse(input).unwrap();
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
de::expand_derive_deserialize(&input)
|
de::expand_derive_deserialize(&input)
|
||||||
.unwrap_or_else(compile_error)
|
.unwrap_or_else(compile_error)
|
||||||
.into()
|
.into()
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
|
|||||||
let ident = &cont.ident;
|
let ident = &cont.ident;
|
||||||
let params = Parameters::new(&cont);
|
let params = Parameters::new(&cont);
|
||||||
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||||
let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::call_site());
|
let suffix = ident.to_string().trim_left_matches("r#").to_owned();
|
||||||
|
let dummy_const = Ident::new(
|
||||||
|
&format!("_IMPL_SERIALIZE_FOR_{}", suffix),
|
||||||
|
Span::call_site(),
|
||||||
|
);
|
||||||
let body = Stmts(serialize_body(&cont, ¶ms));
|
let body = Stmts(serialize_body(&cont, ¶ms));
|
||||||
|
|
||||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ path = "lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "0.4"
|
proc-macro2 = "0.4"
|
||||||
syn = { version = "0.14", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
syn = { version = "0.15", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "serde-rs/serde" }
|
travis-ci = { repository = "serde-rs/serde" }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")]
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
allow(
|
allow(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.72" # remember to update html_root_url
|
version = "1.0.79" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||||
|
|||||||
@@ -161,7 +161,8 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.72")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.79")]
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(lang_items, start, panic_implementation)]
|
#![feature(lang_items, start, panic_handler)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
@@ -20,7 +20,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_eh_personality() {}
|
pub extern "C" fn rust_eh_personality() {}
|
||||||
|
|
||||||
#[panic_implementation]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::abort();
|
libc::abort();
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
// Copyright 2017 Serde Developers
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
enum F {
|
|
||||||
A,
|
|
||||||
#[serde(other)]
|
|
||||||
//~^^^^ ERROR: #[serde(other)] may only be used inside a field_identifier
|
|
||||||
B,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
@@ -20,7 +20,7 @@ mod remote {
|
|||||||
#[serde(remote = "remote::S")]
|
#[serde(remote = "remote::S")]
|
||||||
struct S {
|
struct S {
|
||||||
a: u8,
|
a: u8,
|
||||||
//~^^^^ ERROR: missing field `b` in initializer of `remote::S`
|
//~^^^ ERROR: missing field `b` in initializer of `remote::S`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ mod remote {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::S")]
|
#[serde(remote = "remote::S")]
|
||||||
struct S {
|
struct S {
|
||||||
//~^^^ ERROR: struct `remote::S` has no field named `b`
|
|
||||||
b: u8,
|
b: u8,
|
||||||
//~^^^^^ ERROR: no field `b` on type `&remote::S`
|
//~^ ERROR: struct `remote::S` has no field named `b`
|
||||||
|
//~^^ ERROR: no field `b` on type `&remote::S`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -6,15 +6,18 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
use self::serde::de::{self, Unexpected};
|
use self::serde::de::{self, MapAccess, Unexpected, Visitor};
|
||||||
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
extern crate serde_test;
|
extern crate serde_test;
|
||||||
@@ -2246,3 +2249,129 @@ fn test_transparent_tuple_struct() {
|
|||||||
|
|
||||||
assert_tokens(&Transparent(false, 1, false, PhantomData), &[Token::U32(1)]);
|
assert_tokens(&Transparent(false, 1, false, PhantomData), &[Token::U32(1)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_internally_tagged_unit_enum_with_unknown_fields() {
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
#[serde(tag = "t")]
|
||||||
|
enum Data {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = Data::A;
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&data,
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("t"),
|
||||||
|
Token::Str("A"),
|
||||||
|
Token::Str("b"),
|
||||||
|
Token::I32(0),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
struct S {
|
||||||
|
#[serde(flatten)]
|
||||||
|
x: X,
|
||||||
|
#[serde(flatten)]
|
||||||
|
y: Y,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
#[serde(tag = "typeX")]
|
||||||
|
enum X {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
#[serde(tag = "typeY")]
|
||||||
|
enum Y {
|
||||||
|
B { c: u32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = S {
|
||||||
|
x: X::A,
|
||||||
|
y: Y::B { c: 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&s,
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("typeX"),
|
||||||
|
Token::Str("A"),
|
||||||
|
Token::Str("typeY"),
|
||||||
|
Token::Str("B"),
|
||||||
|
Token::Str("c"),
|
||||||
|
Token::I32(0),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_flatten_any_after_flatten_struct() {
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
struct Any;
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Any {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct AnyVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for AnyVisitor {
|
||||||
|
type Value = Any;
|
||||||
|
|
||||||
|
fn expecting(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||||
|
where
|
||||||
|
M: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
while let Some((Any, Any)) = map.next_entry()? {}
|
||||||
|
Ok(Any)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_any(AnyVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
struct Outer {
|
||||||
|
#[serde(flatten)]
|
||||||
|
inner: Inner,
|
||||||
|
#[serde(flatten)]
|
||||||
|
extra: Any,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
struct Inner {
|
||||||
|
inner: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = Outer {
|
||||||
|
inner: Inner { inner: 0 },
|
||||||
|
extra: Any,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&s,
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("inner"),
|
||||||
|
Token::I32(0),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
allow(decimal_literal_representation)
|
allow(decimal_literal_representation)
|
||||||
@@ -135,6 +136,13 @@ enum EnumSkipAll {
|
|||||||
Skipped,
|
Skipped,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
enum EnumOther {
|
||||||
|
Unit,
|
||||||
|
#[serde(other)]
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! declare_tests {
|
macro_rules! declare_tests {
|
||||||
@@ -156,8 +164,12 @@ macro_rules! declare_tests {
|
|||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
|
|
||||||
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
|
($(
|
||||||
|
$(#[$cfg:meta])*
|
||||||
|
$name:ident { $($value:expr => $tokens:expr,)+ }
|
||||||
|
)+) => {
|
||||||
$(
|
$(
|
||||||
|
$(#[$cfg])*
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
$(
|
$(
|
||||||
@@ -260,6 +272,7 @@ declare_tests! {
|
|||||||
0f32 => &[Token::F32(0.)],
|
0f32 => &[Token::F32(0.)],
|
||||||
0f64 => &[Token::F64(0.)],
|
0f64 => &[Token::F64(0.)],
|
||||||
}
|
}
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
test_small_int_to_128 {
|
test_small_int_to_128 {
|
||||||
1i128 => &[Token::I8(1)],
|
1i128 => &[Token::I8(1)],
|
||||||
1i128 => &[Token::I16(1)],
|
1i128 => &[Token::I16(1)],
|
||||||
@@ -748,6 +761,20 @@ declare_tests! {
|
|||||||
Token::Unit,
|
Token::Unit,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_enum_other_unit {
|
||||||
|
EnumOther::Unit => &[
|
||||||
|
Token::Enum { name: "EnumOther" },
|
||||||
|
Token::Str("Unit"),
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
test_enum_other {
|
||||||
|
EnumOther::Other => &[
|
||||||
|
Token::Enum { name: "EnumOther" },
|
||||||
|
Token::Str("Foo"),
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_box {
|
test_box {
|
||||||
Box::new(0i32) => &[Token::I32(0)],
|
Box::new(0i32) => &[Token::I32(0)],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![deny(trivial_numeric_casts)]
|
#![deny(trivial_numeric_casts)]
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -618,6 +618,7 @@ fn test_enum_skipped() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_integer128() {
|
fn test_integer128() {
|
||||||
assert_ser_tokens_error(&1i128, &[], "i128 is not supported");
|
assert_ser_tokens_error(&1i128, &[], "i128 is not supported");
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2018 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![deny(warnings)]
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
extern crate serde;
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
extern crate serde_test;
|
||||||
|
|
||||||
|
// This test target is convoluted with the actual #[test] in a separate file to
|
||||||
|
// get it so that the stable compiler does not need to parse the code of the
|
||||||
|
// test. If the test were written with #[cfg(feature = "unstable")] #[test]
|
||||||
|
// right here, the stable compiler would fail to parse those raw identifiers
|
||||||
|
// even if the cfg were not enabled.
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
mod unstable;
|
||||||
@@ -26,6 +26,7 @@ fn test_u32_to_enum() {
|
|||||||
assert_eq!(E::B, e);
|
assert_eq!(E::B, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_integer128() {
|
fn test_integer128() {
|
||||||
let de_u128 = IntoDeserializer::<value::Error>::into_deserializer(1u128);
|
let de_u128 = IntoDeserializer::<value::Error>::into_deserializer(1u128);
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2018 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use serde_test::{assert_tokens, Token};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_identifiers() {
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
enum r#type {
|
||||||
|
r#type { r#type: () },
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_tokens(
|
||||||
|
&r#type::r#type { r#type: () },
|
||||||
|
&[
|
||||||
|
Token::StructVariant {
|
||||||
|
name: "type",
|
||||||
|
variant: "type",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Unit,
|
||||||
|
Token::StructVariantEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -42,6 +42,18 @@ if [ -n "${CLIPPY}" ]; then
|
|||||||
|
|
||||||
cd "$DIR/test_suite/no_std"
|
cd "$DIR/test_suite/no_std"
|
||||||
cargo clippy -- -Dclippy
|
cargo clippy -- -Dclippy
|
||||||
|
elif [ -n "${EMSCRIPTEN}" ]; then
|
||||||
|
CARGO_WEB_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/koute/cargo-web/releases/latest)
|
||||||
|
CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/')
|
||||||
|
CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
|
||||||
|
|
||||||
|
mkdir -p ~/.cargo/bin
|
||||||
|
echo "Downloading cargo-web from: ${CARGO_WEB_URL}"
|
||||||
|
curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
|
||||||
|
chmod +x ~/.cargo/bin/cargo-web
|
||||||
|
|
||||||
|
cd "$DIR/test_suite"
|
||||||
|
cargo web test --target=wasm32-unknown-emscripten --nodejs
|
||||||
else
|
else
|
||||||
CHANNEL=nightly
|
CHANNEL=nightly
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
@@ -50,6 +62,7 @@ else
|
|||||||
channel build
|
channel build
|
||||||
channel build --no-default-features
|
channel build --no-default-features
|
||||||
channel build --no-default-features --features alloc
|
channel build --no-default-features --features alloc
|
||||||
|
channel build --no-default-features --features 'rc alloc'
|
||||||
channel test --features 'rc unstable'
|
channel test --features 'rc unstable'
|
||||||
cd "$DIR/test_suite/deps"
|
cd "$DIR/test_suite/deps"
|
||||||
channel build
|
channel build
|
||||||
|
|||||||
Reference in New Issue
Block a user