Compare commits

...

76 Commits

Author SHA1 Message Date
David Tolnay 1b45e5766a Release 1.0.80 2018-10-14 03:08:53 -07:00
David Tolnay 59c8951341 Merge pull request #1411 from dtolnay/vec
Optimize Vec::deserialize_in_place to deserialize elements in place
2018-10-14 03:08:04 -07:00
David Tolnay aca61b5dda Optimize Vec::deserialize_in_place to deserialize elements in place 2018-10-14 02:51:24 -07:00
David Tolnay 908affd24f Remove unused code in seq and map impls 2018-10-14 02:31:56 -07:00
David Tolnay f878d2ebd5 Do not require clippy for a green build 2018-10-06 21:26:25 -07:00
David Tolnay 778e516270 Feature panic_handler has been stabilized 2018-10-06 21:12:14 -07:00
David Tolnay 6d58492ad0 Fix links to redirected derive documentation 2018-10-03 23:14:49 -07:00
David Tolnay fecfabb168 Merge pull request #1399 from derekdreery/more_docs
Some docs
2018-09-30 08:16:24 -07:00
Richard Dodd 80765eb453 Make suggested changes 2018-09-30 15:17:47 +01:00
Richard Dodd f1073dca04 Make the recommended changed from code review. 2018-09-30 12:34:52 +01:00
Richard Dodd da65fe5a52 Some docs 2018-09-29 15:06:23 +01:00
David Tolnay 3f0f739e17 Merge pull request #1391 from dtolnay/ci
Move CI commands into travis.yml and appveyor.yml
2018-09-15 17:00:27 -07:00
David Tolnay 5023e2ad52 Fix escaping issues in emscripten CI commands 2018-09-15 16:37:46 -07:00
David Tolnay 810cde1c84 Split travis builds into individual steps 2018-09-15 16:15:59 -07:00
David Tolnay 9436efb80e Move CI commands into travis.yml and appveyor.yml 2018-09-15 16:04:57 -07:00
David Tolnay 48230890c5 Merge pull request #1390 from dtolnay/asmjs
Run test suite on asmjs
2018-09-15 15:50:11 -07:00
David Tolnay f1e8dcf38e Run test suite on asmjs 2018-09-15 15:25:55 -07:00
David Tolnay 2cf10a6003 Remove separate proc-macro2/nightly build
This feature is automatically enabled on sufficiently new compilers.
2018-09-15 15:25:19 -07:00
David Tolnay 23a53d8008 Remove unused proc-macro2 dependency in test suite 2018-09-15 15:12:47 -07:00
David Tolnay 9956589ed5 Release 1.0.79 2018-09-15 14:40:38 -07:00
David Tolnay 81a3f66d78 Ignore unseparated_literal_suffix pedantic lint 2018-09-11 23:08:13 -07:00
David Tolnay a8247bc619 Sort the ignored lints in serde_derive 2018-09-11 23:08:00 -07:00
David Tolnay 66a9ccb10e Ignore renamed_and_removed_lints lint
The recommended replacement involving clippy::all has not been
stabilized yet.
2018-09-11 23:05:33 -07:00
David Tolnay 53fe1b328e Format with rustfmt 0.99.4 2018-09-11 23:00:08 -07:00
David Tolnay 2753ec757b Merge pull request #1382 from roblabla/serde-other
Implement #[serde(other)] on enum variant
2018-09-11 22:59:30 -07:00
roblabla dcd2232f69 Enforce unit struct for #[serde(other)] 2018-09-11 17:12:37 +00:00
roblabla 0156f1355a Remove obsolete compile-fail test 2018-09-10 17:15:22 +00:00
roblabla 61bf901048 Fix for rust 1.15 2018-09-10 17:12:33 +00:00
roblabla 7870b58356 Add tests for serde(other) in enum 2018-09-10 16:25:02 +00:00
roblabla 8cc7e6aa90 Implement #serde(other) on enum variant 2018-09-10 15:12:15 +00:00
David Tolnay 7b50388fef Release 1.0.78 2018-09-08 17:10:41 -07:00
David Tolnay e704990322 Merge pull request #1380 from dtolnay/f
Fix panic deserializing flattened any after flattened struct
2018-09-08 17:10:01 -07:00
David Tolnay 2a4b8ce42d Fix panic deserializing flattened any after flattened struct 2018-09-08 16:55:34 -07:00
David Tolnay 108cca687c Release 1.0.77 2018-09-06 21:36:27 -07:00
David Tolnay bca8c115c7 Merge pull request #1372 from dtolnay/syn
Update to syn 0.15
2018-09-06 21:34:14 -07:00
David Tolnay b49bd52a53 Use parse_macro_input to report parse errors 2018-09-06 21:16:12 -07:00
David Tolnay 27bd640812 Update to syn 0.15 2018-09-06 21:16:08 -07:00
David Tolnay 8d5cda8464 Merge pull request #1376 from dreid/fix-internally-tagged-enum-deserialization-with-unknown-fields
Fix internally tagged enum deserialization with unknown fields
2018-09-06 21:10:41 -07:00
David Reid 389b9b5fe7 Add a test for an internally tagged unit enum flattened with a second internally tagged unit enum. 2018-09-06 14:55:10 -07:00
David Reid 27478b6f71 Internally tagged unit enum variants should ignore unknown fields. 2018-09-06 14:29:49 -07:00
David Tolnay 480f858fc3 Update panic_handler attribute name changed in nightly 2018-09-03 08:24:27 -07:00
David Tolnay 7d752c5a60 Merge pull request #1373 from dtolnay/emscripten
Add Emscripten build in Travis
2018-09-02 13:56:41 -07:00
David Tolnay 33b7841300 Skip asmjs 2018-09-02 13:21:36 -07:00
David Tolnay 2244b92eb0 Nvm install in .travis.yml
The one in travis.sh was failing:

    ./travis.sh: line 56: nvm: command not found
    The command "./travis.sh" exited with 127.
2018-09-02 12:45:12 -07:00
David Tolnay d0464fbff7 Add Emscripten build in Travis 2018-09-02 12:34:13 -07:00
David Tolnay 98eddf9b29 Update to syn 0.15-rc1 2018-09-01 23:03:59 -07:00
David Tolnay d23a40c1bb Format with rustfmt 0.99.2 2018-09-01 23:03:41 -07:00
David Tolnay 55cecace29 Release 1.0.76 2018-09-01 15:25:53 -07:00
David Tolnay 3da0deaa50 Merge pull request #1371 from hcpl/nonzero_u128
Add support for `NonZeroU128`
2018-09-01 15:25:10 -07:00
hcpl 585550a5be Add support for NonZeroU128 2018-09-02 00:34:56 +03:00
David Tolnay 5b7b8abf9f Move some compile-fail errors based on proc-macro2 update 2018-08-28 20:35:49 -07:00
David Tolnay 2aab0ce2f6 Release 1.0.75 2018-08-24 23:03:04 -04:00
David Tolnay a157c56d7d Merge pull request #1367 from Eh2406/master
update a deb for minimal-versions
2018-08-24 23:02:02 -04:00
Eh2406 6c45593ee4 update a deb for minimal-versions 2018-08-24 22:50:17 -04:00
David Tolnay 1175d54fb7 Stabilize raw_identifiers 2018-08-24 19:49:13 -04:00
David Tolnay cfdbbee845 Release 1.0.74 2018-08-23 18:29:16 -04:00
David Tolnay c1583bf2b8 Merge pull request #1365 from koute/master
Disable i128 integers on Emscripten targets
2018-08-23 18:28:51 -04:00
Jan Bujak 7385b50249 Disable i128 integers on Emscripten targets 2018-08-24 00:02:40 +02:00
David Tolnay db6aaf5110 Release 1.0.73 2018-08-22 21:47:15 -04:00
David Tolnay c4a4501d71 Merge pull request #1363 from dtolnay/raw
Trim the r# from raw identifiers in user-facing strings
2018-08-22 21:46:31 -04:00
David Tolnay a3ae14d090 Test raw identifiers 2018-08-22 21:09:37 -04:00
David Tolnay dc4bb0bf08 Trim the r# from raw identifiers in user-facing strings 2018-08-22 20:50:29 -04:00
David Tolnay c69a3e083f Merge pull request #1360 from Pratyush/master
Update travis.sh to also test `--no-default-features --features "rc alloc"`
2018-08-20 21:38:55 -04:00
Pratyush Mishra c790bd2a69 Update travis.sh 2018-08-20 18:30:43 -07:00
David Tolnay 60cbbacdb3 Release 1.0.72 2018-08-20 21:02:03 -04:00
David Tolnay befc7edc17 Merge pull request #1359 from Pratyush/master
Fix compilation under `rc` feature
2018-08-20 21:00:47 -04:00
Pratyush Mishra 3897ccb3f9 Fix compilation under rc feature 2018-08-20 14:35:48 -07:00
David Tolnay 11c5fd78ad Abbreviate and touch up some attribute parsing comments 2018-08-14 22:37:59 -07:00
David Tolnay cbfdba3826 Use rustfmt to wrap and format comments 2018-08-14 22:32:27 -07:00
David Tolnay 5985b7edaf Format with rustfmt 0.99.2 2018-08-14 19:59:20 -07:00
David Tolnay d28a0e66c8 Fix old reference to serde_codegen 2018-08-12 10:54:59 -07:00
David Tolnay 0ca4db1616 Move untagged borrow test case into codegen tests 2018-08-12 10:54:29 -07:00
David Tolnay 72b3438dfc Merge pull request #1338 from toidiu/ak-untagged-enum
test borrowing untagged enum
2018-08-12 10:49:15 -07:00
David Tolnay c7051ac748 Update links to a renamed manual chapter 2018-08-12 10:48:20 -07:00
David Tolnay a065db9838 Add AppVeyor badge to rest of crates 2018-08-07 00:15:12 -07:00
toidiu 3ca0597a7e test borrowing untagged enum 2018-07-12 17:12:27 -04:00
45 changed files with 761 additions and 385 deletions
+88 -17
View File
@@ -1,22 +1,93 @@
sudo: false
language: rust language: rust
cache: cargo
# run builds for all the trains (and more)
rust:
- stable
- beta
- nightly
- 1.13.0
- 1.15.0
- 1.20.0
- 1.21.0
- 1.25.0
- 1.26.0
matrix: matrix:
include: include:
- rust: nightly - rust: stable
env: CLIPPY=true script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build
- cargo test
script: ./travis.sh - rust: beta
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test
- rust: nightly
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build
- cargo build --no-default-features
- cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc
- cargo test --features rc,unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/deps"
- cargo build
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test --features unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo build
- rust: 1.13.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build
- rust: 1.15.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo build
- rust: 1.20.0
- rust: 1.21.0
- rust: 1.25.0
- rust: 1.26.0
- rust: nightly
env: CLIPPY
script:
- rustup component add clippy-preview || travis_terminate 0
- cargo clippy -- -Dclippy
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo clippy --features rc,unstable -- -Dclippy
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo clippy -- -Dclippy
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo clippy -- -Dclippy
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo clippy --features unstable -- -Dclippy
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo clippy -- -Dclippy
- rust: nightly
env: EMSCRIPTEN
script:
- 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}" | jq -r .tag_name)
- CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
- nvm install 9
- mkdir -p ~/.cargo/bin
- curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
- chmod +x ~/.cargo/bin/cargo-web
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo web test --target=asmjs-unknown-emscripten --nodejs
- cargo web test --target=wasm32-unknown-emscripten --nodejs
allow_failures:
- rust: nightly
env: CLIPPY
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --no-default-features
- cargo build
+1 -1
View File
@@ -15,7 +15,7 @@ You may be looking for:
- [An overview of Serde](https://serde.rs/) - [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](https://serde.rs/#data-formats) - [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
- [Examples](https://serde.rs/examples.html) - [Examples](https://serde.rs/examples.html)
- [API documentation](https://docs.serde.rs/serde/) - [API documentation](https://docs.serde.rs/serde/)
- [Release notes](https://github.com/serde-rs/serde/releases) - [Release notes](https://github.com/serde-rs/serde/releases)
+26 -2
View File
@@ -13,5 +13,29 @@ install:
build: false build: false
test_script: for:
- sh -c 'PATH=`rustc --print sysroot`/bin:$PATH ./travis.sh' - matrix:
only:
- APPVEYOR_RUST_CHANNEL: stable
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\serde
- cargo build --features rc
- cargo build --no-default-features
- cd %APPVEYOR_BUILD_FOLDER%\serde_test
- cargo build
- cargo test
- matrix:
only:
- APPVEYOR_RUST_CHANNEL: nightly
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\serde
- cargo build
- cargo build --no-default-features
- cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc
- cargo test --features rc,unstable
- cd %APPVEYOR_BUILD_FOLDER%\test_suite\deps
- cargo build
- cd %APPVEYOR_BUILD_FOLDER%\test_suite
- cargo test --features unstable
+1 -1
View File
@@ -8,7 +8,7 @@ You may be looking for:
- [An overview of Serde](https://serde.rs/) - [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](https://serde.rs/#data-formats) - [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
- [Examples](https://serde.rs/examples.html) - [Examples](https://serde.rs/examples.html)
- [API documentation](https://docs.serde.rs/serde/) - [API documentation](https://docs.serde.rs/serde/)
- [Release notes](https://github.com/serde-rs/serde/releases) - [Release notes](https://github.com/serde-rs/serde/releases)
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.71" # remember to update html_root_url version = "1.0.80" # 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
View File
@@ -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");
} }
+8 -2
View File
@@ -20,7 +20,9 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// use std::fmt; /// use std::fmt;
/// use std::marker::PhantomData; /// use std::marker::PhantomData;
/// ///
/// use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, IgnoredAny}; /// use serde::de::{
/// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
/// };
/// ///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence /// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`. /// /// while efficiently discarding elements of any type before or after index `n`.
@@ -51,7 +53,11 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// type Value = T; /// type Value = T;
/// ///
/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// write!(formatter, "a sequence in which we care about element {}", self.n) /// write!(
/// formatter,
/// "a sequence in which we care about element {}",
/// self.n
/// )
/// } /// }
/// ///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> /// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+124 -56
View File
@@ -696,7 +696,6 @@ macro_rules! seq_impl {
( (
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
$access:ident, $access:ident,
$ctor:expr,
$clear:expr, $clear:expr,
$with_capacity:expr, $with_capacity:expr,
$reserve:expr, $reserve:expr,
@@ -793,7 +792,6 @@ fn nop_reserve<T>(_seq: T, _n: usize) {}
seq_impl!( seq_impl!(
BinaryHeap<T: Ord>, BinaryHeap<T: Ord>,
seq, seq,
BinaryHeap::new(),
BinaryHeap::clear, BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::reserve, BinaryHeap::reserve,
@@ -803,7 +801,6 @@ seq_impl!(
seq_impl!( seq_impl!(
BTreeSet<T: Eq + Ord>, BTreeSet<T: Eq + Ord>,
seq, seq,
BTreeSet::new(),
BTreeSet::clear, BTreeSet::clear,
BTreeSet::new(), BTreeSet::new(),
nop_reserve, nop_reserve,
@@ -813,7 +810,6 @@ seq_impl!(
seq_impl!( seq_impl!(
LinkedList<T>, LinkedList<T>,
seq, seq,
LinkedList::new(),
LinkedList::clear, LinkedList::clear,
LinkedList::new(), LinkedList::new(),
nop_reserve, nop_reserve,
@@ -824,28 +820,15 @@ seq_impl!(
seq_impl!( seq_impl!(
HashSet<T: Eq + Hash, S: BuildHasher + Default>, HashSet<T: Eq + Hash, S: BuildHasher + Default>,
seq, seq,
HashSet::with_hasher(S::default()),
HashSet::clear, HashSet::clear,
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::reserve, HashSet::reserve,
HashSet::insert); HashSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(
Vec<T>,
seq,
Vec::new(),
Vec::clear,
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::reserve,
Vec::push
);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
VecDeque<T>, VecDeque<T>,
seq, seq,
VecDeque::new(),
VecDeque::clear, VecDeque::clear,
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
VecDeque::reserve, VecDeque::reserve,
@@ -854,6 +837,97 @@ seq_impl!(
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T> Deserialize<'de> for Vec<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VecVisitor<T> {
marker: PhantomData<T>,
}
impl<'de, T> Visitor<'de> for VecVisitor<T>
where
T: Deserialize<'de>,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut values = Vec::with_capacity(size_hint::cautious(seq.size_hint()));
while let Some(value) = try!(seq.next_element()) {
values.push(value);
}
Ok(values)
}
}
let visitor = VecVisitor { marker: PhantomData };
deserializer.deserialize_seq(visitor)
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
struct VecInPlaceVisitor<'a, T: 'a>(&'a mut Vec<T>);
impl<'a, 'de, T> Visitor<'de> for VecInPlaceVisitor<'a, T>
where
T: Deserialize<'de>,
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let hint = size_hint::cautious(seq.size_hint());
if let Some(additional) = hint.checked_sub(self.0.len()) {
self.0.reserve(additional);
}
for i in 0..self.0.len() {
let next = {
let next_place = InPlaceSeed(&mut self.0[i]);
try!(seq.next_element_seed(next_place))
};
if next.is_none() {
self.0.truncate(i);
return Ok(());
}
}
while let Some(value) = try!(seq.next_element()) {
self.0.push(value);
}
Ok(())
}
}
deserializer.deserialize_seq(VecInPlaceVisitor(place))
}
}
////////////////////////////////////////////////////////////////////////////////
struct ArrayVisitor<A> { struct ArrayVisitor<A> {
marker: PhantomData<A>, marker: PhantomData<A>,
} }
@@ -1113,7 +1187,6 @@ macro_rules! map_impl {
( (
$ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
$access:ident, $access:ident,
$ctor:expr,
$with_capacity:expr $with_capacity:expr
) => { ) => {
impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty<K, V $(, $typaram)*> impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty<K, V $(, $typaram)*>
@@ -1168,14 +1241,12 @@ macro_rules! map_impl {
map_impl!( map_impl!(
BTreeMap<K: Ord, V>, BTreeMap<K: Ord, V>,
map, map,
BTreeMap::new(),
BTreeMap::new()); BTreeMap::new());
#[cfg(feature = "std")] #[cfg(feature = "std")]
map_impl!( map_impl!(
HashMap<K: Eq + Hash, V, S: BuildHasher + Default>, HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
map, map,
HashMap::with_hasher(S::default()),
HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default())); HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default()));
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1602,13 +1673,11 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
forwarded_impl!((), Box<str>, String::into_boxed_str); forwarded_impl!((), Box<str>, String::into_boxed_str);
#[cfg( #[cfg(all(
all( not(de_rc_dst),
not(de_rc_dst), feature = "rc",
feature = "rc", any(feature = "std", feature = "alloc")
any(feature = "std", feature = "alloc") ))]
)
)]
forwarded_impl! { forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1620,13 +1689,11 @@ forwarded_impl! {
(T), Arc<T>, Arc::new (T), Arc<T>, Arc::new
} }
#[cfg( #[cfg(all(
all( not(de_rc_dst),
not(de_rc_dst), feature = "rc",
feature = "rc", any(feature = "std", feature = "alloc")
any(feature = "std", feature = "alloc") ))]
)
)]
forwarded_impl! { forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1693,13 +1760,11 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg( #[cfg(all(
all( de_rc_dst,
de_rc_dst, feature = "rc",
feature = "rc", any(feature = "std", feature = "alloc")
any(feature = "std", feature = "alloc") ))]
)
)]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
( (
$(#[doc = $doc:tt])* $(#[doc = $doc:tt])*
@@ -1720,13 +1785,11 @@ macro_rules! box_forwarded_impl {
}; };
} }
#[cfg( #[cfg(all(
all( de_rc_dst,
de_rc_dst, feature = "rc",
feature = "rc", any(feature = "std", feature = "alloc")
any(feature = "std", feature = "alloc") ))]
)
)]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1738,13 +1801,11 @@ box_forwarded_impl! {
Rc Rc
} }
#[cfg( #[cfg(all(
all( de_rc_dst,
de_rc_dst, feature = "rc",
feature = "rc", any(feature = "std", feature = "alloc")
any(feature = "std", feature = "alloc") ))]
)
)]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -2252,10 +2313,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>
+29 -27
View File
@@ -24,8 +24,7 @@
//! //!
//! Additionally, Serde provides a procedural macro called [`serde_derive`] to //! Additionally, Serde provides a procedural macro called [`serde_derive`] to
//! automatically generate [`Deserialize`] implementations for structs and enums //! automatically generate [`Deserialize`] implementations for structs and enums
//! in your program. See the [codegen section of the manual] for how to use //! in your program. See the [derive section of the manual] for how to use this.
//! this.
//! //!
//! In rare cases it may be necessary to implement [`Deserialize`] manually for //! In rare cases it may be necessary to implement [`Deserialize`] manually for
//! some type in your program. See the [Implementing `Deserialize`] section of //! some type in your program. See the [Implementing `Deserialize`] section of
@@ -117,7 +116,7 @@
//! [`serde_derive`]: https://crates.io/crates/serde_derive //! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json //! [`serde_json`]: https://github.com/serde-rs/json
//! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml //! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml
//! [codegen section of the manual]: https://serde.rs/codegen.html //! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats //! [data formats]: https://serde.rs/#data-formats
use lib::*; use lib::*;
@@ -498,7 +497,7 @@ impl<'a> Display for Expected + 'a {
/// ///
/// Additionally, Serde provides a procedural macro called `serde_derive` to /// Additionally, Serde provides a procedural macro called `serde_derive` to
/// automatically generate `Deserialize` implementations for structs and enums /// automatically generate `Deserialize` implementations for structs and enums
/// in your program. See the [codegen section of the manual][codegen] for how to /// in your program. See the [derive section of the manual][derive] for how to
/// use this. /// use this.
/// ///
/// In rare cases it may be necessary to implement `Deserialize` manually for /// In rare cases it may be necessary to implement `Deserialize` manually for
@@ -511,7 +510,7 @@ impl<'a> Display for Expected + 'a {
/// provides an implementation of `Deserialize` for it. /// provides an implementation of `Deserialize` for it.
/// ///
/// [de]: https://docs.serde.rs/serde/de/index.html /// [de]: https://docs.serde.rs/serde/de/index.html
/// [codegen]: https://serde.rs/codegen.html /// [derive]: https://serde.rs/derive.html
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html /// [impl-deserialize]: https://serde.rs/impl-deserialize.html
/// ///
/// # Lifetime /// # Lifetime
@@ -660,7 +659,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// use std::fmt; /// use std::fmt;
/// use std::marker::PhantomData; /// use std::marker::PhantomData;
/// ///
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess}; /// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
/// ///
/// // A DeserializeSeed implementation that uses stateful deserialization to /// // A DeserializeSeed implementation that uses stateful deserialization to
/// // append array elements onto the end of an existing vector. The preexisting /// // append array elements onto the end of an existing vector. The preexisting
@@ -807,16 +806,16 @@ where
/// - When serializing, all strings are handled equally. When deserializing, /// - When serializing, all strings are handled equally. When deserializing,
/// there are three flavors of strings: transient, owned, and borrowed. /// there are three flavors of strings: transient, owned, and borrowed.
/// - **byte array** - \[u8\] /// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be transient, /// - Similar to strings, during deserialization byte arrays can be
/// owned, or borrowed. /// transient, owned, or borrowed.
/// - **option** /// - **option**
/// - Either none or some value. /// - Either none or some value.
/// - **unit** /// - **unit**
/// - The type of `()` in Rust. It represents an anonymous value containing no /// - The type of `()` in Rust. It represents an anonymous value containing
/// data. /// no data.
/// - **unit_struct** /// - **unit_struct**
/// - For example `struct Unit` or `PhantomData<T>`. It represents a named value /// - For example `struct Unit` or `PhantomData<T>`. It represents a named
/// containing no data. /// value containing no data.
/// - **unit_variant** /// - **unit_variant**
/// - For example the `E::A` and `E::B` in `enum E { A, B }`. /// - For example the `E::A` and `E::B` in `enum E { A, B }`.
/// - **newtype_struct** /// - **newtype_struct**
@@ -824,14 +823,15 @@ where
/// - **newtype_variant** /// - **newtype_variant**
/// - For example the `E::N` in `enum E { N(u8) }`. /// - For example the `E::N` in `enum E { N(u8) }`.
/// - **seq** /// - **seq**
/// - A variably sized heterogeneous sequence of values, for example `Vec<T>` or /// - A variably sized heterogeneous sequence of values, for example `Vec<T>`
/// `HashSet<T>`. When serializing, the length may or may not be known before /// or `HashSet<T>`. When serializing, the length may or may not be known
/// iterating through all the data. When deserializing, the length is determined /// before iterating through all the data. When deserializing, the length
/// by looking at the serialized data. /// is determined by looking at the serialized data.
/// - **tuple** /// - **tuple**
/// - A statically sized heterogeneous sequence of values for which the length /// - A statically sized heterogeneous sequence of values for which the
/// will be known at deserialization time without looking at the serialized /// length will be known at deserialization time without looking at the
/// data, for example `(u8,)` or `(String, u64, Vec<T>)` or `[u64; 10]`. /// serialized data, for example `(u8,)` or `(String, u64, Vec<T>)` or
/// `[u64; 10]`.
/// - **tuple_struct** /// - **tuple_struct**
/// - A named tuple, for example `struct Rgb(u8, u8, u8)`. /// - A named tuple, for example `struct Rgb(u8, u8, u8)`.
/// - **tuple_variant** /// - **tuple_variant**
@@ -839,9 +839,9 @@ where
/// - **map** /// - **map**
/// - A heterogeneous key-value pairing, for example `BTreeMap<K, V>`. /// - A heterogeneous key-value pairing, for example `BTreeMap<K, V>`.
/// - **struct** /// - **struct**
/// - A heterogeneous key-value pairing in which the keys are strings and will be /// - A heterogeneous key-value pairing in which the keys are strings and
/// known at deserialization time without looking at the serialized data, for /// will be known at deserialization time without looking at the serialized
/// example `struct S { r: u8, g: u8, b: u8 }`. /// data, for example `struct S { r: u8, g: u8, b: u8 }`.
/// - **struct_variant** /// - **struct_variant**
/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
/// ///
@@ -856,7 +856,8 @@ where
/// type it sees in the input. JSON uses this approach when deserializing /// type it sees in the input. JSON uses this approach when deserializing
/// `serde_json::Value` which is an enum that can represent any JSON /// `serde_json::Value` which is an enum that can represent any JSON
/// document. Without knowing what is in a JSON document, we can deserialize /// document. Without knowing what is in a JSON document, we can deserialize
/// it to `serde_json::Value` by going through `Deserializer::deserialize_any`. /// it to `serde_json::Value` by going through
/// `Deserializer::deserialize_any`.
/// ///
/// 2. The various `deserialize_*` methods. Non-self-describing formats like /// 2. The various `deserialize_*` methods. Non-self-describing formats like
/// Bincode need to be told what is in the input in order to deserialize it. /// Bincode need to be told what is in the input in order to deserialize it.
@@ -866,10 +867,11 @@ where
/// `Deserializer::deserialize_any`. /// `Deserializer::deserialize_any`.
/// ///
/// When implementing `Deserialize`, you should avoid relying on /// When implementing `Deserialize`, you should avoid relying on
/// `Deserializer::deserialize_any` unless you need to be told by the Deserializer /// `Deserializer::deserialize_any` unless you need to be told by the
/// what type is in the input. Know that relying on `Deserializer::deserialize_any` /// Deserializer what type is in the input. Know that relying on
/// means your data type will be able to deserialize from self-describing /// `Deserializer::deserialize_any` means your data type will be able to
/// formats only, ruling out Bincode and many others. /// deserialize from self-describing formats only, ruling out Bincode and many
/// others.
/// ///
/// [Serde data model]: https://serde.rs/data-model.html /// [Serde data model]: https://serde.rs/data-model.html
/// ///
+3 -2
View File
@@ -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.71")] #![doc(html_root_url = "https://docs.rs/serde/1.0.80")]
// 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(
@@ -196,7 +197,7 @@ mod lib {
pub use std::rc::{Rc, Weak as RcWeak}; pub use std::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::{Arc, Weak as ArcWeak}; pub use alloc::sync::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "rc", feature = "std"))] #[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::{Arc, Weak as ArcWeak}; pub use std::sync::{Arc, Weak as ArcWeak};
+14 -14
View File
@@ -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
@@ -832,8 +832,8 @@ mod content {
} }
impl<'de, T> TaggedContentVisitor<'de, T> { impl<'de, T> TaggedContentVisitor<'de, T> {
/// Visitor for the content of an internally tagged enum with the given tag /// Visitor for the content of an internally tagged enum with the given
/// name. /// tag name.
pub fn new(name: &'static str) -> Self { pub fn new(name: &'static str) -> Self {
TaggedContentVisitor { TaggedContentVisitor {
tag_name: name, tag_name: name,
@@ -1075,8 +1075,8 @@ mod content {
Ok(value) Ok(value)
} }
/// Used when deserializing an internally tagged enum because the content will /// Used when deserializing an internally tagged enum because the content
/// be used exactly once. /// will be used exactly once.
impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E> impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
@@ -1790,8 +1790,8 @@ mod content {
Ok(value) Ok(value)
} }
/// Used when deserializing an untagged enum because the content may need to be /// Used when deserializing an untagged enum because the content may need
/// used more than once. /// to be used more than once.
impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E> impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
@@ -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>
+8 -1
View File
@@ -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,
+44 -36
View File
@@ -24,8 +24,7 @@
//! //!
//! Additionally, Serde provides a procedural macro called [`serde_derive`] to //! Additionally, Serde provides a procedural macro called [`serde_derive`] to
//! automatically generate [`Serialize`] implementations for structs and enums //! automatically generate [`Serialize`] implementations for structs and enums
//! in your program. See the [codegen section of the manual] for how to use //! in your program. See the [derive section of the manual] for how to use this.
//! this.
//! //!
//! In rare cases it may be necessary to implement [`Serialize`] manually for //! In rare cases it may be necessary to implement [`Serialize`] manually for
//! some type in your program. See the [Implementing `Serialize`] section of the //! some type in your program. See the [Implementing `Serialize`] section of the
@@ -112,7 +111,7 @@
//! [`serde_derive`]: https://crates.io/crates/serde_derive //! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json //! [`serde_json`]: https://github.com/serde-rs/json
//! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml //! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml
//! [codegen section of the manual]: https://serde.rs/codegen.html //! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats //! [data formats]: https://serde.rs/#data-formats
use lib::*; use lib::*;
@@ -196,7 +195,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// ///
/// Additionally, Serde provides a procedural macro called [`serde_derive`] to /// Additionally, Serde provides a procedural macro called [`serde_derive`] to
/// automatically generate `Serialize` implementations for structs and enums in /// automatically generate `Serialize` implementations for structs and enums in
/// your program. See the [codegen section of the manual] for how to use this. /// your program. See the [derive section of the manual] for how to use this.
/// ///
/// In rare cases it may be necessary to implement `Serialize` manually for some /// In rare cases it may be necessary to implement `Serialize` manually for some
/// type in your program. See the [Implementing `Serialize`] section of the /// type in your program. See the [Implementing `Serialize`] section of the
@@ -211,7 +210,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html /// [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map /// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
/// [`serde_derive`]: https://crates.io/crates/serde_derive /// [`serde_derive`]: https://crates.io/crates/serde_derive
/// [codegen section of the manual]: https://serde.rs/codegen.html /// [derive section of the manual]: https://serde.rs/derive.html
/// [ser]: https://docs.serde.rs/serde/ser/index.html /// [ser]: https://docs.serde.rs/serde/ser/index.html
pub trait Serialize { pub trait Serialize {
/// Serialize this value into the given Serde serializer. /// Serialize this value into the given Serde serializer.
@@ -220,7 +219,7 @@ pub trait Serialize {
/// information about how to implement this method. /// information about how to implement this method.
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct}; /// use serde::ser::{Serialize, SerializeStruct, Serializer};
/// ///
/// struct Person { /// struct Person {
/// name: String, /// name: String,
@@ -274,16 +273,16 @@ pub trait Serialize {
/// - When serializing, all strings are handled equally. When deserializing, /// - When serializing, all strings are handled equally. When deserializing,
/// there are three flavors of strings: transient, owned, and borrowed. /// there are three flavors of strings: transient, owned, and borrowed.
/// - **byte array** - \[u8\] /// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be transient, /// - Similar to strings, during deserialization byte arrays can be
/// owned, or borrowed. /// transient, owned, or borrowed.
/// - **option** /// - **option**
/// - Either none or some value. /// - Either none or some value.
/// - **unit** /// - **unit**
/// - The type of `()` in Rust. It represents an anonymous value containing no /// - The type of `()` in Rust. It represents an anonymous value containing
/// data. /// no data.
/// - **unit_struct** /// - **unit_struct**
/// - For example `struct Unit` or `PhantomData<T>`. It represents a named value /// - For example `struct Unit` or `PhantomData<T>`. It represents a named
/// containing no data. /// value containing no data.
/// - **unit_variant** /// - **unit_variant**
/// - For example the `E::A` and `E::B` in `enum E { A, B }`. /// - For example the `E::A` and `E::B` in `enum E { A, B }`.
/// - **newtype_struct** /// - **newtype_struct**
@@ -291,14 +290,15 @@ pub trait Serialize {
/// - **newtype_variant** /// - **newtype_variant**
/// - For example the `E::N` in `enum E { N(u8) }`. /// - For example the `E::N` in `enum E { N(u8) }`.
/// - **seq** /// - **seq**
/// - A variably sized heterogeneous sequence of values, for example `Vec<T>` or /// - A variably sized heterogeneous sequence of values, for example
/// `HashSet<T>`. When serializing, the length may or may not be known before /// `Vec<T>` or `HashSet<T>`. When serializing, the length may or may not
/// iterating through all the data. When deserializing, the length is determined /// be known before iterating through all the data. When deserializing,
/// by looking at the serialized data. /// the length is determined by looking at the serialized data.
/// - **tuple** /// - **tuple**
/// - A statically sized heterogeneous sequence of values for which the length /// - A statically sized heterogeneous sequence of values for which the
/// will be known at deserialization time without looking at the serialized /// length will be known at deserialization time without looking at the
/// data, for example `(u8,)` or `(String, u64, Vec<T>)` or `[u64; 10]`. /// serialized data, for example `(u8,)` or `(String, u64, Vec<T>)` or
/// `[u64; 10]`.
/// - **tuple_struct** /// - **tuple_struct**
/// - A named tuple, for example `struct Rgb(u8, u8, u8)`. /// - A named tuple, for example `struct Rgb(u8, u8, u8)`.
/// - **tuple_variant** /// - **tuple_variant**
@@ -306,9 +306,9 @@ pub trait Serialize {
/// - **map** /// - **map**
/// - A heterogeneous key-value pairing, for example `BTreeMap<K, V>`. /// - A heterogeneous key-value pairing, for example `BTreeMap<K, V>`.
/// - **struct** /// - **struct**
/// - A heterogeneous key-value pairing in which the keys are strings and will be /// - A heterogeneous key-value pairing in which the keys are strings and
/// known at deserialization time without looking at the serialized data, for /// will be known at deserialization time without looking at the
/// example `struct S { r: u8, g: u8, b: u8 }`. /// serialized data, for example `struct S { r: u8, g: u8, b: u8 }`.
/// - **struct_variant** /// - **struct_variant**
/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
/// ///
@@ -1111,7 +1111,7 @@ pub trait Serializer: Sized {
/// ``` /// ```
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// use serde::ser::{Serialize, SerializeTuple, Serializer};
/// ///
/// const VRAM_SIZE: usize = 386; /// const VRAM_SIZE: usize = 386;
/// struct Vram([u16; VRAM_SIZE]); /// struct Vram([u16; VRAM_SIZE]);
@@ -1139,7 +1139,7 @@ pub trait Serializer: Sized {
/// of data fields that will be serialized. /// of data fields that will be serialized.
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct}; /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
/// ///
/// struct Rgb(u8, u8, u8); /// struct Rgb(u8, u8, u8);
/// ///
@@ -1171,7 +1171,7 @@ pub trait Serializer: Sized {
/// and the `len` is the number of data fields that will be serialized. /// and the `len` is the number of data fields that will be serialized.
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant}; /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
/// ///
/// enum E { /// enum E {
/// T(u8, u8), /// T(u8, u8),
@@ -1265,7 +1265,7 @@ pub trait Serializer: Sized {
/// data fields that will be serialized. /// data fields that will be serialized.
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct}; /// use serde::ser::{Serialize, SerializeStruct, Serializer};
/// ///
/// struct Rgb { /// struct Rgb {
/// r: u8, /// r: u8,
@@ -1301,10 +1301,10 @@ pub trait Serializer: Sized {
/// and the `len` is the number of data fields that will be serialized. /// and the `len` is the number of data fields that will be serialized.
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStructVariant}; /// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
/// ///
/// enum E { /// enum E {
/// S { r: u8, g: u8, b: u8 } /// S { r: u8, g: u8, b: u8 },
/// } /// }
/// ///
/// impl Serialize for E { /// impl Serialize for E {
@@ -1313,7 +1313,11 @@ pub trait Serializer: Sized {
/// S: Serializer, /// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::S { ref r, ref g, ref b } => { /// E::S {
/// ref r,
/// ref g,
/// ref b,
/// } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?; /// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?; /// sv.serialize_field("g", g)?;
@@ -1376,8 +1380,8 @@ pub trait Serializer: Sized {
/// method. /// method.
/// ///
/// ```rust /// ```rust
/// use std::collections::BTreeSet;
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// use std::collections::BTreeSet;
/// ///
/// struct MapToUnit { /// struct MapToUnit {
/// keys: BTreeSet<i32>, /// keys: BTreeSet<i32>,
@@ -1705,7 +1709,7 @@ pub trait SerializeTuple {
/// # Example use /// # Example use
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct}; /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
/// ///
/// struct Rgb(u8, u8, u8); /// struct Rgb(u8, u8, u8);
/// ///
@@ -1750,7 +1754,7 @@ pub trait SerializeTupleStruct {
/// # Example use /// # Example use
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant}; /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
/// ///
/// enum E { /// enum E {
/// T(u8, u8), /// T(u8, u8),
@@ -1919,7 +1923,7 @@ pub trait SerializeMap {
/// # Example use /// # Example use
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct}; /// use serde::ser::{Serialize, SerializeStruct, Serializer};
/// ///
/// struct Rgb { /// struct Rgb {
/// r: u8, /// r: u8,
@@ -1979,10 +1983,10 @@ pub trait SerializeStruct {
/// # Example use /// # Example use
/// ///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStructVariant}; /// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
/// ///
/// enum E { /// enum E {
/// S { r: u8, g: u8, b: u8 } /// S { r: u8, g: u8, b: u8 },
/// } /// }
/// ///
/// impl Serialize for E { /// impl Serialize for E {
@@ -1991,7 +1995,11 @@ pub trait SerializeStruct {
/// S: Serializer, /// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::S { ref r, ref g, ref b } => { /// E::S {
/// ref r,
/// ref g,
/// ref b,
/// } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?; /// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?; /// sv.serialize_field("g", g)?;
+5 -4
View File
@@ -1,18 +1,19 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.71" # remember to update html_root_url version = "1.0.80" # 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)]"
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html" documentation = "https://serde.rs/derive.html"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
readme = "crates-io.md" readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[features] [features]
default = [] default = []
@@ -24,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" }
+2 -1
View File
@@ -90,7 +90,8 @@ pub fn with_where_predicates_from_variants(
// Puts the given bound on any generic type parameters that are used in fields // Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true. // for which filter returns true.
// //
// For example, the following struct needs the bound `A: Serialize, B: Serialize`. // For example, the following struct needs the bound `A: Serialize, B:
// Serialize`.
// //
// struct S<'b, A, B: 'b, C> { // struct S<'b, A, B: 'b, C> {
// a: A, // a: A,
+31 -8
View File
@@ -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(&params); let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
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, &params)); let body = Stmts(deserialize_body(&cont, &params));
@@ -837,7 +838,8 @@ fn deserialize_newtype_struct(
#[cfg(feature = "deserialize_in_place")] #[cfg(feature = "deserialize_in_place")]
fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> TokenStream { fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> TokenStream {
// We do not generate deserialize_in_place if every field has a deserialize_with. // We do not generate deserialize_in_place if every field has a
// deserialize_with.
assert!(field.attrs.deserialize_with().is_none()); assert!(field.attrs.deserialize_with().is_none());
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -941,8 +943,8 @@ fn deserialize_struct(
quote!(mut __seq) quote!(mut __seq)
}; };
// untagged struct variants do not get a visit_seq method. The same applies to structs that // untagged struct variants do not get a visit_seq method. The same applies to
// only have a map representation. // structs that only have a map representation.
let visit_seq = match *untagged { let visit_seq = match *untagged {
Untagged::No if !cattrs.has_flatten() => Some(quote! { Untagged::No if !cattrs.has_flatten() => Some(quote! {
#[inline] #[inline]
@@ -1155,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! {
@@ -1166,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
@@ -1253,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! {
@@ -1264,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
@@ -1322,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! {
@@ -1333,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
@@ -1840,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();
@@ -1848,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 {
@@ -2270,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);
@@ -2290,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);
@@ -2525,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);
@@ -2547,7 +2569,8 @@ fn deserialize_map_in_place(
.map(|(i, field)| (field, field_i(i))) .map(|(i, field)| (field, field_i(i)))
.collect(); .collect();
// For deserialize_in_place, declare booleans for each field that will be deserialized. // For deserialize_in_place, declare booleans for each field that will be
// deserialized.
let let_flags = fields_names let let_flags = fields_names
.iter() .iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing()) .filter(|&&(field, _)| !field.attrs.skip_deserializing())
+18
View File
@@ -6,24 +6,36 @@
// 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.
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
use internals::attr; use internals::attr;
use internals::check; use internals::check;
use internals::{Ctxt, Derive}; use internals::{Ctxt, Derive};
use syn; use syn;
use syn::punctuated::Punctuated; use syn::punctuated::Punctuated;
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
/// parsed into an internal representation.
pub struct Container<'a> { pub struct Container<'a> {
/// The struct or enum name (without generics).
pub ident: syn::Ident, pub ident: syn::Ident,
/// Attributes on the structure, parsed for Serde.
pub attrs: attr::Container, pub attrs: attr::Container,
/// The contents of the struct or enum.
pub data: Data<'a>, pub data: Data<'a>,
/// Any generics on the struct or enum.
pub generics: &'a syn::Generics, pub generics: &'a syn::Generics,
} }
/// The fields of a struct or enum.
///
/// Analagous to `syn::Data`.
pub enum Data<'a> { pub enum Data<'a> {
Enum(Vec<Variant<'a>>), Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>), Struct(Style, Vec<Field<'a>>),
} }
/// A variant of an enum.
pub struct Variant<'a> { pub struct Variant<'a> {
pub ident: syn::Ident, pub ident: syn::Ident,
pub attrs: attr::Variant, pub attrs: attr::Variant,
@@ -31,6 +43,7 @@ pub struct Variant<'a> {
pub fields: Vec<Field<'a>>, pub fields: Vec<Field<'a>>,
} }
/// A field of a struct.
pub struct Field<'a> { pub struct Field<'a> {
pub member: syn::Member, pub member: syn::Member,
pub attrs: attr::Field, pub attrs: attr::Field,
@@ -40,13 +53,18 @@ pub struct Field<'a> {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum Style { pub enum Style {
/// Named fields.
Struct, Struct,
/// Many unnamed fields.
Tuple, Tuple,
/// One unnamed field.
Newtype, Newtype,
/// No fields.
Unit, Unit,
} }
impl<'a> Container<'a> { impl<'a> Container<'a> {
/// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`.
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive) -> Container<'a> { pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive) -> Container<'a> {
let mut attrs = attr::Container::from_ast(cx, item); let mut attrs = attr::Container::from_ast(cx, item);
+29 -25
View File
@@ -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 {
@@ -102,7 +106,7 @@ impl Name {
} }
} }
/// Represents container (e.g. struct) attribute information /// Represents struct or enum attribute information.
pub struct Container { pub struct Container {
name: Name, name: Name,
transparent: bool, transparent: bool,
@@ -272,7 +276,7 @@ impl Container {
} }
} }
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "T: SomeBound")]`
Meta(NameValue(ref m)) if m.ident == "bound" => { Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
@@ -282,7 +286,7 @@ impl Container {
} }
} }
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]` // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]`
Meta(List(ref m)) if m.ident == "bound" => { Meta(List(ref m)) if m.ident == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser); ser_bound.set_opt(ser);
@@ -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(),
@@ -617,7 +621,7 @@ impl Variant {
other.set_true(); other.set_true();
} }
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "T: SomeBound")]`
Meta(NameValue(ref m)) if m.ident == "bound" => { Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
@@ -627,7 +631,7 @@ impl Variant {
} }
} }
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]` // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]`
Meta(List(ref m)) if m.ident == "bound" => { Meta(List(ref m)) if m.ident == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser); ser_bound.set_opt(ser);
@@ -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(),
}; };
@@ -921,7 +925,7 @@ impl Field {
} }
} }
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "T: SomeBound")]`
Meta(NameValue(ref m)) if m.ident == "bound" => { Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
@@ -931,7 +935,7 @@ impl Field {
} }
} }
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]` // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]`
Meta(List(ref m)) if m.ident == "bound" => { Meta(List(ref m)) if m.ident == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser); ser_bound.set_opt(ser);
@@ -989,9 +993,9 @@ impl Field {
} }
} }
// Is skip_deserializing, initialize the field to Default::default() unless a different // Is skip_deserializing, initialize the field to Default::default() unless a
// default is specified by `#[serde(default = "...")]` on ourselves or our container (e.g. // different default is specified by `#[serde(default = "...")]` on
// the struct we are in). // ourselves or our container (e.g. the struct we are in).
if let Default::None = *container_default { if let Default::None = *container_default {
if skip_deserializing.0.value.is_some() { if skip_deserializing.0.value.is_some() {
default.set_if_none(Default::Default); default.set_if_none(Default::Default);
@@ -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()))
} }
+12 -3
View File
@@ -6,6 +6,9 @@
// 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.
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
//! case of the source (e.g. `my-field`, `MY_FIELD`).
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726 // See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
#[allow(deprecated, unused_imports)] #[allow(deprecated, unused_imports)]
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
@@ -14,6 +17,7 @@ use std::str::FromStr;
use self::RenameRule::*; use self::RenameRule::*;
/// The different possible ways to change case of fields in a struct, or variants in an enum.
#[derive(PartialEq)] #[derive(PartialEq)]
pub enum RenameRule { pub enum RenameRule {
/// Don't apply a default rename rule. /// Don't apply a default rename rule.
@@ -22,13 +26,16 @@ pub enum RenameRule {
LowerCase, LowerCase,
/// Rename direct children to "UPPERCASE" style. /// Rename direct children to "UPPERCASE" style.
UPPERCASE, UPPERCASE,
/// Rename direct children to "PascalCase" style, as typically used for enum variants. /// Rename direct children to "PascalCase" style, as typically used for
/// enum variants.
PascalCase, PascalCase,
/// Rename direct children to "camelCase" style. /// Rename direct children to "camelCase" style.
CamelCase, CamelCase,
/// Rename direct children to "snake_case" style, as commonly used for fields. /// Rename direct children to "snake_case" style, as commonly used for
/// fields.
SnakeCase, SnakeCase,
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants. /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly
/// used for constants.
ScreamingSnakeCase, ScreamingSnakeCase,
/// Rename direct children to "kebab-case" style. /// Rename direct children to "kebab-case" style.
KebabCase, KebabCase,
@@ -37,6 +44,7 @@ pub enum RenameRule {
} }
impl RenameRule { impl RenameRule {
/// Apply a renaming rule to an enum variant, returning the version expected in the source.
pub fn apply_to_variant(&self, variant: &str) -> String { pub fn apply_to_variant(&self, variant: &str) -> String {
match *self { match *self {
None | PascalCase => variant.to_owned(), None | PascalCase => variant.to_owned(),
@@ -61,6 +69,7 @@ impl RenameRule {
} }
} }
/// Apply a renaming rule to a struct field, returning the version expected in the source.
pub fn apply_to_field(&self, field: &str) -> String { pub fn apply_to_field(&self, field: &str) -> String {
match *self { match *self {
None | LowerCase | SnakeCase => field.to_owned(), None | LowerCase | SnakeCase => field.to_owned(),
+17 -11
View File
@@ -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");
} }
} }
+12
View File
@@ -10,18 +10,29 @@ use std::cell::RefCell;
use std::fmt::Display; use std::fmt::Display;
use std::thread; use std::thread;
/// A type to collect errors together and format them.
///
/// Dropping this object will cause a panic. It must be consumed using `check`.
///
/// References can be shared since this type uses run-time exclusive mut checking.
#[derive(Default)] #[derive(Default)]
pub struct Ctxt { pub struct Ctxt {
// The contents will be set to `None` during checking. This is so that checking can be
// enforced.
errors: RefCell<Option<Vec<String>>>, errors: RefCell<Option<Vec<String>>>,
} }
impl Ctxt { impl Ctxt {
/// Create a new context object.
///
/// This object contains no errors, but will still trigger a panic if it is not `check`ed.
pub fn new() -> Self { pub fn new() -> Self {
Ctxt { Ctxt {
errors: RefCell::new(Some(Vec::new())), errors: RefCell::new(Some(Vec::new())),
} }
} }
/// Add an error to the context object.
pub fn error<T: Display>(&self, msg: T) { pub fn error<T: Display>(&self, msg: T) {
self.errors self.errors
.borrow_mut() .borrow_mut()
@@ -30,6 +41,7 @@ impl Ctxt {
.push(msg.to_string()); .push(msg.to_string());
} }
/// Consume this object, producing a formatted error string if there are errors.
pub fn check(self) -> Result<(), String> { pub fn check(self) -> Result<(), String> {
let mut errors = self.errors.borrow_mut().take().unwrap(); let mut errors = self.errors.borrow_mut().take().unwrap();
match errors.len() { match errors.len() {
+16 -14
View File
@@ -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.71")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.80")]
#![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()
+5 -1
View File
@@ -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, &params)); let body = Stmts(serialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
+2 -1
View File
@@ -16,7 +16,8 @@ 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" }
appveyor = { repository = "serde-rs/serde" }
+1
View File
@@ -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(
+2 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.71" # remember to update html_root_url version = "1.0.80" # 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"
@@ -20,3 +20,4 @@ serde_derive = { version = "1.0", path = "../serde_derive" }
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
+2 -1
View File
@@ -95,7 +95,8 @@ where
} }
} }
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`. /// Asserts that `value` serializes to the given `tokens`, and then yields
/// `error`.
/// ///
/// ```rust /// ```rust
/// # #[macro_use] /// # #[macro_use]
+2 -7
View File
@@ -19,7 +19,7 @@ pub struct Compact<T: ?Sized>(T);
/// extern crate serde_test; /// extern crate serde_test;
/// ///
/// use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{Configure, Token, assert_tokens}; /// use serde_test::{assert_tokens, Configure, Token};
/// ///
/// #[derive(Debug, PartialEq)] /// #[derive(Debug, PartialEq)]
/// struct Example(u8, u8); /// struct Example(u8, u8);
@@ -67,12 +67,7 @@ pub struct Compact<T: ?Sized>(T);
/// Token::TupleEnd, /// Token::TupleEnd,
/// ], /// ],
/// ); /// );
/// assert_tokens( /// assert_tokens(&Example(1, 0).readable(), &[Token::Str("1.0")]);
/// &Example(1, 0).readable(),
/// &[
/// Token::Str("1.0"),
/// ],
/// );
/// } /// }
/// ``` /// ```
pub trait Configure { pub trait Configure {
+2 -1
View File
@@ -161,7 +161,8 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.71")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.80")]
#![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))]
+2 -1
View File
@@ -11,7 +11,8 @@ use serde::{ser, Serialize};
use error::Error; use error::Error;
use token::Token; use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of tokens. /// A `Serializer` that ensures that a value serializes to a given list of
/// tokens.
#[derive(Debug)] #[derive(Debug)]
pub struct Serializer<'a> { pub struct Serializer<'a> {
tokens: &'a [Token], tokens: &'a [Token],
-1
View File
@@ -9,7 +9,6 @@ unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies] [dev-dependencies]
fnv = "1.0" fnv = "1.0"
proc-macro2 = "0.4"
rustc-serialize = "0.3.16" rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] } serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
+2 -2
View File
@@ -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)]
#![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() {}
+130 -1
View File
@@ -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,
],
);
}
+28 -1
View File
@@ -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(any(target_arch = "asmjs", 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)],
} }
+22 -13
View File
@@ -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.
// These just test that serde_codegen is able to produce code that compiles // These just test that serde_derive is able to produce code that compiles
// successfully when there are a variety of generics and non-(de)serializable // successfully when there are a variety of generics and non-(de)serializable
// types involved. // types involved.
@@ -198,12 +198,10 @@ fn test_gen() {
assert::<WithTraits1<X, X>>(); assert::<WithTraits1<X, X>>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde( #[serde(bound(
bound( serialize = "D: SerializeWith",
serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"
deserialize = "D: DeserializeWith" ))]
)
)]
struct WithTraits2<D, E> { struct WithTraits2<D, E> {
#[serde( #[serde(
serialize_with = "SerializeWith::serialize_with", serialize_with = "SerializeWith::serialize_with",
@@ -240,12 +238,10 @@ fn test_gen() {
assert::<VariantWithTraits1<X, X>>(); assert::<VariantWithTraits1<X, X>>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde( #[serde(bound(
bound( serialize = "D: SerializeWith",
serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"
deserialize = "D: DeserializeWith" ))]
)
)]
enum VariantWithTraits2<D, E> { enum VariantWithTraits2<D, E> {
#[serde( #[serde(
serialize_with = "SerializeWith::serialize_with", serialize_with = "SerializeWith::serialize_with",
@@ -669,6 +665,19 @@ fn test_gen() {
#[serde(deserialize_with = "de_x")] #[serde(deserialize_with = "de_x")]
x: X, x: X,
} }
#[derive(Deserialize)]
#[serde(untagged)]
enum UntaggedWithBorrow<'a> {
Single(#[serde(borrow)] RelObject<'a>),
Many(#[serde(borrow)] Vec<RelObject<'a>>),
}
#[derive(Deserialize)]
struct RelObject<'a> {
ty: &'a str,
id: String,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+1
View File
@@ -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]
+1
View File
@@ -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]
+1
View File
@@ -618,6 +618,7 @@ fn test_enum_skipped() {
); );
} }
#[cfg(not(any(target_arch = "asmjs", 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");
+26
View File
@@ -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;
+1
View File
@@ -26,6 +26,7 @@ fn test_u32_to_enum() {
assert_eq!(E::B, e); assert_eq!(E::B, e);
} }
#[cfg(not(any(target_arch = "asmjs", 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);
+32
View File
@@ -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,
],
);
}
-104
View File
@@ -1,104 +0,0 @@
#!/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
elif [ -n "${APPVEYOR}" ]; then
if [ "${APPVEYOR_RUST_CHANNEL}" = "${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 'rc unstable' -- -Dclippy
cd "$DIR/serde_derive"
cargo clippy -- -Dclippy
cd "$DIR/serde_test"
cargo clippy -- -Dclippy
cd "$DIR/test_suite"
cargo clippy --features unstable -- -Dclippy
cd "$DIR/test_suite/no_std"
cargo clippy -- -Dclippy
else
CHANNEL=nightly
cd "$DIR"
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
channel build --no-default-features --features alloc
channel test --features 'rc unstable'
cd "$DIR/test_suite/deps"
channel build
cd "$DIR/test_suite"
channel test --features unstable
channel build --tests --features proc-macro2/nightly
if [ -z "${APPVEYOR}" ]; then
cd "$DIR/test_suite/no_std"
channel build
fi
CHANNEL=beta
cd "$DIR"
cargo clean
cd "$DIR/serde"
channel build --features rc
cd "$DIR/test_suite"
channel test
CHANNEL=stable
cd "$DIR"
cargo clean
cd "$DIR/serde"
channel build --features rc
channel build --no-default-features
cd "$DIR/serde_test"
channel build
channel test
CHANNEL=1.13.0
cd "$DIR"
cargo clean
cd "$DIR/serde"
channel build --features rc
channel build --no-default-features
cd "$DIR/serde_test"
channel build
CHANNEL=1.15.0
cd "$DIR"
cargo clean
cd "$DIR/serde_derive"
channel build
for CHANNEL in 1.20.0 1.21.0 1.25.0 1.26.0; do
cd "$DIR"
cargo clean
cd "$DIR/serde"
channel build --no-default-features
channel build
done
fi