Compare commits

...

149 Commits

Author SHA1 Message Date
David Tolnay 7407d71417 Release 1.0.61 2018-05-26 10:38:18 -07:00
David Tolnay 9faa11fd9a Update list of impls to show NonZero* stable 2018-05-26 10:37:08 -07:00
David Tolnay 5310bd87ae Remove unneeded core import
This was previously used by the unstable nonzero impls.

    #[cfg(feature = "unstable")]
    use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
2018-05-26 10:37:06 -07:00
David Tolnay 99091d5925 Merge pull request #1285 from dtolnay/rcdst
Stabilize impls for dynamically sized Rc / Arc
2018-05-26 10:36:52 -07:00
David Tolnay 320a059e4b Stabilize impls for dynamically sized Rc / Arc 2018-05-26 10:06:29 -07:00
David Tolnay 8a596951bf Merge pull request #1284 from serde-rs/boxcstr
Stabilize Deserialize for Box<CStr>
2018-05-26 10:06:14 -07:00
David Tolnay 350406e827 Merge pull request #1283 from serde-rs/dep
Specify serde version required by serde_test
2018-05-26 09:53:47 -07:00
David Tolnay 7ec3cac7d6 Stabilize Deserialize for Box<CStr> 2018-05-26 09:48:50 -07:00
David Tolnay ad47bd132b Specify serde version required by serde_test 2018-05-26 09:42:31 -07:00
David Tolnay 1385aac208 Release 1.0.60 2018-05-25 16:05:01 -07:00
David Tolnay b279ebb244 Merge pull request #1263 from serde-rs/integer128
Add Serde impls for i128 and u128
2018-05-25 16:03:08 -07:00
David Tolnay 039ebc63a1 Merge pull request #1278 from SimonSapin/stable-nonzero
Implement for std::num::NonZero* on Rust 1.28+
2018-05-24 09:47:10 -07:00
Simon Sapin defd8853b1 Implement for std::num::NonZero* on Rust 1.28+
… regardless of the `unstable` feature. Fix #1274.
2018-05-24 18:06:24 +02:00
David Tolnay 7d73089b7c Milder and more general wording for feature requests 2018-05-22 21:30:25 -07:00
David Tolnay 06dcbbbaba Format with rustfmt 0.7.0 2018-05-22 21:27:37 -07:00
David Tolnay ad62a6895c Merge pull request #1275 from serde-rs/nightly
Re-enable testing of nightly proc macro
2018-05-22 21:16:10 -07:00
David Tolnay ced57a9e5f Re-enable testing of nightly proc macro 2018-05-22 21:02:45 -07:00
David Tolnay b5f083e6f4 Update test suite to proc-macro2 0.4 2018-05-21 09:23:00 -07:00
David Tolnay 4de20bd48d Release 1.0.59 2018-05-21 03:51:32 -07:00
David Tolnay 9083cf4b00 Test integer128 impls 2018-05-20 22:17:35 -07:00
David Tolnay c17bc6c49c Add 128-bit deserialization in serde_test 2018-05-20 22:17:35 -07:00
David Tolnay e883dc1bba Include i128 and u128 in forward_to_deserialize_any invocations 2018-05-20 22:17:34 -07:00
David Tolnay 412bedc192 Document conditional compilation of 128-bit methods 2018-05-20 22:17:33 -07:00
David Tolnay 4615e428e8 Document serde_if_integer128 macro 2018-05-20 22:17:32 -07:00
David Tolnay 26fec05611 Add Serde impls for i128 and u128 2018-05-20 22:17:31 -07:00
David Tolnay fdb51cc7dc Add integer128 to Serde traits 2018-05-20 22:17:30 -07:00
David Tolnay 5510f758f8 Add a macro conditional on integer128 support 2018-05-20 22:17:29 -07:00
David Tolnay 922fadf7e3 Merge pull request #1270 from serde-rs/transparent
Transparent attribute to specify that representation is the same as its only field
2018-05-20 22:17:07 -07:00
David Tolnay 6bbc415fdf Resolve conflicts between transparent and proc-macro2 upgrade 2018-05-20 21:57:23 -07:00
David Tolnay b13875dd97 Add compile-fail tests for transparent error messages 2018-05-20 21:55:50 -07:00
David Tolnay ac1b25e91d Improve error messages related to transparent 2018-05-20 21:55:48 -07:00
David Tolnay 1335f85213 Test transparent attribute 2018-05-20 21:55:21 -07:00
David Tolnay 0a4d536253 Implement transparent deserialize 2018-05-20 21:55:20 -07:00
David Tolnay 7dba1e303d Implement transparent serialize 2018-05-20 21:55:19 -07:00
David Tolnay 0ea9d73fdf Validate use of serde(transparent) 2018-05-20 21:55:18 -07:00
David Tolnay a64aaeeb3b Parse serde(transparent) container attribute 2018-05-20 21:55:16 -07:00
David Tolnay 320897679b Merge pull request #1273 from serde-rs/up
Update to proc-macro2 0.4
2018-05-20 21:54:07 -07:00
David Tolnay 3d5141a2f1 Update to proc-macro2 0.4 2018-05-20 20:55:14 -07:00
David Tolnay 656ea96c65 Remove reminders about flatten in a sequence 2018-05-20 12:42:40 -07:00
David Tolnay 5302482596 Simplify deserialize_seq_in_place 2018-05-20 12:40:35 -07:00
David Tolnay 7ada27014d Track field index in internal AST 2018-05-20 12:40:28 -07:00
David Tolnay 4fa2a50f62 Format with rustfmt 0.7.0 2018-05-19 17:33:30 -07:00
David Tolnay 0c5f20c148 Release 1.0.58 2018-05-19 17:30:39 -07:00
David Tolnay aa2bbb4704 Merge pull request #1269 from serde-rs/with
Fix generated code for deserializing untagged newtype variant
2018-05-19 17:30:30 -07:00
David Tolnay 16d1265e17 Fix generated code for deserializing untagged newtype variant 2018-05-19 17:20:14 -07:00
David Tolnay f09320b293 Remove unused methods on FromPrimitive trait 2018-05-19 16:29:25 -07:00
David Tolnay 3b4803115b Release 1.0.57 2018-05-18 23:31:33 -07:00
David Tolnay fa5f0f4541 Remove EnumSet from documentation
These impls were removed in Serde 0.9.6.
2018-05-18 21:26:23 -07:00
David Tolnay 4b7f55bd42 Merge pull request #1265 from serde-rs/nonzero
Remove impls for NonZero<T>
2018-05-18 21:16:03 -07:00
David Tolnay 593bcb087d Remove impls for NonZero<T> 2018-05-18 21:06:14 -07:00
David Tolnay f58000cb41 Release 1.0.56 2018-05-18 12:37:06 -07:00
David Tolnay 01b86d5ce4 Merge pull request #1259 from serde-rs/build
Build script that does nothing
2018-05-18 12:35:13 -07:00
David Tolnay c80f9238d7 Link to i128 announcement 2018-05-18 12:34:36 -07:00
David Tolnay 62850bf832 Disable nightly proc-macro build 2018-05-18 12:24:03 -07:00
David Tolnay 9f114548f4 Revert "Use version_check crate instead of handcrafted version parsing"
This reverts commit 8890061f82.
2018-05-18 11:48:05 -07:00
Oliver Schneider 8890061f82 Use version_check crate instead of handcrafted version parsing 2018-05-18 14:41:40 +02:00
David Tolnay 2c05518810 Build script that does nothing
Eventually we will want a build script that enables Serde impls for i128
and u128. As a first step here is a build script that does nothing to
see whether we can roll this out without breaking anyone's workflow,
without having a supported feature at stake in the event that it needs
to be rolled back.
2018-05-15 14:41:38 -07:00
David Tolnay 4aeb0df88f Add a button to clarify any other type of issue is welcome 2018-05-12 11:27:14 -07:00
David Tolnay 6550231a51 Release 1.0.55 2018-05-12 09:47:43 -07:00
David Tolnay ea0012fc5a Support deserializing bytes as the flattened identifier 2018-05-12 09:44:04 -07:00
David Tolnay d6b62b9417 Release 1.0.54 2018-05-11 23:02:37 -07:00
David Tolnay 2ee347c5a5 Merge pull request #1256 from serde-rs/option
Support flattened untagged Options in struct fields
2018-05-11 23:01:37 -07:00
David Tolnay 4305260174 Support flattened untagged Options in struct fields 2018-05-11 22:14:16 -07:00
David Tolnay 35aae92b56 Remove playground feature
These days serde_derive is in the top 100 crates so it gets picked up
without needing this help from serde.
2018-05-11 01:28:20 -07:00
David Tolnay f3f26796c7 Format with rustfmt 0.6.1 2018-05-10 09:11:19 -07:00
David Tolnay d1460e1f0d Release 1.0.53 2018-05-10 08:44:53 -07:00
David Tolnay dfd81323d5 Cfg away a macro used only by flatten 2018-05-10 08:44:26 -07:00
David Tolnay 368961e961 Support deserializing flattened untagged enum 2018-05-10 08:33:47 -07:00
David Tolnay f9c6f0ab62 Release 1.0.52 2018-05-09 13:01:41 -07:00
David Tolnay b2b36e1764 Accept implicitly borrowed data inside of Option 2018-05-08 12:19:09 -07:00
David Tolnay 4ad140ea70 Improve error for struct deserialized from array that is too short 2018-05-08 12:03:35 -07:00
David Tolnay 67777eb585 Account for skip_serializing_if in tuple struct length 2018-05-08 11:49:37 -07:00
David Tolnay b4e51fcc77 Respect skip_serializing in tuple structs and variants 2018-05-08 11:37:52 -07:00
David Tolnay be7fe2a5eb Introduce bound attribute on enum variants 2018-05-08 11:16:10 -07:00
David Tolnay b4076f4577 Release 1.0.51 2018-05-08 10:07:45 -07:00
David Tolnay c4181f46be Respect variant skip attribute in inferred bounds 2018-05-07 21:30:00 -07:00
David Tolnay 8c0efc3d77 Add a variant skip attribute 2018-05-07 21:27:34 -07:00
David Tolnay 7e3efaf6c5 Improve error when a 'de lifetime parameter already exists 2018-05-07 21:15:44 -07:00
David Tolnay 12fe42ed45 Support empty adjacently tagged enum 2018-05-07 21:02:42 -07:00
David Tolnay 7cd4f49c76 Release 1.0.50 2018-05-07 13:51:32 -07:00
David Tolnay ff9c85d47f Merge pull request #1252 from serde-rs/precondition
Detect deserialize on a struct ending in dynamically sized slice
2018-05-07 13:50:48 -07:00
David Tolnay 0025ef9aba Detect deserialize on a struct ending in dynamically sized slice 2018-05-07 11:52:59 -07:00
David Tolnay 536bdd77a0 Release 1.0.49 2018-05-07 11:51:15 -07:00
David Tolnay 6993b983d2 Merge pull request #1251 from serde-rs/weak
Add impls for Weak
2018-05-07 11:50:35 -07:00
David Tolnay 4bfeb05f22 Prefer Self and associated types in de impls 2018-05-07 11:36:41 -07:00
David Tolnay 4687c1b52b Test Weak deserialize impls 2018-05-07 11:23:18 -07:00
David Tolnay a58abae193 Test Weak serialize impls 2018-05-07 11:23:17 -07:00
David Tolnay 0bc9c729b3 Add impls for Weak 2018-05-07 11:23:16 -07:00
David Tolnay dc921892be Eliminate map_or(None, f) 2018-05-07 11:23:04 -07:00
David Tolnay 62557731c3 Enable pedantic clippy lints in serde_derive 2018-05-07 11:03:09 -07:00
David Tolnay ab62cd3b28 Eliminate loop that does not loop 2018-05-07 10:46:54 -07:00
David Tolnay 30824e9f61 Release 1.0.48 2018-05-07 10:22:26 -07:00
David Tolnay eecc0870fc Test for pub(restricted) 2018-05-06 23:22:27 -07:00
David Tolnay 6475e73b05 Less horrible logic for missing fields that unconditionally return error 2018-05-06 22:20:35 -07:00
David Tolnay 697234517d Merge pull request #1249 from serde-rs/empty
Fix adjacently tagged empty tuple variant or struct variant
2018-05-06 22:20:27 -07:00
David Tolnay 3cd9d071c2 Fix adjacently tagged empty tuple variant or struct variant 2018-05-06 21:50:40 -07:00
David Tolnay 9dc05c36f0 Release 1.0.47 2018-05-06 21:39:21 -07:00
David Tolnay 972cc06fed Format the flatten tests using rustfmt 0.6.1 2018-05-06 21:38:41 -07:00
David Tolnay 20013464f8 Merge pull request #1248 from serde-rs/flatten
Support flatten in enums
2018-05-06 21:37:32 -07:00
David Tolnay 2009b4da5f Remove old flatten in enum compile-fail test 2018-05-06 21:26:40 -07:00
David Tolnay 0b72c86a35 Add tests for flatten in enums 2018-05-06 21:23:20 -07:00
David Tolnay 94b857057b Support deserializing enums containing flatten 2018-05-06 20:41:02 -07:00
David Tolnay 979df3427b Support serializing enums containing flatten 2018-05-06 20:14:35 -07:00
David Tolnay 978d64993e Allow flatten attribute in enums 2018-05-06 20:14:28 -07:00
David Tolnay 5098609935 Release 1.0.46 2018-05-06 13:44:55 -07:00
David Tolnay 6374467f02 Merge pull request #1245 from serde-rs/flat
Support deserializing a flattened internally tagged enum
2018-05-06 13:43:44 -07:00
David Tolnay 1f9fc61b98 Merge pull request #1246 from serde-rs/internals
Move derive internals into serde_derive crate
2018-05-05 23:58:41 -07:00
David Tolnay 3859f58d9b Move derive internals into serde_derive crate
We can continue to publish serde_derive_internals independently but
serde_derive no longer has a dependency on it. This improves compile
time of serde_derive by 7%.
2018-05-05 23:46:30 -07:00
David Tolnay aac1c65033 Simplify implementation of flattened internally tagged enum
The fact that the tag entry is consumed was only observable if there is
a later flattened map field, at which point the behavior is already
confusing anyway.

    #[derive(Deserialize)]
    struct Example {
        #[serde(flatten)]
        a: InternallyTagged,
        #[serde(flatten)]
        rest: BTreeMap<String, Value>,
    }

Before this simplification the map would receive all the fields of the
internally tagged enum but not its tag, after it receives all the fields
including the tag.
2018-05-05 22:30:46 -07:00
David Tolnay d8120e19bc Support deserializing a flattened internally tagged enum 2018-05-05 21:52:16 -07:00
David Tolnay ed425b3a6f Clean up indentation in VariantAccess doc 2018-05-05 18:40:28 -07:00
David Tolnay d1297deb36 Format where-clauses in serde docs like rustfmt 2018-05-05 18:33:33 -07:00
David Tolnay f263e3fcec Format serde_derive generated where-clauses 2018-05-05 18:24:16 -07:00
David Tolnay 40479336c1 Format serde_test doc where-clauses in the style of rustfmt 2018-05-05 18:20:26 -07:00
David Tolnay 6ca4dd2c4a Add an issue suggestion for documentation improvements 2018-05-05 10:01:54 -07:00
David Tolnay c04c233838 Generalize the help issue type 2018-05-05 10:00:17 -07:00
David Tolnay 175c638fdc Set up some issue templates 2018-05-05 01:45:24 -07:00
David Tolnay 97eff8e875 Format with rustfmt 0.6.1 2018-05-05 00:56:12 -07:00
David Tolnay 47676cdb49 Clean up references to Ident 2018-05-05 00:45:30 -07:00
David Tolnay 93bddb361e Fix toplevel_ref_arg lint 2018-05-05 00:39:26 -07:00
David Tolnay adb1c9540d Remove a layer of wrapping in deserialize_with untagged newtype variant 2018-05-05 00:25:27 -07:00
David Tolnay 0e1d065402 Format with rustfmt 0.6.1 2018-05-05 00:18:21 -07:00
David Tolnay 8c3b52e308 Remove a layer of wrapping in deserialize_with newtype struct 2018-05-05 00:17:00 -07:00
David Tolnay 3f0d3453d8 Release 1.0.45 2018-05-02 15:18:17 -07:00
David Tolnay b27a27ce22 Merge pull request #1241 from serde-rs/pretend
Pretend remote derives are not dead code
2018-05-02 15:17:19 -07:00
David Tolnay 80c0600657 Merge pull request #1243 from serde-rs/ci
Add a CI build on 1.15.0
2018-05-02 15:17:10 -07:00
David Tolnay 77f9e63661 Add a CI build on 1.15.0 2018-05-02 14:29:51 -07:00
David Tolnay b78f434086 Pretend remote derives are not dead code 2018-05-02 14:23:59 -07:00
David Tolnay 893c0578dd Release 1.0.44 2018-05-01 22:34:27 -07:00
David Tolnay cb2b92f828 Handle flatten + deserialize_with 2018-05-01 22:25:06 -07:00
David Tolnay 47a4ffbd31 Fill in missing fully qualified paths in flatten 2018-05-01 22:24:25 -07:00
David Tolnay d82d1707d6 Format with rustfmt 0.6.0 2018-04-30 01:42:46 -07:00
David Tolnay 89278996c5 Release 1.0.43 2018-04-23 11:23:58 -07:00
David Tolnay ecef937e26 Merge pull request #1234 from serde-rs/newtype
Unpack a layer of NewtypeStruct when content is newtype
2018-04-23 11:23:21 -07:00
David Tolnay bceda5fb18 Unpack a layer of NewtypeStruct when content is newtype 2018-04-23 11:04:42 -07:00
David Tolnay f46a08b04e Merge pull request #1231 from ignatenkobrain/patch-1
derive: bump min version of quote to 0.5.2
2018-04-22 16:48:11 -07:00
Igor Gnatenko f3cb7c7a32 derive: bump min version of quote to 0.5.2
Fixes: https://github.com/serde-rs/serde/issues/1230
2018-04-22 09:22:47 +02:00
David Tolnay af795e2e54 Release 1.0.42 2018-04-21 15:16:10 -07:00
David Tolnay 6aa07fe0d6 Merge pull request #1229 from serde-rs/cold
Mark error construction as cold code
2018-04-21 14:57:11 -07:00
David Tolnay c455720f81 Mark error construction as cold code
This eliminates 12% of the Serde-related code in the Xi release binary
as measured by:

nm -S target/release/xi-core \
    | awk '/serde/{sum += strtonum("0x"$2)} END{print sum}'
2018-04-21 14:41:14 -07:00
David Tolnay b07a208716 Merge pull request #1228 from serde-rs/untagged
Reduce instantiations of Result::map in Deserialize of unit variants
2018-04-21 13:46:36 -07:00
David Tolnay df93fab5fa Reduce instantiations of Result::map in Deserialize of unit variants
This eliminates 110 instantiations of Result::map in Xi and reduces
binary size by 229 kilobytes.
2018-04-21 13:27:17 -07:00
David Tolnay 1a972d2105 Merge pull request #1227 from serde-rs/ser
Improve Serialize of adjacently tagged newtype variants
2018-04-21 12:10:28 -07:00
David Tolnay 6d1807bb4a Improve Serialize of adjacently tagged newtype variants
The existing implementation was unnecessarily complicated.

    struct __AdjacentlyTagged<'__a> {
        data: (&'__a String,),
        phantom: _serde::export::PhantomData<AdjacentlyTagged>,
    }
    impl<'__a> _serde::Serialize for __AdjacentlyTagged<'__a> {
        fn serialize<__S>(
            &self,
            __serializer: __S,
        ) -> _serde::export::Result<__S::Ok, __S::Error>
        where
            __S: _serde::Serializer,
        {
            let (__field0,) = self.data;
            _serde::Serialize::serialize(__field0, __serializer)
        }
    }
    _serde::ser::SerializeStruct::serialize_field(
        &mut __struct,
        "content",
        &__AdjacentlyTagged {
            data: (__field0,),
            phantom: _serde::export::PhantomData::<AdjacentlyTagged>,
        },
    )?;

Instead the new implementation does simply:

    _serde::ser::SerializeStruct::serialize_field(
        &mut __struct,
        "content",
        __field0,
    )?;
2018-04-21 11:41:39 -07:00
David Tolnay b37cf858ce Remove unneeded quote_spanned that uses call_site 2018-04-21 11:33:39 -07:00
David Tolnay 5f8fa33756 Quote's default has changed to call_site 2018-04-21 11:33:38 -07:00
David Tolnay f3f006f411 Merge pull request #1226 from serde-rs/try
More efficient try!() alternative
2018-04-21 11:33:28 -07:00
David Tolnay 607966dcf7 Fix error message type inference in compile-fail/remote/wrong_de.rs 2018-04-21 11:21:13 -07:00
David Tolnay 6a8c39b2aa More efficient try!() alternative 2018-04-21 10:53:13 -07:00
58 changed files with 3252 additions and 1082 deletions
+7
View File
@@ -0,0 +1,7 @@
---
name: Problem
about: Something does not seem right
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Suggestion
about: Share how Serde could support your use case better
---
@@ -0,0 +1,7 @@
---
name: Documentation
about: Certainly there is room for improvement
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Help or discussion
about: This is the right place
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Anything else!
about: Whatever is on your mind
---
+1
View File
@@ -5,6 +5,7 @@ cache: cargo
# run builds for all the trains (and more) # run builds for all the trains (and more)
rust: rust:
- 1.13.0 - 1.13.0
- 1.15.0
- stable - stable
- beta - beta
- nightly - nightly
+3 -7
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.41" # remember to update html_root_url version = "1.0.61" # 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"
@@ -10,7 +10,8 @@ documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"] categories = ["encoding"]
readme = "README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "build.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs"
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -61,8 +62,3 @@ alloc = ["unstable"]
# does not preserve identity and may result in multiple copies of the same data. # does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature. # Be sure that this is what you want before enabling this feature.
rc = [] rc = []
# Get serde_derive picked up by the Integer 32 playground. Not public API.
#
# http://play.integer32.com/
playground = ["serde_derive"]
+60
View File
@@ -0,0 +1,60 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
fn main() {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return,
};
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return;
}
let next = match pieces.next() {
Some(next) => next,
None => return,
};
let minor = match u32::from_str(next) {
Ok(minor) => minor,
Err(_) => return,
};
// 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
if minor >= 20 {
println!("cargo:rustc-cfg=de_boxed_c_str");
}
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
if minor >= 21 {
println!("cargo:rustc-cfg=de_rc_dst");
}
// 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
if minor >= 26 {
println!("cargo:rustc-cfg=integer128");
}
// Non-zero integers stabilized in Rust 1.28:
// https://github.com/rust-lang/rust/pull/50808
if minor >= 28 {
println!("cargo:rustc-cfg=num_nonzero");
}
}
+88 -26
View File
@@ -39,12 +39,10 @@ macro_rules! uint_to {
} }
pub trait FromPrimitive: Sized { pub trait FromPrimitive: Sized {
fn from_isize(n: isize) -> Option<Self>;
fn from_i8(n: i8) -> Option<Self>; fn from_i8(n: i8) -> Option<Self>;
fn from_i16(n: i16) -> Option<Self>; fn from_i16(n: i16) -> Option<Self>;
fn from_i32(n: i32) -> Option<Self>; fn from_i32(n: i32) -> Option<Self>;
fn from_i64(n: i64) -> Option<Self>; fn from_i64(n: i64) -> Option<Self>;
fn from_usize(n: usize) -> Option<Self>;
fn from_u8(n: u8) -> Option<Self>; fn from_u8(n: u8) -> Option<Self>;
fn from_u16(n: u16) -> Option<Self>; fn from_u16(n: u16) -> Option<Self>;
fn from_u32(n: u32) -> Option<Self>; fn from_u32(n: u32) -> Option<Self>;
@@ -54,10 +52,6 @@ pub trait FromPrimitive: Sized {
macro_rules! impl_from_primitive_for_int { macro_rules! impl_from_primitive_for_int {
($t:ident) => { ($t:ident) => {
impl FromPrimitive for $t { impl FromPrimitive for $t {
#[inline]
fn from_isize(n: isize) -> Option<Self> {
int_to_int!($t, n)
}
#[inline] #[inline]
fn from_i8(n: i8) -> Option<Self> { fn from_i8(n: i8) -> Option<Self> {
int_to_int!($t, n) int_to_int!($t, n)
@@ -75,10 +69,6 @@ macro_rules! impl_from_primitive_for_int {
int_to_int!($t, n) int_to_int!($t, n)
} }
#[inline] #[inline]
fn from_usize(n: usize) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> { fn from_u8(n: u8) -> Option<Self> {
uint_to!($t, n) uint_to!($t, n)
} }
@@ -101,10 +91,6 @@ macro_rules! impl_from_primitive_for_int {
macro_rules! impl_from_primitive_for_uint { macro_rules! impl_from_primitive_for_uint {
($t:ident) => { ($t:ident) => {
impl FromPrimitive for $t { impl FromPrimitive for $t {
#[inline]
fn from_isize(n: isize) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline] #[inline]
fn from_i8(n: i8) -> Option<Self> { fn from_i8(n: i8) -> Option<Self> {
int_to_uint!($t, n) int_to_uint!($t, n)
@@ -122,10 +108,6 @@ macro_rules! impl_from_primitive_for_uint {
int_to_uint!($t, n) int_to_uint!($t, n)
} }
#[inline] #[inline]
fn from_usize(n: usize) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> { fn from_u8(n: u8) -> Option<Self> {
uint_to!($t, n) uint_to!($t, n)
} }
@@ -148,10 +130,6 @@ macro_rules! impl_from_primitive_for_uint {
macro_rules! impl_from_primitive_for_float { macro_rules! impl_from_primitive_for_float {
($t:ident) => { ($t:ident) => {
impl FromPrimitive for $t { impl FromPrimitive for $t {
#[inline]
fn from_isize(n: isize) -> Option<Self> {
Some(n as Self)
}
#[inline] #[inline]
fn from_i8(n: i8) -> Option<Self> { fn from_i8(n: i8) -> Option<Self> {
Some(n as Self) Some(n as Self)
@@ -169,10 +147,6 @@ macro_rules! impl_from_primitive_for_float {
Some(n as Self) Some(n as Self)
} }
#[inline] #[inline]
fn from_usize(n: usize) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> { fn from_u8(n: u8) -> Option<Self> {
Some(n as Self) Some(n as Self)
} }
@@ -204,3 +178,91 @@ impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64); impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32); impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64); impl_from_primitive_for_float!(f64);
serde_if_integer128! {
impl FromPrimitive for i128 {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as i128)
}
}
impl FromPrimitive for u128 {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as u128)
}
}
}
+10 -5
View File
@@ -45,7 +45,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// } /// }
/// ///
/// impl<'de, T> Visitor<'de> for NthElement<T> /// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// type Value = T; /// type Value = T;
/// ///
@@ -54,7 +55,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// } /// }
/// ///
/// 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>
/// where A: SeqAccess<'de> /// where
/// A: SeqAccess<'de>,
/// { /// {
/// // Skip over the first `n` elements. /// // Skip over the first `n` elements.
/// for i in 0..self.n { /// for i in 0..self.n {
@@ -82,19 +84,22 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// } /// }
/// ///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T> /// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// type Value = T; /// type Value = T;
/// ///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> /// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// deserializer.deserialize_seq(self) /// deserializer.deserialize_seq(self)
/// } /// }
/// } /// }
/// ///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> /// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de> /// # where
/// # D: Deserializer<'de>,
/// # { /// # {
/// // Deserialize only the sequence element at index 3 from this deserializer. /// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and /// // The element at index 3 is required to be a string. Elements before and
+216 -100
View File
@@ -8,8 +8,9 @@
use lib::*; use lib::*;
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, use de::{
Visitor}; Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::MapAccess; use de::MapAccess;
@@ -31,7 +32,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
formatter.write_str("unit") formatter.write_str("unit")
} }
fn visit_unit<E>(self) -> Result<(), E> fn visit_unit<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -40,7 +41,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
} }
impl<'de> Deserialize<'de> for () { impl<'de> Deserialize<'de> for () {
fn deserialize<D>(deserializer: D) -> Result<(), D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -59,7 +60,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
formatter.write_str("a boolean") formatter.write_str("a boolean")
} }
fn visit_bool<E>(self, v: bool) -> Result<bool, E> fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -68,7 +69,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
} }
impl<'de> Deserialize<'de> for bool { impl<'de> Deserialize<'de> for bool {
fn deserialize<D>(deserializer: D) -> Result<bool, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -109,7 +110,7 @@ macro_rules! impl_deserialize_num {
($ty:ident, $method:ident, $($visit:ident),*) => { ($ty:ident, $method:ident, $($visit:ident),*) => {
impl<'de> Deserialize<'de> for $ty { impl<'de> Deserialize<'de> for $ty {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -165,6 +166,92 @@ impl_deserialize_num!(usize, deserialize_u64, integer);
impl_deserialize_num!(f32, deserialize_f32, integer, float); impl_deserialize_num!(f32, deserialize_f32, integer, float);
impl_deserialize_num!(f64, deserialize_f64, integer, float); impl_deserialize_num!(f64, deserialize_f64, integer, float);
serde_if_integer128! {
impl<'de> Deserialize<'de> for i128 {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PrimitiveVisitor;
impl<'de> Visitor<'de> for PrimitiveVisitor {
type Value = i128;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("i128")
}
impl_deserialize_num!(integer i128);
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v)
}
#[inline]
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
if v <= i128::max_value() as u128 {
Ok(v as i128)
} else {
Err(Error::invalid_value(Unexpected::Other("u128"), &self))
}
}
}
deserializer.deserialize_i128(PrimitiveVisitor)
}
}
impl<'de> Deserialize<'de> for u128 {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PrimitiveVisitor;
impl<'de> Visitor<'de> for PrimitiveVisitor {
type Value = u128;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("u128")
}
impl_deserialize_num!(integer u128);
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
if v >= 0 {
Ok(v as u128)
} else {
Err(Error::invalid_value(Unexpected::Other("i128"), &self))
}
}
#[inline]
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v)
}
}
deserializer.deserialize_u128(PrimitiveVisitor)
}
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct CharVisitor; struct CharVisitor;
@@ -177,7 +264,7 @@ impl<'de> Visitor<'de> for CharVisitor {
} }
#[inline] #[inline]
fn visit_char<E>(self, v: char) -> Result<char, E> fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -185,7 +272,7 @@ impl<'de> Visitor<'de> for CharVisitor {
} }
#[inline] #[inline]
fn visit_str<E>(self, v: &str) -> Result<char, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -199,7 +286,7 @@ impl<'de> Visitor<'de> for CharVisitor {
impl<'de> Deserialize<'de> for char { impl<'de> Deserialize<'de> for char {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<char, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -222,21 +309,21 @@ impl<'de> Visitor<'de> for StringVisitor {
formatter.write_str("a string") formatter.write_str("a string")
} }
fn visit_str<E>(self, v: &str) -> Result<String, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
Ok(v.to_owned()) Ok(v.to_owned())
} }
fn visit_string<E>(self, v: String) -> Result<String, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
Ok(v) Ok(v)
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<String, E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -246,7 +333,7 @@ impl<'de> Visitor<'de> for StringVisitor {
} }
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<String, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -268,7 +355,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
formatter.write_str("a string") formatter.write_str("a string")
} }
fn visit_str<E>(self, v: &str) -> Result<(), E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -277,7 +364,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
Ok(()) Ok(())
} }
fn visit_string<E>(self, v: String) -> Result<(), E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -285,7 +372,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
Ok(()) Ok(())
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -299,7 +386,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
} }
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -318,7 +405,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for String { impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -416,7 +503,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
formatter.write_str("byte array") formatter.write_str("byte array")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<CString, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -430,28 +517,28 @@ impl<'de> Visitor<'de> for CStringVisitor {
CString::new(values).map_err(Error::custom) CString::new(values).map_err(Error::custom)
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<CString, E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
CString::new(v).map_err(Error::custom) CString::new(v).map_err(Error::custom)
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<CString, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
CString::new(v).map_err(Error::custom) CString::new(v).map_err(Error::custom)
} }
fn visit_str<E>(self, v: &str) -> Result<CString, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
CString::new(v).map_err(Error::custom) CString::new(v).map_err(Error::custom)
} }
fn visit_string<E>(self, v: String) -> Result<CString, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -461,7 +548,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de> Deserialize<'de> for CString { impl<'de> Deserialize<'de> for CString {
fn deserialize<D>(deserializer: D) -> Result<CString, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -486,7 +573,7 @@ macro_rules! forwarded_impl {
} }
} }
#[cfg(all(feature = "std", feature = "unstable"))] #[cfg(all(feature = "std", de_boxed_c_str))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str); forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -506,7 +593,7 @@ where
} }
#[inline] #[inline]
fn visit_unit<E>(self) -> Result<Option<T>, E> fn visit_unit<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -514,7 +601,7 @@ where
} }
#[inline] #[inline]
fn visit_none<E>(self) -> Result<Option<T>, E> fn visit_none<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -522,19 +609,27 @@ where
} }
#[inline] #[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Option<T>, D::Error> fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
T::deserialize(deserializer).map(Some) T::deserialize(deserializer).map(Some)
} }
#[doc(hidden)]
fn __private_visit_untagged_option<D>(self, deserializer: D) -> Result<Self::Value, ()>
where
D: Deserializer<'de>,
{
Ok(T::deserialize(deserializer).ok())
}
} }
impl<'de, T> Deserialize<'de> for Option<T> impl<'de, T> Deserialize<'de> for Option<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Option<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -564,7 +659,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
} }
#[inline] #[inline]
fn visit_unit<E>(self) -> Result<PhantomData<T>, E> fn visit_unit<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -573,7 +668,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
} }
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> { impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -658,7 +753,7 @@ macro_rules! seq_impl {
} }
#[inline] #[inline]
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error> fn visit_seq<A>(mut self, mut $access: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -770,7 +865,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
} }
#[inline] #[inline]
fn visit_seq<A>(self, _: A) -> Result<[T; 0], A::Error> fn visit_seq<A>(self, _: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -780,7 +875,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
// Does not require T: Deserialize<'de>. // Does not require T: Deserialize<'de>.
impl<'de, T> Deserialize<'de> for [T; 0] { impl<'de, T> Deserialize<'de> for [T; 0] {
fn deserialize<D>(deserializer: D) -> Result<[T; 0], D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -802,7 +897,7 @@ macro_rules! array_impls {
} }
#[inline] #[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -828,7 +923,7 @@ macro_rules! array_impls {
} }
#[inline] #[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -850,7 +945,7 @@ macro_rules! array_impls {
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -910,7 +1005,7 @@ macro_rules! tuple_impls {
$( $(
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -927,7 +1022,7 @@ macro_rules! tuple_impls {
#[inline] #[inline]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -961,7 +1056,7 @@ macro_rules! tuple_impls {
#[inline] #[inline]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1330,14 +1425,14 @@ impl<'de> Visitor<'de> for PathBufVisitor {
formatter.write_str("path string") formatter.write_str("path string")
} }
fn visit_str<E>(self, v: &str) -> Result<PathBuf, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
Ok(From::from(v)) Ok(From::from(v))
} }
fn visit_string<E>(self, v: String) -> Result<PathBuf, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1347,7 +1442,7 @@ impl<'de> Visitor<'de> for PathBufVisitor {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de> Deserialize<'de> for PathBuf { impl<'de> Deserialize<'de> for PathBuf {
fn deserialize<D>(deserializer: D) -> Result<PathBuf, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1380,7 +1475,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
} }
#[cfg(unix)] #[cfg(unix)]
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
@@ -1395,14 +1490,15 @@ impl<'de> Visitor<'de> for OsStringVisitor {
} }
#[cfg(windows)] #[cfg(windows)]
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
use std::os::windows::ffi::OsStringExt; use std::os::windows::ffi::OsStringExt;
match try!(data.variant()) { match try!(data.variant()) {
(OsStringKind::Windows, v) => v.newtype_variant::<Vec<u16>>() (OsStringKind::Windows, v) => v
.newtype_variant::<Vec<u16>>()
.map(|vec| OsString::from_wide(&vec)), .map(|vec| OsString::from_wide(&vec)),
(OsStringKind::Unix, _) => Err(Error::custom( (OsStringKind::Unix, _) => Err(Error::custom(
"cannot deserialize Unix OS string on Windows", "cannot deserialize Unix OS string on Windows",
@@ -1413,7 +1509,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
#[cfg(all(feature = "std", any(unix, windows)))] #[cfg(all(feature = "std", any(unix, windows)))]
impl<'de> Deserialize<'de> for OsString { impl<'de> Deserialize<'de> for OsString {
fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1432,7 +1528,7 @@ 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(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(not(de_rc_dst), feature = "rc", 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.
/// ///
@@ -1444,7 +1540,7 @@ forwarded_impl! {
(T), Arc<T>, Arc::new (T), Arc<T>, Arc::new
} }
#[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(not(de_rc_dst), feature = "rc", 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.
/// ///
@@ -1463,7 +1559,7 @@ where
T::Owned: Deserialize<'de>, T::Owned: Deserialize<'de>,
{ {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<Cow<'a, T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1473,7 +1569,45 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] /// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
Ok(RcWeak::new())
}
}
/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
Ok(ArcWeak::new())
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
( (
$(#[doc = $doc:tt])* $(#[doc = $doc:tt])*
@@ -1494,7 +1628,7 @@ macro_rules! box_forwarded_impl {
}; };
} }
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(de_rc_dst, feature = "rc", 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.
/// ///
@@ -1506,7 +1640,7 @@ box_forwarded_impl! {
Rc Rc
} }
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(de_rc_dst, feature = "rc", 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.
/// ///
@@ -1524,7 +1658,7 @@ impl<'de, T> Deserialize<'de> for Cell<T>
where where
T: Deserialize<'de> + Copy, T: Deserialize<'de> + Copy,
{ {
fn deserialize<D>(deserializer: D) -> Result<Cell<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1566,7 +1700,7 @@ impl<'de> Deserialize<'de> for Duration {
}; };
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1579,7 +1713,7 @@ impl<'de> Deserialize<'de> for Duration {
formatter.write_str("`secs` or `nanos`") formatter.write_str("`secs` or `nanos`")
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1590,7 +1724,7 @@ impl<'de> Deserialize<'de> for Duration {
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1618,7 +1752,7 @@ impl<'de> Deserialize<'de> for Duration {
formatter.write_str("struct Duration") formatter.write_str("struct Duration")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1637,7 +1771,7 @@ impl<'de> Deserialize<'de> for Duration {
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
@@ -1691,7 +1825,7 @@ impl<'de> Deserialize<'de> for SystemTime {
}; };
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1704,7 +1838,7 @@ impl<'de> Deserialize<'de> for SystemTime {
formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`") formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`")
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1715,7 +1849,7 @@ impl<'de> Deserialize<'de> for SystemTime {
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1743,7 +1877,7 @@ impl<'de> Deserialize<'de> for SystemTime {
formatter.write_str("struct SystemTime") formatter.write_str("struct SystemTime")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1762,7 +1896,7 @@ impl<'de> Deserialize<'de> for SystemTime {
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
@@ -1835,7 +1969,7 @@ where
}; };
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1848,7 +1982,7 @@ where
formatter.write_str("`start` or `end`") formatter.write_str("`start` or `end`")
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1859,7 +1993,7 @@ where
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1892,7 +2026,7 @@ where
formatter.write_str("struct Range") formatter.write_str("struct Range")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<ops::Range<Idx>, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1911,7 +2045,7 @@ where
Ok(start..end) Ok(start..end)
} }
fn visit_map<A>(self, mut map: A) -> Result<ops::Range<Idx>, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
@@ -1958,35 +2092,17 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
#[allow(deprecated)]
impl<'de, T> Deserialize<'de> for NonZero<T>
where
T: Deserialize<'de> + Zeroable,
{
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
where
D: Deserializer<'de>,
{
let value = try!(Deserialize::deserialize(deserializer));
match NonZero::new(value) {
Some(nonzero) => Ok(nonzero),
None => Err(Error::custom("expected a non-zero value")),
}
}
}
macro_rules! nonzero_integers { macro_rules! nonzero_integers {
( $( $T: ty, )+ ) => { ( $( $T: ident, )+ ) => {
$( $(
#[cfg(feature = "unstable")] #[cfg(num_nonzero)]
impl<'de> Deserialize<'de> for $T { impl<'de> Deserialize<'de> for num::$T {
fn deserialize<D>(deserializer: D) -> Result<$T, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let value = try!(Deserialize::deserialize(deserializer)); let value = try!(Deserialize::deserialize(deserializer));
match <$T>::new(value) { match <num::$T>::new(value) {
Some(nonzero) => Ok(nonzero), Some(nonzero) => Ok(nonzero),
None => Err(Error::custom("expected a non-zero value")), None => Err(Error::custom("expected a non-zero value")),
} }
@@ -2013,7 +2129,7 @@ where
T: Deserialize<'de>, T: Deserialize<'de>,
E: Deserialize<'de>, E: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -2028,7 +2144,7 @@ where
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -2041,7 +2157,7 @@ where
formatter.write_str("`Ok` or `Err`") formatter.write_str("`Ok` or `Err`")
} }
fn visit_u32<E>(self, value: u32) -> Result<Field, E> fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -2055,7 +2171,7 @@ where
} }
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -2066,7 +2182,7 @@ where
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -2100,7 +2216,7 @@ where
formatter.write_str("enum Result") formatter.write_str("enum Result")
} }
fn visit_enum<A>(self, data: A) -> Result<Result<T, E>, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
@@ -2124,7 +2240,7 @@ impl<'de, T> Deserialize<'de> for Wrapping<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
+144 -43
View File
@@ -52,8 +52,8 @@
//! //!
//! - **Primitive types**: //! - **Primitive types**:
//! - bool //! - bool
//! - i8, i16, i32, i64, isize //! - i8, i16, i32, i64, i128, isize
//! - u8, u16, u32, u64, usize //! - u8, u16, u32, u64, u128, usize
//! - f32, f64 //! - f32, f64
//! - char //! - char
//! - **Compound types**: //! - **Compound types**:
@@ -84,7 +84,6 @@
//! - LinkedList\<T\> //! - LinkedList\<T\>
//! - VecDeque\<T\> //! - VecDeque\<T\>
//! - Vec\<T\> //! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **Zero-copy types**: //! - **Zero-copy types**:
//! - &str //! - &str
//! - &[u8] //! - &[u8]
@@ -98,8 +97,7 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - NonZero\<T\> (unstable, deprecated) //! - num::NonZero*
//! - num::NonZero* (unstable)
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -172,7 +170,8 @@ macro_rules! declare_error_trait {
/// ///
/// impl<'de> Deserialize<'de> for IpAddr { /// impl<'de> Deserialize<'de> for IpAddr {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> /// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// let s = try!(String::deserialize(deserializer)); /// let s = try!(String::deserialize(deserializer));
/// s.parse().map_err(de::Error::custom) /// s.parse().map_err(de::Error::custom)
@@ -196,6 +195,7 @@ macro_rules! declare_error_trait {
/// For example if we try to deserialize a String out of a JSON file /// For example if we try to deserialize a String out of a JSON file
/// containing an integer, the unexpected type is the integer and the /// containing an integer, the unexpected type is the integer and the
/// expected type is the string. /// expected type is the string.
#[cold]
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self { fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
} }
@@ -213,6 +213,7 @@ macro_rules! declare_error_trait {
/// For example if we try to deserialize a String out of some binary data /// For example if we try to deserialize a String out of some binary data
/// that is not valid UTF-8, the unexpected value is the bytes and the /// that is not valid UTF-8, the unexpected value is the bytes and the
/// expected value is a string. /// expected value is a string.
#[cold]
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self { fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp)) Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
} }
@@ -226,12 +227,14 @@ macro_rules! declare_error_trait {
/// The `exp` argument provides information about what data was being /// The `exp` argument provides information about what data was being
/// expected. For example `exp` might say that a tuple of size 6 was /// expected. For example `exp` might say that a tuple of size 6 was
/// expected. /// expected.
#[cold]
fn invalid_length(len: usize, exp: &Expected) -> Self { fn invalid_length(len: usize, exp: &Expected) -> Self {
Error::custom(format_args!("invalid length {}, expected {}", len, exp)) Error::custom(format_args!("invalid length {}, expected {}", len, exp))
} }
/// Raised when a `Deserialize` enum type received a variant with an /// Raised when a `Deserialize` enum type received a variant with an
/// unrecognized name. /// unrecognized name.
#[cold]
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() { if expected.is_empty() {
Error::custom(format_args!("unknown variant `{}`, there are no variants", Error::custom(format_args!("unknown variant `{}`, there are no variants",
@@ -245,6 +248,7 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type received a field with an /// Raised when a `Deserialize` struct type received a field with an
/// unrecognized name. /// unrecognized name.
#[cold]
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() { if expected.is_empty() {
Error::custom(format_args!("unknown field `{}`, there are no fields", Error::custom(format_args!("unknown field `{}`, there are no fields",
@@ -259,12 +263,14 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type expected to receive a required /// Raised when a `Deserialize` struct type expected to receive a required
/// field with a particular name but that field was not present in the /// field with a particular name but that field was not present in the
/// input. /// input.
#[cold]
fn missing_field(field: &'static str) -> Self { fn missing_field(field: &'static str) -> Self {
Error::custom(format_args!("missing field `{}`", field)) Error::custom(format_args!("missing field `{}`", field))
} }
/// Raised when a `Deserialize` struct type received more than one of the /// Raised when a `Deserialize` struct type received more than one of the
/// same field. /// same field.
#[cold]
fn duplicate_field(field: &'static str) -> Self { fn duplicate_field(field: &'static str) -> Self {
Error::custom(format_args!("duplicate field `{}`", field)) Error::custom(format_args!("duplicate field `{}`", field))
} }
@@ -299,7 +305,8 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// # } /// # }
/// # /// #
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> /// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
/// where E: de::Error /// where
/// E: de::Error,
/// { /// {
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self)) /// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
/// } /// }
@@ -423,7 +430,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # } /// # }
/// # /// #
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> /// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
/// where E: de::Error /// where
/// E: de::Error,
/// { /// {
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self)) /// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
/// } /// }
@@ -436,7 +444,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # use serde::de::{self, Unexpected}; /// # use serde::de::{self, Unexpected};
/// # /// #
/// # fn example<E>() -> Result<(), E> /// # fn example<E>() -> Result<(), E>
/// # where E: de::Error /// # where
/// # E: de::Error,
/// # { /// # {
/// # let v = true; /// # let v = true;
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); /// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
@@ -550,11 +559,13 @@ pub trait Deserialize<'de>: Sized {
/// # /// #
/// # trait Ignore { /// # trait Ignore {
/// fn from_str<'a, T>(s: &'a str) -> Result<T> /// fn from_str<'a, T>(s: &'a str) -> Result<T>
/// where T: Deserialize<'a>; /// where
/// T: Deserialize<'a>;
/// ///
/// fn from_reader<R, T>(rdr: R) -> Result<T> /// fn from_reader<R, T>(rdr: R) -> Result<T>
/// where R: Read, /// where
/// T: DeserializeOwned; /// R: Read,
/// T: DeserializeOwned;
/// # } /// # }
/// ``` /// ```
pub trait DeserializeOwned: for<'de> Deserialize<'de> {} pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
@@ -630,7 +641,8 @@ where
/// struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>); /// struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);
/// ///
/// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T> /// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// // The return type of the `deserialize` method. This implementation /// // The return type of the `deserialize` method. This implementation
/// // appends onto an existing vector but does not create any new data /// // appends onto an existing vector but does not create any new data
@@ -638,14 +650,16 @@ where
/// type Value = (); /// type Value = ();
/// ///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> /// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// // Visitor implementation that will walk an inner array of the JSON /// // Visitor implementation that will walk an inner array of the JSON
/// // input. /// // input.
/// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>); /// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
/// ///
/// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T> /// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// type Value = (); /// type Value = ();
/// ///
@@ -654,7 +668,8 @@ where
/// } /// }
/// ///
/// fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error> /// fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
/// where A: SeqAccess<'de> /// where
/// A: SeqAccess<'de>,
/// { /// {
/// // Visit each element in the inner array and push it onto /// // Visit each element in the inner array and push it onto
/// // the existing vector. /// // the existing vector.
@@ -673,7 +688,8 @@ where
/// struct FlattenedVecVisitor<T>(PhantomData<T>); /// struct FlattenedVecVisitor<T>(PhantomData<T>);
/// ///
/// impl<'de, T> Visitor<'de> for FlattenedVecVisitor<T> /// impl<'de, T> Visitor<'de> for FlattenedVecVisitor<T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// // This Visitor constructs a single Vec<T> to hold the flattened /// // This Visitor constructs a single Vec<T> to hold the flattened
/// // contents of the inner arrays. /// // contents of the inner arrays.
@@ -684,7 +700,8 @@ where
/// } /// }
/// ///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error> /// fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
/// where A: SeqAccess<'de> /// where
/// A: SeqAccess<'de>,
/// { /// {
/// // Create a single Vec to hold the flattened contents. /// // Create a single Vec to hold the flattened contents.
/// let mut vec = Vec::new(); /// let mut vec = Vec::new();
@@ -700,7 +717,8 @@ where
/// } /// }
/// ///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> /// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de> /// # where
/// # D: Deserializer<'de>,
/// # { /// # {
/// let visitor = FlattenedVecVisitor(PhantomData); /// let visitor = FlattenedVecVisitor(PhantomData);
/// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?; /// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?;
@@ -739,7 +757,7 @@ where
/// Serde. /// Serde.
/// ///
/// The role of this trait is to define the deserialization half of the Serde /// The role of this trait is to define the deserialization half of the Serde
/// data model, which is a way to categorize every Rust data type into one of 27 /// data model, which is a way to categorize every Rust data type into one of 29
/// possible types. Each method of the `Serializer` trait corresponds to one of /// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model. /// the types of the data model.
/// ///
@@ -749,10 +767,10 @@ where
/// ///
/// The types that make up the Serde data model are: /// The types that make up the Serde data model are:
/// ///
/// - **12 primitive types** /// - **14 primitive types**
/// - bool /// - bool
/// - i8, i16, i32, i64 /// - i8, i16, i32, i64, i128
/// - u8, u16, u32, u64 /// - u8, u16, u32, u64, u128
/// - f32, f64 /// - f32, f64
/// - char /// - char
/// - **string** /// - **string**
@@ -866,6 +884,20 @@ pub trait Deserializer<'de>: Sized {
where where
V: Visitor<'de>; V: Visitor<'de>;
serde_if_integer128! {
/// Hint that the `Deserialize` type is expecting an `i128` value.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>
{
let _ = visitor;
Err(Error::custom("i128 is not supported"))
}
}
/// Hint that the `Deserialize` type is expecting a `u8` value. /// Hint that the `Deserialize` type is expecting a `u8` value.
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
@@ -886,6 +918,20 @@ pub trait Deserializer<'de>: Sized {
where where
V: Visitor<'de>; V: Visitor<'de>;
serde_if_integer128! {
/// Hint that the `Deserialize` type is expecting an `u128` value.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>
{
let _ = visitor;
Err(Error::custom("u128 is not supported"))
}
}
/// Hint that the `Deserialize` type is expecting a `f32` value. /// Hint that the `Deserialize` type is expecting a `f32` value.
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
@@ -1085,7 +1131,8 @@ pub trait Deserializer<'de>: Sized {
/// ///
/// impl<'de> Deserialize<'de> for Timestamp { /// impl<'de> Deserialize<'de> for Timestamp {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> /// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// if deserializer.is_human_readable() { /// if deserializer.is_human_readable() {
/// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z". /// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z".
@@ -1136,7 +1183,8 @@ pub trait Deserializer<'de>: Sized {
/// } /// }
/// ///
/// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> /// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
/// where E: de::Error /// where
/// E: de::Error,
/// { /// {
/// if s.len() >= self.min { /// if s.len() >= self.min {
/// Ok(s.to_owned()) /// Ok(s.to_owned())
@@ -1230,6 +1278,20 @@ pub trait Visitor<'de>: Sized {
Err(Error::invalid_type(Unexpected::Signed(v), &self)) Err(Error::invalid_type(Unexpected::Signed(v), &self))
} }
serde_if_integer128! {
/// The input contains a `i128`.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default implementation fails with a type error.
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Other("i128"), &self))
}
}
/// The input contains a `u8`. /// The input contains a `u8`.
/// ///
/// The default implementation forwards to [`visit_u64`]. /// The default implementation forwards to [`visit_u64`].
@@ -1276,6 +1338,20 @@ pub trait Visitor<'de>: Sized {
Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
} }
serde_if_integer128! {
/// The input contains a `u128`.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default implementation fails with a type error.
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Other("u128"), &self))
}
}
/// The input contains an `f32`. /// The input contains an `f32`.
/// ///
/// The default implementation forwards to [`visit_f64`]. /// The default implementation forwards to [`visit_f64`].
@@ -1507,6 +1583,15 @@ pub trait Visitor<'de>: Sized {
let _ = data; let _ = data;
Err(Error::invalid_type(Unexpected::Enum, &self)) Err(Error::invalid_type(Unexpected::Enum, &self))
} }
// Used when deserializing a flattened Option field. Not public API.
#[doc(hidden)]
fn __private_visit_untagged_option<D>(self, _: D) -> Result<Self::Value, ()>
where
D: Deserializer<'de>,
{
Err(())
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1816,15 +1901,18 @@ pub trait VariantAccess<'de>: Sized {
/// } /// }
/// # /// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error> /// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de> /// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error> /// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error> /// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # } /// # }
/// ``` /// ```
@@ -1851,7 +1939,8 @@ pub trait VariantAccess<'de>: Sized {
/// # } /// # }
/// # /// #
/// fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error> /// fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
/// where T: DeserializeSeed<'de> /// where
/// T: DeserializeSeed<'de>,
/// { /// {
/// // What the data actually contained; suppose it is a unit variant. /// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant; /// let unexp = Unexpected::UnitVariant;
@@ -1859,11 +1948,13 @@ pub trait VariantAccess<'de>: Sized {
/// } /// }
/// # /// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error> /// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error> /// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # } /// # }
/// ``` /// ```
@@ -1904,13 +1995,17 @@ pub trait VariantAccess<'de>: Sized {
/// # } /// # }
/// # /// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error> /// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de> /// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// fn tuple_variant<V>(self, /// fn tuple_variant<V>(
/// _len: usize, /// self,
/// _visitor: V) -> Result<V::Value, Self::Error> /// _len: usize,
/// where V: Visitor<'de> /// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// { /// {
/// // What the data actually contained; suppose it is a unit variant. /// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant; /// let unexp = Unexpected::UnitVariant;
@@ -1918,7 +2013,8 @@ pub trait VariantAccess<'de>: Sized {
/// } /// }
/// # /// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error> /// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # } /// # }
/// ``` /// ```
@@ -1946,17 +2042,22 @@ pub trait VariantAccess<'de>: Sized {
/// # } /// # }
/// # /// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error> /// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de> /// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error> /// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// fn struct_variant<V>(self, /// fn struct_variant<V>(
/// _fields: &'static [&'static str], /// self,
/// _visitor: V) -> Result<V::Value, Self::Error> /// _fields: &'static [&'static str],
/// where V: Visitor<'de> /// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// { /// {
/// // What the data actually contained; suppose it is a unit variant. /// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant; /// let unexp = Unexpected::UnitVariant;
+42 -39
View File
@@ -58,6 +58,7 @@ type ErrorImpl = ();
impl de::Error for Error { impl de::Error for Error {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[cold]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -68,6 +69,7 @@ impl de::Error for Error {
} }
#[cfg(not(any(feature = "std", feature = "alloc")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
#[cold]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -78,6 +80,7 @@ impl de::Error for Error {
} }
impl ser::Error for Error { impl ser::Error for Error {
#[cold]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -133,9 +136,9 @@ where
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct
struct enum identifier ignored_any map struct enum identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -186,9 +189,9 @@ macro_rules! primitive_deserializer {
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str
byte_buf option unit unit_struct newtype_struct seq tuple string bytes byte_buf option unit unit_struct newtype_struct seq
tuple_struct map struct enum identifier ignored_any tuple tuple_struct map struct enum identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -243,9 +246,9 @@ where
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -336,9 +339,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -405,9 +408,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -480,9 +483,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -559,9 +562,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -615,9 +618,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any enum tuple_struct map struct identifier ignored_any enum
} }
} }
@@ -685,9 +688,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -800,9 +803,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -914,9 +917,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct tuple_struct map struct bytes byte_buf option unit unit_struct newtype_struct tuple_struct map
enum identifier ignored_any struct enum identifier ignored_any
} }
} }
@@ -1056,9 +1059,9 @@ where
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct tuple_struct map struct bytes byte_buf option unit unit_struct newtype_struct tuple_struct map
enum identifier ignored_any struct enum identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -1204,9 +1207,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
+3
View File
@@ -16,6 +16,9 @@ pub use lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy; pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::Vec;
mod string { mod string {
use lib::*; use lib::*;
+86
View File
@@ -0,0 +1,86 @@
/// Conditional compilation depending on whether Serde is built with support for
/// 128-bit integers.
///
/// Data formats that wish to support Rust compiler versions older than 1.26 may
/// place the i128 / u128 methods of their Serializer and Deserializer behind
/// this macro.
///
/// Data formats that require a minimum Rust compiler version of at least 1.26
/// do not need to bother with this macro and may assume support for 128-bit
/// integers.
///
/// ```rust
/// #[macro_use]
/// extern crate serde;
///
/// use serde::Serializer;
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
///
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
///
/// /* ... */
///
/// serde_if_integer128! {
/// fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
///
/// fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
/// }
/// #
/// # __serialize_unimplemented! {
/// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant seq
/// # tuple tuple_struct tuple_variant map struct struct_variant
/// # }
/// }
/// #
/// # fn main() {}
/// ```
///
/// When Serde is built with support for 128-bit integers, this macro expands
/// transparently into just the input tokens.
///
/// ```rust
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {
/// $($tt)*
/// };
/// }
/// ```
///
/// When built without support for 128-bit integers, this macro expands to
/// nothing.
///
/// ```rust
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {};
/// }
/// ```
#[cfg(integer128)]
#[macro_export]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {
$($tt)*
};
}
#[cfg(not(integer128))]
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {};
}
+10 -17
View File
@@ -79,14 +79,14 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 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.41")] #![doc(html_root_url = "https://docs.rs/serde/1.0.61")]
// 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
// discussion of these features please refer to this issue: // discussion of these features please refer to this issue:
// //
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))] #![cfg_attr(feature = "unstable", feature(specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Whitelisted clippy lints
@@ -130,9 +130,6 @@
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(all(feature = "unstable", feature = "std"))]
extern crate core;
/// A facade around all the types we need from the `std`, `core`, and `alloc` /// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every /// crates. This avoids elaborate import wrangling having to happen in every
/// module. /// module.
@@ -144,7 +141,7 @@ mod lib {
pub use std::*; pub use std::*;
} }
pub use self::core::{cmp, iter, mem, ops, slice, str}; pub use self::core::{cmp, iter, mem, num, ops, slice, str};
pub use self::core::{f32, f64}; pub use self::core::{f32, f64};
pub use self::core::{i16, i32, i64, i8, isize}; pub use self::core::{i16, i32, i64, i8, isize};
pub use self::core::{u16, u32, u64, u8, usize}; pub use self::core::{u16, u32, u64, u8, usize};
@@ -179,14 +176,14 @@ mod lib {
pub use std::boxed::Box; pub use std::boxed::Box;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc; pub use alloc::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "std"))] #[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc; 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; pub use alloc::arc::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "rc", feature = "std"))] #[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc; pub use std::sync::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
@@ -212,13 +209,6 @@ mod lib {
pub use std::sync::{Mutex, RwLock}; pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "unstable")]
#[allow(deprecated)]
pub use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "unstable")]
pub use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -226,6 +216,9 @@ mod lib {
#[macro_use] #[macro_use]
mod macros; mod macros;
#[macro_use]
mod integer128;
pub mod de; pub mod de;
pub mod ser; pub mod ser;
+25 -11
View File
@@ -31,21 +31,23 @@
/// # type Error = value::Error; /// # type Error = value::Error;
/// # /// #
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error> /// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { /// # {
/// # unimplemented!() /// # unimplemented!()
/// # } /// # }
/// # /// #
/// #[inline] /// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de> /// where
/// V: Visitor<'de>,
/// { /// {
/// self.deserialize_any(visitor) /// self.deserialize_any(visitor)
/// } /// }
/// # /// #
/// # forward_to_deserialize_any! { /// # forward_to_deserialize_any! {
/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes /// # i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// # byte_buf option unit unit_struct newtype_struct seq tuple /// # bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any /// # tuple_struct map struct enum identifier ignored_any
/// # } /// # }
/// # } /// # }
@@ -69,7 +71,8 @@
/// # type Error = value::Error; /// # type Error = value::Error;
/// # /// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de> /// where
/// V: Visitor<'de>,
/// { /// {
/// /* ... */ /// /* ... */
/// # let _ = visitor; /// # let _ = visitor;
@@ -77,8 +80,8 @@
/// } /// }
/// ///
/// forward_to_deserialize_any! { /// forward_to_deserialize_any! {
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes /// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// byte_buf option unit unit_struct newtype_struct seq tuple /// bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct map struct enum identifier ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// } /// }
@@ -105,16 +108,17 @@
/// # type Error = value::Error; /// # type Error = value::Error;
/// # /// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error> /// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q> /// # where
/// # W: Visitor<'q>,
/// # { /// # {
/// # unimplemented!() /// # unimplemented!()
/// # } /// # }
/// # /// #
/// forward_to_deserialize_any! { /// forward_to_deserialize_any! {
/// <W: Visitor<'q>> /// <W: Visitor<'q>>
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes /// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct /// bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// map struct enum identifier ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// # } /// # }
/// # /// #
@@ -170,6 +174,11 @@ macro_rules! forward_to_deserialize_any_helper {
(i64<$l:tt, $v:ident>) => { (i64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()} forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
}; };
(i128<$l:tt, $v:ident>) => {
serde_if_integer128! {
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
}
};
(u8<$l:tt, $v:ident>) => { (u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()} forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
}; };
@@ -182,6 +191,11 @@ macro_rules! forward_to_deserialize_any_helper {
(u64<$l:tt, $v:ident>) => { (u64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()} forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
}; };
(u128<$l:tt, $v:ident>) => {
serde_if_integer128! {
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
}
};
(f32<$l:tt, $v:ident>) => { (f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()} forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
}; };
+159 -40
View File
@@ -14,10 +14,11 @@ use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Vi
use de::{MapAccess, Unexpected}; use de::{MapAccess, Unexpected};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer, pub use self::content::{
InternallyTaggedUnitVisitor, TagContentOtherField, Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer,
TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor, TagContentOtherField, TagContentOtherFieldVisitor,
TaggedContentVisitor, UntaggedUnitVisitor}; TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
};
/// If the missing field is of type `Option<T>` then treat is as `None`, /// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error. /// otherwise it is an error.
@@ -49,9 +50,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map bytes byte_buf unit unit_struct newtype_struct seq tuple
struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -229,8 +230,10 @@ mod content {
use lib::*; use lib::*;
use super::size_hint; use super::size_hint;
use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, MapAccess, use de::{
SeqAccess, Unexpected, Visitor}; self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, 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
/// deserializing untagged enums and internally tagged enums. /// deserializing untagged enums and internally tagged enums.
@@ -273,10 +276,13 @@ mod content {
match *self { match *self {
Content::Str(x) => Some(x), Content::Str(x) => Some(x),
Content::String(ref x) => Some(x), Content::String(ref x) => Some(x),
Content::Bytes(x) => str::from_utf8(x).ok(),
Content::ByteBuf(ref x) => str::from_utf8(x).ok(),
_ => None, _ => None,
} }
} }
#[cold]
fn unexpected(&self) -> Unexpected { fn unexpected(&self) -> Unexpected {
match *self { match *self {
Content::Bool(b) => Unexpected::Bool(b), Content::Bool(b) => Unexpected::Bool(b),
@@ -1309,7 +1315,10 @@ mod content {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
visitor.visit_newtype_struct(self) match self.content {
Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)),
_ => visitor.visit_newtype_struct(self),
}
} }
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -1416,6 +1425,8 @@ mod content {
match self.content { match self.content {
Content::String(v) => visitor.visit_string(v), Content::String(v) => visitor.visit_string(v),
Content::Str(v) => visitor.visit_borrowed_str(v), Content::Str(v) => visitor.visit_borrowed_str(v),
Content::ByteBuf(v) => visitor.visit_byte_buf(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@@ -1607,8 +1618,8 @@ mod content {
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -1705,8 +1716,8 @@ mod content {
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -2000,7 +2011,12 @@ mod content {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
visitor.visit_newtype_struct(self) match *self.content {
Content::Newtype(ref v) => {
visitor.visit_newtype_struct(ContentRefDeserializer::new(v))
}
_ => visitor.visit_newtype_struct(self),
}
} }
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -2111,6 +2127,8 @@ mod content {
match *self.content { match *self.content {
Content::String(ref v) => visitor.visit_str(v), Content::String(ref v) => visitor.visit_str(v),
Content::Str(v) => visitor.visit_borrowed_str(v), Content::Str(v) => visitor.visit_borrowed_str(v),
Content::ByteBuf(ref v) => visitor.visit_bytes(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@@ -2288,8 +2306,8 @@ mod content {
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -2305,7 +2323,8 @@ mod content {
T: de::DeserializeSeed<'de>, T: de::DeserializeSeed<'de>,
{ {
match self.iter.next() { match self.iter.next() {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)) Some(value) => seed
.deserialize(ContentRefDeserializer::new(value))
.map(Some), .map(Some),
None => Ok(None), None => Ok(None),
} }
@@ -2387,8 +2406,8 @@ mod content {
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -2559,9 +2578,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -2598,9 +2617,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -2628,6 +2647,30 @@ pub struct FlatMapDeserializer<'a, 'de: 'a, E>(
pub PhantomData<E>, pub PhantomData<E>,
); );
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> FlatMapDeserializer<'a, 'de, E>
where
E: Error,
{
fn deserialize_other<V>() -> Result<V, E> {
Err(Error::custom("can only flatten structs and maps"))
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! forward_to_deserialize_other {
($($func:ident ( $($arg:ty),* ))*) => {
$(
fn $func<V>(self, $(_: $arg,)* _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
Self::deserialize_other()
}
)*
}
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E> impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E>
where where
@@ -2635,11 +2678,15 @@ where
{ {
type Error = E; type Error = E;
fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
Err(Error::custom("can only flatten structs and maps")) visitor.visit_map(FlatInternallyTaggedAccess {
iter: self.0.iter_mut(),
pending: None,
_marker: PhantomData,
})
} }
fn deserialize_enum<V>( fn deserialize_enum<V>(
@@ -2698,10 +2745,40 @@ where
visitor.visit_newtype_struct(self) visitor.visit_newtype_struct(self)
} }
forward_to_deserialize_any! { fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes where
byte_buf option unit unit_struct seq tuple tuple_struct identifier V: Visitor<'de>,
ignored_any {
match visitor.__private_visit_untagged_option(self) {
Ok(value) => Ok(value),
Err(()) => Self::deserialize_other(),
}
}
forward_to_deserialize_other! {
deserialize_bool()
deserialize_i8()
deserialize_i16()
deserialize_i32()
deserialize_i64()
deserialize_u8()
deserialize_u16()
deserialize_u32()
deserialize_u64()
deserialize_f32()
deserialize_f64()
deserialize_char()
deserialize_str()
deserialize_string()
deserialize_bytes()
deserialize_byte_buf()
deserialize_unit()
deserialize_unit_struct(&'static str)
deserialize_seq()
deserialize_tuple(usize)
deserialize_tuple_struct(&'static str, usize)
deserialize_identifier()
deserialize_ignored_any()
} }
} }
@@ -2745,14 +2822,13 @@ where
// about. In case we do not know which fields we want, we take them all. // about. In case we do not know which fields we want, we take them all.
let use_item = match *item { let use_item = match *item {
None => false, None => false,
Some((ref c, _)) => { Some((ref c, _)) => c.as_str().map_or(self.fields.is_none(), |key| {
c.as_str() match self.fields {
.map_or(self.fields.is_none(), |key| match self.fields { None => true,
None => true, Some(fields) if fields.contains(&key) => true,
Some(fields) if fields.contains(&key) => true, _ => false,
_ => false, }
}) }),
}
}; };
if use_item { if use_item {
@@ -2774,3 +2850,46 @@ where
} }
} }
} }
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatInternallyTaggedAccess<'a, 'de: 'a, E> {
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
pending: Option<&'a Content<'de>>,
_marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> MapAccess<'de> for FlatInternallyTaggedAccess<'a, 'de, E>
where
E: Error,
{
type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.iter.next() {
Some(item) => {
// Do not take(), instead borrow this entry. The internally tagged
// enum does its own buffering so we can't tell whether this entry
// is going to be consumed. Borrowing here leaves the entry
// available for later flattened fields.
let (ref key, ref content) = *item.as_ref().unwrap();
self.pending = Some(content);
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.pending.take() {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
None => panic!("value is missing"),
}
}
}
+8 -6
View File
@@ -11,8 +11,9 @@ use lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer}; use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{Content, ContentSerializer, SerializeStructVariantAsMapValue, use self::content::{
SerializeTupleVariantAsMapValue}; Content, ContentSerializer, SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue,
};
/// Used to check that serde(getter) attributes return the expected type. /// Used to check that serde(getter) attributes return the expected type.
/// Not public API. /// Not public API.
@@ -946,7 +947,8 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let key = self.key let key = self
.key
.take() .take()
.expect("serialize_value called before serialize_key"); .expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = try!(value.serialize(ContentSerializer::<E>::new()));
@@ -1121,14 +1123,14 @@ where
} }
fn serialize_none(self) -> Result<Self::Ok, Self::Error> { fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional)) Ok(())
} }
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error> fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where where
T: Serialize, T: Serialize,
{ {
Err(self.bad_type(Unsupported::Optional)) value.serialize(self)
} }
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+34 -8
View File
@@ -44,6 +44,11 @@ primitive_impl!(f32, serialize_f32);
primitive_impl!(f64, serialize_f64); primitive_impl!(f64, serialize_f64);
primitive_impl!(char, serialize_char); primitive_impl!(char, serialize_char);
serde_if_integer128! {
primitive_impl!(i128, serialize_i128);
primitive_impl!(u128, serialize_u128);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
impl Serialize for str { impl Serialize for str {
@@ -374,25 +379,45 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")] /// This impl requires the [`"rc"`] Cargo feature of Serde.
#[allow(deprecated)] ///
impl<T> Serialize for NonZero<T> /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for RcWeak<T>
where where
T: Serialize + Zeroable + Clone, T: Serialize,
{ {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
self.clone().get().serialize(serializer) self.upgrade().serialize(serializer)
} }
} }
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for ArcWeak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.upgrade().serialize(serializer)
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! nonzero_integers { macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => { ( $( $T: ident, )+ ) => {
$( $(
#[cfg(feature = "unstable")] #[cfg(num_nonzero)]
impl Serialize for $T { impl Serialize for num::$T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
@@ -515,7 +540,8 @@ impl Serialize for SystemTime {
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let duration_since_epoch = self.duration_since(UNIX_EPOCH) let duration_since_epoch = self
.duration_since(UNIX_EPOCH)
.expect("SystemTime must be later than UNIX_EPOCH"); .expect("SystemTime must be later than UNIX_EPOCH");
let mut state = try!(serializer.serialize_struct("SystemTime", 2)); let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())); try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
+4 -2
View File
@@ -10,8 +10,10 @@
use lib::*; use lib::*;
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, use ser::{
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant}; self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
};
/// Helper type for implementing a `Serializer` that does not support /// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types. /// serializing one of the compound types.
+179 -67
View File
@@ -48,8 +48,8 @@
//! //!
//! - **Primitive types**: //! - **Primitive types**:
//! - bool //! - bool
//! - i8, i16, i32, i64, isize //! - i8, i16, i32, i64, i128, isize
//! - u8, u16, u32, u64, usize //! - u8, u16, u32, u64, u128, usize
//! - f32, f64 //! - f32, f64
//! - char //! - char
//! - str //! - str
@@ -81,7 +81,6 @@
//! - LinkedList\<T\> //! - LinkedList\<T\>
//! - VecDeque\<T\> //! - VecDeque\<T\>
//! - Vec\<T\> //! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **FFI types**: //! - **FFI types**:
//! - CStr //! - CStr
//! - CString //! - CString
@@ -93,8 +92,7 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - NonZero\<T\> (unstable, deprecated) //! - num::NonZero*
//! - num::NonZero* (unstable)
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -152,7 +150,8 @@ macro_rules! declare_error_trait {
/// ///
/// impl Serialize for Path { /// impl Serialize for Path {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match self.to_str() { /// match self.to_str() {
/// Some(s) => serializer.serialize_str(s), /// Some(s) => serializer.serialize_str(s),
@@ -223,7 +222,8 @@ pub trait Serialize {
/// // This is what #[derive(Serialize)] would generate. /// // This is what #[derive(Serialize)] would generate.
/// impl Serialize for Person { /// impl Serialize for Person {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut s = serializer.serialize_struct("Person", 3)?; /// let mut s = serializer.serialize_struct("Person", 3)?;
/// s.serialize_field("name", &self.name)?; /// s.serialize_field("name", &self.name)?;
@@ -245,7 +245,7 @@ pub trait Serialize {
/// A **data format** that can serialize any data structure supported by Serde. /// A **data format** that can serialize any data structure supported by Serde.
/// ///
/// The role of this trait is to define the serialization half of the Serde data /// The role of this trait is to define the serialization half of the Serde data
/// model, which is a way to categorize every Rust data structure into one of 27 /// model, which is a way to categorize every Rust data structure into one of 29
/// possible types. Each method of the `Serializer` trait corresponds to one of /// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model. /// the types of the data model.
/// ///
@@ -254,10 +254,10 @@ pub trait Serialize {
/// ///
/// The types that make up the Serde data model are: /// The types that make up the Serde data model are:
/// ///
/// - **12 primitive types** /// - **14 primitive types**
/// - bool /// - bool
/// - i8, i16, i32, i64 /// - i8, i16, i32, i64, i128
/// - u8, u16, u32, u64 /// - u8, u16, u32, u64, u128
/// - f32, f64 /// - f32, f64
/// - char /// - char
/// - **string** /// - **string**
@@ -377,7 +377,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for bool { /// impl Serialize for bool {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_bool(*self) /// serializer.serialize_bool(*self)
/// } /// }
@@ -403,7 +404,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i8 { /// impl Serialize for i8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i8(*self) /// serializer.serialize_i8(*self)
/// } /// }
@@ -429,7 +431,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i16 { /// impl Serialize for i16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i16(*self) /// serializer.serialize_i16(*self)
/// } /// }
@@ -455,7 +458,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i32 { /// impl Serialize for i32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i32(*self) /// serializer.serialize_i32(*self)
/// } /// }
@@ -477,7 +481,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i64 { /// impl Serialize for i64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i64(*self) /// serializer.serialize_i64(*self)
/// } /// }
@@ -487,6 +492,37 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>; fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize an `i128` value.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer;
/// #
/// # __private_serialize!();
/// #
/// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i128(*self)
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("i128 is not supported"))
}
}
/// Serialize a `u8` value. /// Serialize a `u8` value.
/// ///
/// If the format does not differentiate between `u8` and `u64`, a /// If the format does not differentiate between `u8` and `u64`, a
@@ -503,7 +539,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u8 { /// impl Serialize for u8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u8(*self) /// serializer.serialize_u8(*self)
/// } /// }
@@ -529,7 +566,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u16 { /// impl Serialize for u16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u16(*self) /// serializer.serialize_u16(*self)
/// } /// }
@@ -555,7 +593,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u32 { /// impl Serialize for u32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u32(*self) /// serializer.serialize_u32(*self)
/// } /// }
@@ -577,7 +616,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u64 { /// impl Serialize for u64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u64(*self) /// serializer.serialize_u64(*self)
/// } /// }
@@ -587,6 +627,37 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>; fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize a `u128` value.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer;
/// #
/// # __private_serialize!();
/// #
/// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u128(*self)
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("u128 is not supported"))
}
}
/// Serialize an `f32` value. /// Serialize an `f32` value.
/// ///
/// If the format does not differentiate between `f32` and `f64`, a /// If the format does not differentiate between `f32` and `f64`, a
@@ -603,7 +674,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for f32 { /// impl Serialize for f32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_f32(*self) /// serializer.serialize_f32(*self)
/// } /// }
@@ -625,7 +697,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for f64 { /// impl Serialize for f64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_f64(*self) /// serializer.serialize_f64(*self)
/// } /// }
@@ -650,7 +723,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for char { /// impl Serialize for char {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_char(*self) /// serializer.serialize_char(*self)
/// } /// }
@@ -672,7 +746,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for str { /// impl Serialize for str {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_str(self) /// serializer.serialize_str(self)
/// } /// }
@@ -737,10 +812,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None}; /// # use Option::{Some, None};
/// # /// #
/// impl<T> Serialize for Option<T> /// impl<T> Serialize for Option<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// Some(ref value) => serializer.serialize_some(value), /// Some(ref value) => serializer.serialize_some(value),
@@ -770,10 +847,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None}; /// # use Option::{Some, None};
/// # /// #
/// impl<T> Serialize for Option<T> /// impl<T> Serialize for Option<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// Some(ref value) => serializer.serialize_some(value), /// Some(ref value) => serializer.serialize_some(value),
@@ -802,7 +881,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for () { /// impl Serialize for () {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_unit() /// serializer.serialize_unit()
/// } /// }
@@ -823,7 +903,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Nothing { /// impl Serialize for Nothing {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_unit_struct("Nothing") /// serializer.serialize_unit_struct("Nothing")
/// } /// }
@@ -847,7 +928,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::A => serializer.serialize_unit_variant("E", 0, "A"), /// E::A => serializer.serialize_unit_variant("E", 0, "A"),
@@ -876,7 +958,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Millimeters { /// impl Serialize for Millimeters {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_newtype_struct("Millimeters", &self.0) /// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// } /// }
@@ -906,7 +989,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s), /// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s),
@@ -956,10 +1040,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq}; /// use serde::ser::{Serialize, Serializer, SerializeSeq};
/// ///
/// impl<T> Serialize for Vec<T> /// impl<T> Serialize for Vec<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_seq(Some(self.len()))?; /// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self { /// for element in self {
@@ -988,12 +1074,14 @@ pub trait Serializer: Sized {
/// # struct Tuple3<A, B, C>(A, B, C); /// # struct Tuple3<A, B, C>(A, B, C);
/// # /// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C> /// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize, /// where
/// B: Serialize, /// A: Serialize,
/// C: Serialize /// B: Serialize,
/// C: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut tup = serializer.serialize_tuple(3)?; /// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?; /// tup.serialize_element(&self.0)?;
@@ -1012,7 +1100,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Vram { /// impl Serialize for Vram {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?; /// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?;
/// for element in &self.0[..] { /// for element in &self.0[..] {
@@ -1038,7 +1127,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?; /// ts.serialize_field(&self.0)?;
@@ -1072,7 +1162,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::T(ref a, ref b) => { /// E::T(ref a, ref b) => {
@@ -1130,11 +1221,13 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeMap}; /// use serde::ser::{Serialize, Serializer, SerializeMap};
/// ///
/// impl<K, V> Serialize for HashMap<K, V> /// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize, /// where
/// V: Serialize /// K: Serialize,
/// V: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut map = serializer.serialize_map(Some(self.len()))?; /// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self { /// for (k, v) in self {
@@ -1164,7 +1257,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?; /// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
/// rgb.serialize_field("r", &self.r)?; /// rgb.serialize_field("r", &self.r)?;
@@ -1197,7 +1291,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::S { ref r, ref g, ref b } => { /// E::S { ref r, ref g, ref b } => {
@@ -1234,7 +1329,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for SecretlyOneHigher { /// impl Serialize for SecretlyOneHigher {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_seq(self.data.iter().map(|x| x + 1)) /// serializer.collect_seq(self.data.iter().map(|x| x + 1))
/// } /// }
@@ -1272,7 +1368,8 @@ pub trait Serializer: Sized {
/// // Serializes as a map in which the values are all unit. /// // Serializes as a map in which the values are all unit.
/// impl Serialize for MapToUnit { /// impl Serialize for MapToUnit {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_map(self.keys.iter().map(|k| (k, ()))) /// serializer.collect_map(self.keys.iter().map(|k| (k, ())))
/// } /// }
@@ -1312,7 +1409,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for DateTime { /// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_str(&format_args!("{:?}{:?}", /// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(), /// self.naive_local(),
@@ -1352,7 +1450,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for DateTime { /// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_str(&format_args!("{:?}{:?}", /// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(), /// self.naive_local(),
@@ -1393,7 +1492,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Timestamp { /// impl Serialize for Timestamp {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// if serializer.is_human_readable() { /// if serializer.is_human_readable() {
/// // Serialize to a human-readable string "2015-05-15T17:01:00Z". /// // Serialize to a human-readable string "2015-05-15T17:01:00Z".
@@ -1442,10 +1542,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq}; /// use serde::ser::{Serialize, Serializer, SerializeSeq};
/// ///
/// impl<T> Serialize for Vec<T> /// impl<T> Serialize for Vec<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_seq(Some(self.len()))?; /// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self { /// for element in self {
@@ -1485,12 +1587,14 @@ pub trait SerializeSeq {
/// # struct Tuple3<A, B, C>(A, B, C); /// # struct Tuple3<A, B, C>(A, B, C);
/// # /// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C> /// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize, /// where
/// B: Serialize, /// A: Serialize,
/// C: Serialize /// B: Serialize,
/// C: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut tup = serializer.serialize_tuple(3)?; /// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?; /// tup.serialize_element(&self.0)?;
@@ -1529,10 +1633,12 @@ pub trait SerializeSeq {
/// # } /// # }
/// # /// #
/// # impl<T> Serialize for Array<T> /// # impl<T> Serialize for Array<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_tuple(16)?; /// let mut seq = serializer.serialize_tuple(16)?;
/// for element in self { /// for element in self {
@@ -1567,7 +1673,8 @@ pub trait SerializeTuple {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?; /// ts.serialize_field(&self.0)?;
@@ -1605,7 +1712,8 @@ pub trait SerializeTupleStruct {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::T(ref a, ref b) => { /// E::T(ref a, ref b) => {
@@ -1666,11 +1774,13 @@ pub trait SerializeTupleVariant {
/// use serde::ser::{Serialize, Serializer, SerializeMap}; /// use serde::ser::{Serialize, Serializer, SerializeMap};
/// ///
/// impl<K, V> Serialize for HashMap<K, V> /// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize, /// where
/// V: Serialize /// K: Serialize,
/// V: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut map = serializer.serialize_map(Some(self.len()))?; /// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self { /// for (k, v) in self {
@@ -1754,7 +1864,8 @@ pub trait SerializeMap {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?; /// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
/// rgb.serialize_field("r", &self.r)?; /// rgb.serialize_field("r", &self.r)?;
@@ -1802,7 +1913,8 @@ pub trait SerializeStruct {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::S { ref r, ref g, ref b } => { /// E::S { ref r, ref g, ref b } => {
+4 -5
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.41" # remember to update html_root_url version = "1.0.61" # 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)]"
@@ -23,10 +23,9 @@ name = "serde_derive"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "0.3" proc-macro2 = "0.4"
quote = "0.5" quote = "0.6"
serde_derive_internals = { version = "=0.23.1", default-features = false, path = "../serde_derive_internals" } syn = { version = "0.14", features = ["visit"] }
syn = { version = "0.13", features = ["visit"] }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0", path = "../serde" } serde = { version = "1.0", path = "../serde" }
+42 -13
View File
@@ -55,7 +55,8 @@ pub fn with_where_predicates_from_fields(
generics: &syn::Generics, generics: &syn::Generics,
from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>, from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics { ) -> syn::Generics {
let predicates = cont.data let predicates = cont
.data
.all_fields() .all_fields()
.flat_map(|field| from_field(&field.attrs)) .flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec()); .flat_map(|predicates| predicates.to_vec());
@@ -65,6 +66,28 @@ pub fn with_where_predicates_from_fields(
generics generics
} }
pub fn with_where_predicates_from_variants(
cont: &Container,
generics: &syn::Generics,
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return generics.clone();
}
};
let predicates = variants
.iter()
.flat_map(|variant| from_variant(&variant.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
generics
}
// 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.
// //
@@ -117,9 +140,9 @@ pub fn with_bound(
} }
} }
if path.leading_colon.is_none() && path.segments.len() == 1 { if path.leading_colon.is_none() && path.segments.len() == 1 {
let id = path.segments[0].ident; let id = &path.segments[0].ident;
if self.all_type_params.contains(&id) { if self.all_type_params.contains(id) {
self.relevant_type_params.insert(id); self.relevant_type_params.insert(id.clone());
} }
} }
visit::visit_path(self, path); visit::visit_path(self, path);
@@ -134,7 +157,10 @@ pub fn with_bound(
fn visit_macro(&mut self, _mac: &'ast syn::Macro) {} fn visit_macro(&mut self, _mac: &'ast syn::Macro) {}
} }
let all_type_params = generics.type_params().map(|param| param.ident).collect(); let all_type_params = generics
.type_params()
.map(|param| param.ident.clone())
.collect();
let mut visitor = FindTyParams { let mut visitor = FindTyParams {
all_type_params: all_type_params, all_type_params: all_type_params,
@@ -162,7 +188,7 @@ pub fn with_bound(
let associated_type_usage = visitor.associated_type_usage; let associated_type_usage = visitor.associated_type_usage;
let new_predicates = generics let new_predicates = generics
.type_params() .type_params()
.map(|param| param.ident) .map(|param| param.ident.clone())
.filter(|id| relevant_type_params.contains(id)) .filter(|id| relevant_type_params.contains(id))
.map(|id| syn::TypePath { .map(|id| syn::TypePath {
qself: None, qself: None,
@@ -224,7 +250,7 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
let bound = syn::Lifetime::new(lifetime, Span::call_site()); let bound = syn::Lifetime::new(lifetime, Span::call_site());
let def = syn::LifetimeDef { let def = syn::LifetimeDef {
attrs: Vec::new(), attrs: Vec::new(),
lifetime: bound, lifetime: bound.clone(),
colon_token: None, colon_token: None,
bounds: Punctuated::new(), bounds: Punctuated::new(),
}; };
@@ -234,10 +260,12 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
.chain(generics.params.iter().cloned().map(|mut param| { .chain(generics.params.iter().cloned().map(|mut param| {
match param { match param {
syn::GenericParam::Lifetime(ref mut param) => { syn::GenericParam::Lifetime(ref mut param) => {
param.bounds.push(bound); param.bounds.push(bound.clone());
} }
syn::GenericParam::Type(ref mut param) => { syn::GenericParam::Type(ref mut param) => {
param.bounds.push(syn::TypeParamBound::Lifetime(bound)); param
.bounds
.push(syn::TypeParamBound::Lifetime(bound.clone()));
} }
syn::GenericParam::Const(_) => {} syn::GenericParam::Const(_) => {}
} }
@@ -257,23 +285,24 @@ fn type_of_item(cont: &Container) -> syn::Type {
path: syn::Path { path: syn::Path {
leading_colon: None, leading_colon: None,
segments: vec![syn::PathSegment { segments: vec![syn::PathSegment {
ident: cont.ident, ident: cont.ident.clone(),
arguments: syn::PathArguments::AngleBracketed( arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments { syn::AngleBracketedGenericArguments {
colon2_token: None, colon2_token: None,
lt_token: Default::default(), lt_token: Default::default(),
args: cont.generics args: cont
.generics
.params .params
.iter() .iter()
.map(|param| match *param { .map(|param| match *param {
syn::GenericParam::Type(ref param) => { syn::GenericParam::Type(ref param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None, qself: None,
path: param.ident.into(), path: param.ident.clone().into(),
})) }))
} }
syn::GenericParam::Lifetime(ref param) => { syn::GenericParam::Lifetime(ref param) => {
syn::GenericArgument::Lifetime(param.lifetime) syn::GenericArgument::Lifetime(param.lifetime.clone())
} }
syn::GenericParam::Const(_) => { syn::GenericParam::Const(_) => {
panic!("Serde does not support const generics yet"); panic!("Serde does not support const generics yet");
+390 -247
View File
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -6,15 +6,16 @@
// 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.
use quote::{ToTokens, Tokens}; use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::token; use syn::token;
pub enum Fragment { pub enum Fragment {
/// Tokens that can be used as an expression. /// Tokens that can be used as an expression.
Expr(Tokens), Expr(TokenStream),
/// Tokens that can be used inside a block. The surrounding curly braces are /// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens. /// not part of these tokens.
Block(Tokens), Block(TokenStream),
} }
macro_rules! quote_expr { macro_rules! quote_expr {
@@ -33,7 +34,7 @@ macro_rules! quote_block {
/// Block fragments in curly braces. /// Block fragments in curly braces.
pub struct Expr(pub Fragment); pub struct Expr(pub Fragment);
impl ToTokens for Expr { impl ToTokens for Expr {
fn to_tokens(&self, out: &mut Tokens) { fn to_tokens(&self, out: &mut TokenStream) {
match self.0 { match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out), Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => { Fragment::Block(ref block) => {
@@ -46,7 +47,7 @@ impl ToTokens for Expr {
/// Interpolate a fragment as the statements of a block. /// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment); pub struct Stmts(pub Fragment);
impl ToTokens for Stmts { impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut Tokens) { fn to_tokens(&self, out: &mut TokenStream) {
match self.0 { match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out), Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out), Fragment::Block(ref block) => block.to_tokens(out),
@@ -58,7 +59,7 @@ impl ToTokens for Stmts {
/// involves putting a comma after expressions and curly braces around blocks. /// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment); pub struct Match(pub Fragment);
impl ToTokens for Match { impl ToTokens for Match {
fn to_tokens(&self, out: &mut Tokens) { fn to_tokens(&self, out: &mut TokenStream) {
match self.0 { match self.0 {
Fragment::Expr(ref expr) => { Fragment::Expr(ref expr) => {
expr.to_tokens(out); expr.to_tokens(out);
@@ -71,8 +72,8 @@ impl ToTokens for Match {
} }
} }
impl AsRef<Tokens> for Fragment { impl AsRef<TokenStream> for Fragment {
fn as_ref(&self) -> &Tokens { fn as_ref(&self) -> &TokenStream {
match *self { match *self {
Fragment::Expr(ref expr) => expr, Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block, Fragment::Block(ref block) => block,
@@ -6,11 +6,11 @@
// 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.
use attr; use internals::attr;
use check; use internals::check;
use internals::{Ctxt, Derive};
use syn; use syn;
use syn::punctuated::Punctuated; use syn::punctuated::Punctuated;
use Ctxt;
pub struct Container<'a> { pub struct Container<'a> {
pub ident: syn::Ident, pub ident: syn::Ident,
@@ -32,7 +32,7 @@ pub struct Variant<'a> {
} }
pub struct Field<'a> { pub struct Field<'a> {
pub ident: Option<syn::Ident>, pub member: syn::Member,
pub attrs: attr::Field, pub attrs: attr::Field,
pub ty: &'a syn::Type, pub ty: &'a syn::Type,
pub original: &'a syn::Field, pub original: &'a syn::Field,
@@ -47,7 +47,7 @@ pub enum Style {
} }
impl<'a> Container<'a> { impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> 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);
let mut data = match item.data { let mut data = match item.data {
@@ -86,13 +86,13 @@ impl<'a> Container<'a> {
attrs.mark_has_flatten(); attrs.mark_has_flatten();
} }
let item = Container { let mut item = Container {
ident: item.ident, ident: item.ident.clone(),
attrs: attrs, attrs: attrs,
data: data, data: data,
generics: &item.generics, generics: &item.generics,
}; };
check::check(cx, &item); check::check(cx, &mut item, derive);
item item
} }
} }
@@ -124,7 +124,7 @@ fn enum_from_ast<'a>(
let (style, fields) = let (style, fields) =
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default); struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant { Variant {
ident: variant.ident, ident: variant.ident.clone(),
attrs: attrs, attrs: attrs,
style: style, style: style,
fields: fields, fields: fields,
@@ -166,7 +166,10 @@ fn fields_from_ast<'a>(
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, field)| Field { .map(|(i, field)| Field {
ident: field.ident, member: match field.ident {
Some(ref ident) => syn::Member::Named(ident.clone()),
None => syn::Member::Unnamed(i.into()),
},
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default), attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty, ty: &field.ty,
original: field, original: field,
@@ -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.
use internals::Ctxt;
use proc_macro2::{Group, Span, TokenStream, TokenTree}; use proc_macro2::{Group, Span, TokenStream, TokenTree};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::str::FromStr; use std::str::FromStr;
@@ -15,7 +16,6 @@ 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};
use Ctxt;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints // This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and // are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
@@ -25,7 +25,7 @@ use Ctxt;
// user will see errors simultaneously for all bad attributes in the crate // user will see errors simultaneously for all bad attributes in the crate
// rather than just the first. // rather than just the first.
pub use case::RenameRule; pub use internals::case::RenameRule;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct Attr<'c, T> { struct Attr<'c, T> {
@@ -105,6 +105,7 @@ impl Name {
/// Represents container (e.g. struct) attribute information /// Represents container (e.g. struct) attribute information
pub struct Container { pub struct Container {
name: Name, name: Name,
transparent: bool,
deny_unknown_fields: bool, deny_unknown_fields: bool,
default: Default, default: Default,
rename_all: RenameRule, rename_all: RenameRule,
@@ -167,6 +168,7 @@ pub enum Identifier {
} }
impl Identifier { impl Identifier {
#[cfg(feature = "deserialize_in_place")]
pub fn is_some(self) -> bool { pub fn is_some(self) -> bool {
match self { match self {
Identifier::No => false, Identifier::No => false,
@@ -180,6 +182,7 @@ impl Container {
pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
let mut ser_name = Attr::none(cx, "rename"); let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename");
let mut transparent = BoolAttr::none(cx, "transparent");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields"); let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut default = Attr::none(cx, "default"); let mut default = Attr::none(cx, "default");
let mut rename_all = Attr::none(cx, "rename_all"); let mut rename_all = Attr::none(cx, "rename_all");
@@ -199,7 +202,7 @@ impl Container {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename" => { Meta(NameValue(ref m)) if m.ident == "rename" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
ser_name.set(s.value()); ser_name.set(s.value());
de_name.set(s.value()); de_name.set(s.value());
} }
@@ -215,7 +218,7 @@ impl Container {
// Parse `#[serde(rename_all = "foo")]` // Parse `#[serde(rename_all = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename_all" => { Meta(NameValue(ref m)) if m.ident == "rename_all" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match RenameRule::from_str(&s.value()) { match RenameRule::from_str(&s.value()) {
Ok(rename_rule) => rename_all.set(rename_rule), Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => cx.error(format!( Err(()) => cx.error(format!(
@@ -227,13 +230,18 @@ impl Container {
} }
} }
// Parse `#[serde(transparent)]`
Meta(Word(ref word)) if word == "transparent" => {
transparent.set_true();
}
// Parse `#[serde(deny_unknown_fields)]` // Parse `#[serde(deny_unknown_fields)]`
Meta(Word(word)) if word == "deny_unknown_fields" => { Meta(Word(ref word)) if word == "deny_unknown_fields" => {
deny_unknown_fields.set_true(); deny_unknown_fields.set_true();
} }
// Parse `#[serde(default)]` // Parse `#[serde(default)]`
Meta(Word(word)) if word == "default" => match item.data { Meta(Word(ref word)) if word == "default" => match item.data {
syn::Data::Struct(syn::DataStruct { syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(_), fields: syn::Fields::Named(_),
.. ..
@@ -248,7 +256,7 @@ impl Container {
// Parse `#[serde(default = "...")]` // Parse `#[serde(default = "...")]`
Meta(NameValue(ref m)) if m.ident == "default" => { Meta(NameValue(ref m)) if m.ident == "default" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
match item.data { match item.data {
syn::Data::Struct(syn::DataStruct { syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(_), fields: syn::Fields::Named(_),
@@ -267,7 +275,7 @@ impl Container {
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
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.as_ref(), m.ident.as_ref(), &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
{ {
ser_bound.set(where_predicates.clone()); ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates); de_bound.set(where_predicates);
@@ -283,7 +291,7 @@ impl Container {
} }
// Parse `#[serde(untagged)]` // Parse `#[serde(untagged)]`
Meta(Word(word)) if word == "untagged" => match item.data { Meta(Word(ref word)) if word == "untagged" => match item.data {
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
untagged.set_true(); untagged.set_true();
} }
@@ -294,7 +302,7 @@ impl Container {
// Parse `#[serde(tag = "type")]` // Parse `#[serde(tag = "type")]`
Meta(NameValue(ref m)) if m.ident == "tag" => { Meta(NameValue(ref m)) if m.ident == "tag" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match item.data { match item.data {
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
internal_tag.set(s.value()); internal_tag.set(s.value());
@@ -308,7 +316,7 @@ impl Container {
// Parse `#[serde(content = "c")]` // Parse `#[serde(content = "c")]`
Meta(NameValue(ref m)) if m.ident == "content" => { Meta(NameValue(ref m)) if m.ident == "content" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match item.data { match item.data {
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
content.set(s.value()); content.set(s.value());
@@ -323,23 +331,23 @@ impl Container {
// Parse `#[serde(from = "Type")] // Parse `#[serde(from = "Type")]
Meta(NameValue(ref m)) if m.ident == "from" => { Meta(NameValue(ref m)) if m.ident == "from" => {
if let Ok(from_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) { if let Ok(from_ty) = parse_lit_into_ty(cx, &m.ident, &m.lit) {
type_from.set_opt(Some(from_ty)); type_from.set_opt(Some(from_ty));
} }
} }
// Parse `#[serde(into = "Type")] // Parse `#[serde(into = "Type")]
Meta(NameValue(ref m)) if m.ident == "into" => { Meta(NameValue(ref m)) if m.ident == "into" => {
if let Ok(into_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) { if let Ok(into_ty) = parse_lit_into_ty(cx, &m.ident, &m.lit) {
type_into.set_opt(Some(into_ty)); type_into.set_opt(Some(into_ty));
} }
} }
// Parse `#[serde(remote = "...")]` // Parse `#[serde(remote = "...")]`
Meta(NameValue(ref m)) if m.ident == "remote" => { Meta(NameValue(ref m)) if m.ident == "remote" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_path(cx, &m.ident, &m.lit) {
if is_primitive_path(&path, "Self") { if is_primitive_path(&path, "Self") {
remote.set(item.ident.into()); remote.set(item.ident.clone().into());
} else { } else {
remote.set(path); remote.set(path);
} }
@@ -347,12 +355,12 @@ impl Container {
} }
// Parse `#[serde(field_identifier)]` // Parse `#[serde(field_identifier)]`
Meta(Word(word)) if word == "field_identifier" => { Meta(Word(ref word)) if word == "field_identifier" => {
field_identifier.set_true(); field_identifier.set_true();
} }
// Parse `#[serde(variant_identifier)]` // Parse `#[serde(variant_identifier)]`
Meta(Word(word)) if word == "variant_identifier" => { Meta(Word(ref word)) if word == "variant_identifier" => {
variant_identifier.set_true(); variant_identifier.set_true();
} }
@@ -375,6 +383,7 @@ impl Container {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()), deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
}, },
transparent: transparent.get(),
deny_unknown_fields: deny_unknown_fields.get(), deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None), default: default.get().unwrap_or(Default::None),
rename_all: rename_all.get().unwrap_or(RenameRule::None), rename_all: rename_all.get().unwrap_or(RenameRule::None),
@@ -397,6 +406,10 @@ impl Container {
&self.rename_all &self.rename_all
} }
pub fn transparent(&self) -> bool {
self.transparent
}
pub fn deny_unknown_fields(&self) -> bool { pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields self.deny_unknown_fields
} }
@@ -526,6 +539,8 @@ pub struct Variant {
ser_renamed: bool, ser_renamed: bool,
de_renamed: bool, de_renamed: bool,
rename_all: RenameRule, rename_all: RenameRule,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
skip_deserializing: bool, skip_deserializing: bool,
skip_serializing: bool, skip_serializing: bool,
other: bool, other: bool,
@@ -541,6 +556,8 @@ impl Variant {
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut rename_all = Attr::none(cx, "rename_all"); let mut rename_all = Attr::none(cx, "rename_all");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let mut other = BoolAttr::none(cx, "other"); let mut other = BoolAttr::none(cx, "other");
let mut serialize_with = Attr::none(cx, "serialize_with"); let mut serialize_with = Attr::none(cx, "serialize_with");
let mut deserialize_with = Attr::none(cx, "deserialize_with"); let mut deserialize_with = Attr::none(cx, "deserialize_with");
@@ -551,7 +568,7 @@ impl Variant {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename" => { Meta(NameValue(ref m)) if m.ident == "rename" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
ser_name.set(s.value()); ser_name.set(s.value());
de_name.set(s.value()); de_name.set(s.value());
} }
@@ -567,7 +584,7 @@ impl Variant {
// Parse `#[serde(rename_all = "foo")]` // Parse `#[serde(rename_all = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename_all" => { Meta(NameValue(ref m)) if m.ident == "rename_all" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match RenameRule::from_str(&s.value()) { match RenameRule::from_str(&s.value()) {
Ok(rename_rule) => rename_all.set(rename_rule), Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => cx.error(format!( Err(()) => cx.error(format!(
@@ -579,24 +596,48 @@ impl Variant {
} }
} }
// Parse `#[serde(skip)]`
Meta(Word(ref word)) if word == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
}
// Parse `#[serde(skip_deserializing)]` // Parse `#[serde(skip_deserializing)]`
Meta(Word(word)) if word == "skip_deserializing" => { Meta(Word(ref word)) if word == "skip_deserializing" => {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip_serializing)]` // Parse `#[serde(skip_serializing)]`
Meta(Word(word)) if word == "skip_serializing" => { Meta(Word(ref word)) if word == "skip_serializing" => {
skip_serializing.set_true(); skip_serializing.set_true();
} }
// Parse `#[serde(other)]` // Parse `#[serde(other)]`
Meta(Word(word)) if word == "other" => { Meta(Word(ref word)) if word == "other" => {
other.set_true(); other.set_true();
} }
// Parse `#[serde(bound = "D: Serialize")]`
Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
{
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
Meta(List(ref m)) if m.ident == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
// Parse `#[serde(with = "...")]` // Parse `#[serde(with = "...")]`
Meta(NameValue(ref m)) if m.ident == "with" => { Meta(NameValue(ref m)) if m.ident == "with" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path ser_path
.path .path
@@ -614,14 +655,14 @@ impl Variant {
// Parse `#[serde(serialize_with = "...")]` // Parse `#[serde(serialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "serialize_with" => { Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
serialize_with.set(path); serialize_with.set(path);
} }
} }
// Parse `#[serde(deserialize_with = "...")]` // Parse `#[serde(deserialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "deserialize_with" => { Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
@@ -662,6 +703,8 @@ impl Variant {
ser_renamed: ser_renamed, ser_renamed: ser_renamed,
de_renamed: de_renamed, de_renamed: de_renamed,
rename_all: rename_all.get().unwrap_or(RenameRule::None), rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
skip_deserializing: skip_deserializing.get(), skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(), skip_serializing: skip_serializing.get(),
other: other.get(), other: other.get(),
@@ -688,6 +731,14 @@ impl Variant {
&self.rename_all &self.rename_all
} }
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn skip_deserializing(&self) -> bool { pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing self.skip_deserializing
} }
@@ -725,6 +776,7 @@ pub struct Field {
borrowed_lifetimes: BTreeSet<syn::Lifetime>, borrowed_lifetimes: BTreeSet<syn::Lifetime>,
getter: Option<syn::ExprPath>, getter: Option<syn::ExprPath>,
flatten: bool, flatten: bool,
transparent: bool,
} }
/// Represents the default to use for a field when deserializing. /// Represents the default to use for a field when deserializing.
@@ -737,6 +789,15 @@ pub enum Default {
Path(syn::ExprPath), Path(syn::ExprPath),
} }
impl Default {
pub fn is_none(&self) -> bool {
match *self {
Default::None => true,
Default::Default | Default::Path(_) => false,
}
}
}
impl Field { impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field. /// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast( pub fn from_ast(
@@ -766,9 +827,7 @@ impl Field {
}; };
let variant_borrow = attrs let variant_borrow = attrs
.map(|variant| &variant.borrow) .and_then(|variant| variant.borrow.as_ref())
.unwrap_or(&None)
.as_ref()
.map(|borrow| vec![Meta(borrow.clone())]); .map(|borrow| vec![Meta(borrow.clone())]);
for meta_items in field for meta_items in field
@@ -781,7 +840,7 @@ impl Field {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename" => { Meta(NameValue(ref m)) if m.ident == "rename" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
ser_name.set(s.value()); ser_name.set(s.value());
de_name.set(s.value()); de_name.set(s.value());
} }
@@ -796,57 +855,57 @@ impl Field {
} }
// Parse `#[serde(default)]` // Parse `#[serde(default)]`
Meta(Word(word)) if word == "default" => { Meta(Word(ref word)) if word == "default" => {
default.set(Default::Default); default.set(Default::Default);
} }
// Parse `#[serde(default = "...")]` // Parse `#[serde(default = "...")]`
Meta(NameValue(ref m)) if m.ident == "default" => { Meta(NameValue(ref m)) if m.ident == "default" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
default.set(Default::Path(path)); default.set(Default::Path(path));
} }
} }
// Parse `#[serde(skip_serializing)]` // Parse `#[serde(skip_serializing)]`
Meta(Word(word)) if word == "skip_serializing" => { Meta(Word(ref word)) if word == "skip_serializing" => {
skip_serializing.set_true(); skip_serializing.set_true();
} }
// Parse `#[serde(skip_deserializing)]` // Parse `#[serde(skip_deserializing)]`
Meta(Word(word)) if word == "skip_deserializing" => { Meta(Word(ref word)) if word == "skip_deserializing" => {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip)]` // Parse `#[serde(skip)]`
Meta(Word(word)) if word == "skip" => { Meta(Word(ref word)) if word == "skip" => {
skip_serializing.set_true(); skip_serializing.set_true();
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip_serializing_if = "...")]` // Parse `#[serde(skip_serializing_if = "...")]`
Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => { Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
skip_serializing_if.set(path); skip_serializing_if.set(path);
} }
} }
// Parse `#[serde(serialize_with = "...")]` // Parse `#[serde(serialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "serialize_with" => { Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
serialize_with.set(path); serialize_with.set(path);
} }
} }
// Parse `#[serde(deserialize_with = "...")]` // Parse `#[serde(deserialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "deserialize_with" => { Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
// Parse `#[serde(with = "...")]` // Parse `#[serde(with = "...")]`
Meta(NameValue(ref m)) if m.ident == "with" => { Meta(NameValue(ref m)) if m.ident == "with" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path ser_path
.path .path
@@ -865,7 +924,7 @@ impl Field {
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
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.as_ref(), m.ident.as_ref(), &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
{ {
ser_bound.set(where_predicates.clone()); ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates); de_bound.set(where_predicates);
@@ -881,7 +940,7 @@ impl Field {
} }
// Parse `#[serde(borrow)]` // Parse `#[serde(borrow)]`
Meta(Word(word)) if word == "borrow" => { Meta(Word(ref word)) if word == "borrow" => {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
borrowed_lifetimes.set(borrowable); borrowed_lifetimes.set(borrowable);
} }
@@ -889,9 +948,7 @@ impl Field {
// Parse `#[serde(borrow = "'a + 'b")]` // Parse `#[serde(borrow = "'a + 'b")]`
Meta(NameValue(ref m)) if m.ident == "borrow" => { Meta(NameValue(ref m)) if m.ident == "borrow" => {
if let Ok(lifetimes) = if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, &m.ident, &m.lit) {
parse_lit_into_lifetimes(cx, m.ident.as_ref(), &m.lit)
{
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
for lifetime in &lifetimes { for lifetime in &lifetimes {
if !borrowable.contains(lifetime) { if !borrowable.contains(lifetime) {
@@ -908,13 +965,13 @@ impl Field {
// Parse `#[serde(getter = "...")]` // Parse `#[serde(getter = "...")]`
Meta(NameValue(ref m)) if m.ident == "getter" => { Meta(NameValue(ref m)) if m.ident == "getter" => {
if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
getter.set(path); getter.set(path);
} }
} }
// Parse `#[serde(flatten)]` // Parse `#[serde(flatten)]`
Meta(Word(word)) if word == "flatten" => { Meta(Word(ref word)) if word == "flatten" => {
flatten.set_true(); flatten.set_true();
} }
@@ -991,7 +1048,7 @@ impl Field {
}; };
deserialize_with.set_if_none(expr); deserialize_with.set_if_none(expr);
} }
} else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) { } else if is_implicitly_borrowed(&field.ty) {
// Types &str and &[u8] are always implicitly borrowed. No need for // Types &str and &[u8] are always implicitly borrowed. No need for
// a #[serde(borrow)]. // a #[serde(borrow)].
collect_lifetimes(&field.ty, &mut borrowed_lifetimes); collect_lifetimes(&field.ty, &mut borrowed_lifetimes);
@@ -1019,6 +1076,7 @@ impl Field {
borrowed_lifetimes: borrowed_lifetimes, borrowed_lifetimes: borrowed_lifetimes,
getter: getter.get(), getter: getter.get(),
flatten: flatten.get(), flatten: flatten.get(),
transparent: false,
} }
} }
@@ -1078,6 +1136,14 @@ impl Field {
pub fn flatten(&self) -> bool { pub fn flatten(&self) -> bool {
self.flatten self.flatten
} }
pub fn transparent(&self) -> bool {
self.transparent
}
pub fn mark_transparent(&mut self) {
self.transparent = true;
}
} }
type SerAndDe<T> = (Option<T>, Option<T>); type SerAndDe<T> = (Option<T>, Option<T>);
@@ -1090,21 +1156,22 @@ fn get_ser_and_de<'a, T, F>(
) -> Result<SerAndDe<T>, ()> ) -> Result<SerAndDe<T>, ()>
where where
T: 'a, T: 'a,
F: Fn(&Ctxt, &str, &str, &'a syn::Lit) -> Result<T, ()>, F: Fn(&Ctxt, &Ident, &Ident, &'a syn::Lit) -> Result<T, ()>,
{ {
let mut ser_meta = Attr::none(cx, attr_name); let mut ser_meta = Attr::none(cx, attr_name);
let mut de_meta = Attr::none(cx, attr_name); let mut de_meta = Attr::none(cx, attr_name);
let attr_name = Ident::new(attr_name, Span::call_site());
for meta in metas { for meta in metas {
match *meta { match *meta {
Meta(NameValue(ref meta)) if meta.ident == "serialize" => { Meta(NameValue(ref meta)) if meta.ident == "serialize" => {
if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) { if let Ok(v) = f(cx, &attr_name, &meta.ident, &meta.lit) {
ser_meta.set(v); ser_meta.set(v);
} }
} }
Meta(NameValue(ref meta)) if meta.ident == "deserialize" => { Meta(NameValue(ref meta)) if meta.ident == "deserialize" => {
if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) { if let Ok(v) = f(cx, &attr_name, &meta.ident, &meta.lit) {
de_meta.set(v); de_meta.set(v);
} }
} }
@@ -1153,8 +1220,8 @@ pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMeta
fn get_lit_str<'a>( fn get_lit_str<'a>(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
meta_item_name: &str, meta_item_name: &Ident,
lit: &'a syn::Lit, lit: &'a syn::Lit,
) -> Result<&'a syn::LitStr, ()> { ) -> Result<&'a syn::LitStr, ()> {
if let syn::Lit::Str(ref lit) = *lit { if let syn::Lit::Str(ref lit) = *lit {
@@ -1168,7 +1235,7 @@ fn get_lit_str<'a>(
} }
} }
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> { fn parse_lit_into_path(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
parse_lit_str(string) parse_lit_str(string)
.map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value()))) .map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
@@ -1176,7 +1243,7 @@ fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn
fn parse_lit_into_expr_path( fn parse_lit_into_expr_path(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
lit: &syn::Lit, lit: &syn::Lit,
) -> Result<syn::ExprPath, ()> { ) -> Result<syn::ExprPath, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
@@ -1186,8 +1253,8 @@ fn parse_lit_into_expr_path(
fn parse_lit_into_where( fn parse_lit_into_where(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
meta_item_name: &str, meta_item_name: &Ident,
lit: &syn::Lit, lit: &syn::Lit,
) -> Result<Vec<syn::WherePredicate>, ()> { ) -> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_lit_str(cx, attr_name, meta_item_name, lit)); let string = try!(get_lit_str(cx, attr_name, meta_item_name, lit));
@@ -1202,7 +1269,7 @@ fn parse_lit_into_where(
.map_err(|err| cx.error(err)) .map_err(|err| cx.error(err))
} }
fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Type, ()> { fn parse_lit_into_ty(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn::Type, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
parse_lit_str(string).map_err(|_| { parse_lit_str(string).map_err(|_| {
@@ -1218,7 +1285,7 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::
// lifetimes separated by `+`. // lifetimes separated by `+`.
fn parse_lit_into_lifetimes( fn parse_lit_into_lifetimes(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
lit: &syn::Lit, lit: &syn::Lit,
) -> Result<BTreeSet<syn::Lifetime>, ()> { ) -> Result<BTreeSet<syn::Lifetime>, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
@@ -1239,7 +1306,7 @@ fn parse_lit_into_lifetimes(
if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) { if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
let mut set = BTreeSet::new(); let mut set = BTreeSet::new();
for lifetime in lifetimes { for lifetime in lifetimes {
if !set.insert(lifetime) { if !set.insert(lifetime.clone()) {
cx.error(format!("duplicate borrowed lifetime `{}`", lifetime)); cx.error(format!("duplicate borrowed lifetime `{}`", lifetime));
} }
} }
@@ -1253,6 +1320,14 @@ fn parse_lit_into_lifetimes(
Err(()) Err(())
} }
fn is_implicitly_borrowed(ty: &syn::Type) -> bool {
is_implicitly_borrowed_reference(ty) || is_option(ty, is_implicitly_borrowed_reference)
}
fn is_implicitly_borrowed_reference(ty: &syn::Type) -> bool {
is_reference(ty, is_str) || is_reference(ty, is_slice_u8)
}
// Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T". // Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T".
// This can have false negatives and false positives. // This can have false negatives and false positives.
// //
@@ -1300,6 +1375,31 @@ fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
} }
} }
fn is_option(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
let path = match *ty {
syn::Type::Path(ref ty) => &ty.path,
_ => {
return false;
}
};
let seg = match path.segments.last() {
Some(seg) => seg.into_value(),
None => {
return false;
}
};
let args = match seg.arguments {
syn::PathArguments::AngleBracketed(ref bracketed) => &bracketed.args,
_ => {
return false;
}
};
seg.ident == "Option" && args.len() == 1 && match args[0] {
syn::GenericArgument::Type(ref arg) => elem(arg),
_ => false,
}
}
// Whether the type looks like it might be `&T` where elem="T". This can have // Whether the type looks like it might be `&T` where elem="T". This can have
// false negatives and false positives. // false negatives and false positives.
// //
@@ -1320,7 +1420,7 @@ fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
// struct S<'a> { // struct S<'a> {
// r: &'a str, // r: &'a str,
// } // }
fn is_rptr(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { fn is_reference(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
match *ty { match *ty {
syn::Type::Reference(ref ty) => ty.mutability.is_none() && elem(&ty.elem), syn::Type::Reference(ref ty) => ty.mutability.is_none() && elem(&ty.elem),
_ => false, _ => false,
@@ -1346,7 +1446,9 @@ fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool {
} }
fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool { fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
path.leading_colon.is_none() && path.segments.len() == 1 && path.segments[0].ident == primitive path.leading_colon.is_none()
&& path.segments.len() == 1
&& path.segments[0].ident == primitive
&& path.segments[0].arguments.is_empty() && path.segments[0].arguments.is_empty()
} }
@@ -6,19 +6,21 @@
// 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.
use ast::{Container, Data, Style}; use internals::ast::{Container, Data, Field, Style};
use attr::{EnumTag, Identifier}; use internals::attr::{EnumTag, Identifier};
use Ctxt; use internals::{Ctxt, Derive};
use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs /// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs. /// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) { pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_getter(cx, cont); check_getter(cx, cont);
check_flatten(cx, cont); check_flatten(cx, cont);
check_identifier(cx, cont); check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont); check_variant_skip_attrs(cx, cont);
check_internal_tag_field_name_conflict(cx, cont); check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont); check_adjacent_tag_conflict(cx, cont);
check_transparent(cx, cont, derive);
} }
/// Getters are only allowed inside structs (not enums) with the `remote` /// Getters are only allowed inside structs (not enums) with the `remote`
@@ -44,43 +46,49 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
/// Flattening has some restrictions we can test. /// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) { fn check_flatten(cx: &Ctxt, cont: &Container) {
match cont.data { match cont.data {
Data::Enum(_) => { Data::Enum(ref variants) => {
if cont.attrs.has_flatten() { for variant in variants {
cx.error("#[serde(flatten)] cannot be used within enums"); for field in &variant.fields {
} check_flatten_field(cx, variant.style, field);
}
Data::Struct(style, _) => {
for field in cont.data.all_fields() {
if !field.attrs.flatten() {
continue;
}
match style {
Style::Tuple => {
cx.error("#[serde(flatten)] cannot be used on tuple structs");
}
Style::Newtype => {
cx.error("#[serde(flatten)] cannot be used on newtype structs");
}
_ => {}
}
if field.attrs.skip_serializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing)]",
);
} else if field.attrs.skip_serializing_if().is_some() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing_if = \"...\")]",
);
} else if field.attrs.skip_deserializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_deserializing)]",
);
} }
} }
} }
Data::Struct(style, ref fields) => {
for field in fields {
check_flatten_field(cx, style, field);
}
}
}
}
fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
if !field.attrs.flatten() {
return;
}
match style {
Style::Tuple => {
cx.error("#[serde(flatten)] cannot be used on tuple structs");
}
Style::Newtype => {
cx.error("#[serde(flatten)] cannot be used on newtype structs");
}
_ => {}
}
if field.attrs.skip_serializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing)]",
);
} else if field.attrs.skip_serializing_if().is_some() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing_if = \"...\")]",
);
} else if field.attrs.skip_deserializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_deserializing)]",
);
} }
} }
@@ -165,17 +173,14 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
)); ));
} }
for (i, field) in variant.fields.iter().enumerate() { for field in &variant.fields {
let ident = field let member = member_message(&field.member);
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
if field.attrs.skip_serializing() { if field.attrs.skip_serializing() {
cx.error(format!( cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \ "variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]", a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident variant.ident, member
)); ));
} }
@@ -183,7 +188,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error(format!( cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \ "variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]", a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident variant.ident, member
)); ));
} }
} }
@@ -198,17 +203,14 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
)); ));
} }
for (i, field) in variant.fields.iter().enumerate() { for field in &variant.fields {
if field.attrs.skip_deserializing() { if field.attrs.skip_deserializing() {
let ident = field let member = member_message(&field.member);
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
cx.error(format!( cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \ "variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]", and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident variant.ident, member
)); ));
} }
} }
@@ -276,3 +278,78 @@ fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
cx.error(message); cx.error(message);
} }
} }
/// Enums and unit structs cannot be transparent.
fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
if !cont.attrs.transparent() {
return;
}
if cont.attrs.type_from().is_some() {
cx.error("#[serde(transparent)] is not allowed with #[serde(from = \"...\")]");
}
if cont.attrs.type_into().is_some() {
cx.error("#[serde(transparent)] is not allowed with #[serde(into = \"...\")]");
}
let fields = match cont.data {
Data::Enum(_) => {
cx.error("#[serde(transparent)] is not allowed on an enum");
return;
}
Data::Struct(Style::Unit, _) => {
cx.error("#[serde(transparent)] is not allowed on a unit struct");
return;
}
Data::Struct(_, ref mut fields) => fields,
};
let mut transparent_field = None;
for field in fields {
if allow_transparent(field, derive) {
if transparent_field.is_some() {
cx.error(
"#[serde(transparent)] requires struct to have at most one transparent field",
);
return;
}
transparent_field = Some(field);
}
}
match transparent_field {
Some(transparent_field) => transparent_field.attrs.mark_transparent(),
None => match derive {
Derive::Serialize => {
cx.error("#[serde(transparent)] requires at least one field that is not skipped");
}
Derive::Deserialize => {
cx.error("#[serde(transparent)] requires at least one field that is neither skipped nor has a default");
}
},
}
}
fn member_message(member: &Member) -> String {
match *member {
Member::Named(ref ident) => format!("`{}`", ident),
Member::Unnamed(ref i) => i.index.to_string(),
}
}
fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ref ty) = *field.ty {
if let Some(seg) = ty.path.segments.last() {
if seg.into_value().ident == "PhantomData" {
return false;
}
}
}
match derive {
Derive::Serialize => !field.attrs.skip_serializing(),
Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(),
}
}
+22
View File
@@ -0,0 +1,22 @@
// 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.
pub mod ast;
pub mod attr;
mod ctxt;
pub use self::ctxt::Ctxt;
mod case;
mod check;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
Deserialize,
}
+19 -12
View File
@@ -22,10 +22,23 @@
//! //!
//! [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.41")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.61")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding) allow(
enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding,
cyclomatic_complexity
)
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
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
)
)] )]
// The `quote!` macro requires deep recursion. // The `quote!` macro requires deep recursion.
#![recursion_limit = "512"] #![recursion_limit = "512"]
@@ -35,29 +48,23 @@ extern crate quote;
#[macro_use] #[macro_use]
extern crate syn; extern crate syn;
extern crate serde_derive_internals as internals;
extern crate proc_macro; extern crate proc_macro;
extern crate proc_macro2; extern crate proc_macro2;
mod internals;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use syn::DeriveInput; use syn::DeriveInput;
// Quote's default is def_site but it appears call_site is likely to stabilize
// before def_site. Thus we try to use only call_site.
macro_rules! quote {
($($tt:tt)*) => {
quote_spanned!($crate::proc_macro2::Span::call_site()=> $($tt)*)
}
}
#[macro_use] #[macro_use]
mod bound; mod bound;
#[macro_use] #[macro_use]
mod fragment; mod fragment;
mod de; mod de;
mod pretend;
mod ser; mod ser;
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 {
+140
View File
@@ -0,0 +1,140 @@
use proc_macro2::{Span, TokenStream};
use syn::Ident;
use internals::ast::{Container, Data, Field, Style};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
// never has its fields referenced and an enum annotated with remote derive
// never has its variants constructed.
//
// warning: field is never used: `i`
// --> src/main.rs:4:20
// |
// 4 | struct StructDef { i: i32 }
// | ^^^^^^
//
// warning: variant is never constructed: `V`
// --> src/main.rs:8:16
// |
// 8 | enum EnumDef { V }
// | ^
//
pub fn pretend_used(cont: &Container) -> TokenStream {
let pretend_fields = pretend_fields_used(cont);
let pretend_variants = pretend_variants_used(cont);
quote! {
#pretend_fields
#pretend_variants
}
}
// For structs with named fields, expands to:
//
// match None::<T> {
// Some(T { a: ref __v0, b: ref __v1 }) => {}
// _ => {}
// }
//
// For enums, expands to the following but only including struct variants:
//
// match None::<T> {
// Some(T::A { a: ref __v0 }) => {}
// Some(T::B { b: ref __v0 }) => {}
// _ => {}
// }
//
// The `ref` is important in case the user has written a Drop impl on their
// type. Rust does not allow destructuring a struct or enum that has a Drop
// impl.
fn pretend_fields_used(cont: &Container) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = &variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
Data::Struct(_, _) => {
return quote!();
}
};
quote! {
match _serde::export::None::<#type_ident #ty_generics> {
#(
_serde::export::Some(#patterns) => {}
)*
_ => {}
}
}
}
// Expands to one of these per enum variant:
//
// match None {
// Some((__v0, __v1,)) => {
// let _ = E::V { a: __v0, b: __v1 };
// }
// _ => {}
// }
//
fn pretend_variants_used(cont: &Container) -> TokenStream {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
};
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let turbofish = ty_generics.as_turbofish();
let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.collect::<Vec<_>>();
let pat = match variant.style {
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote!({ #(#members: #placeholders),* })
}
Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
Style::Unit => quote!(),
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
}
});
quote!(#(#cases)*)
}
fn struct_pattern(fields: &[Field]) -> TokenStream {
let members = fields.iter().map(|field| &field.member);
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#members: ref #placeholders),* })
}
+235 -81
View File
@@ -6,21 +6,20 @@
// 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.
use proc_macro2::Span; use proc_macro2::{Span, TokenStream};
use quote::Tokens;
use syn::spanned::Spanned; use syn::spanned::Spanned;
use syn::{self, Ident, Index, Member}; use syn::{self, Ident, Index, Member};
use bound; use bound;
use fragment::{Fragment, Match, Stmts}; use fragment::{Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant}; use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, Ctxt}; use internals::{attr, Ctxt, Derive};
use pretend;
use try;
use std::u32; pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, String> {
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = Ctxt::new(); let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input); let cont = Container::from_ast(&ctxt, input, Derive::Serialize);
precondition(&ctxt, &cont); precondition(&ctxt, &cont);
try!(ctxt.check()); try!(ctxt.check());
@@ -32,12 +31,14 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis; let vis = &input.vis;
let fun = quote_spanned!(Span::call_site()=> serialize); let used = pretend::pretend_used(&cont);
quote! { quote! {
impl #impl_generics #ident #ty_generics #where_clause { impl #impl_generics #ident #ty_generics #where_clause {
#vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
#used
#body #body
} }
} }
@@ -47,7 +48,8 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
#[automatically_derived] #[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause { impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
#body #body
} }
@@ -55,10 +57,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
} }
}; };
let try_replacement = try::replacement();
let generated = quote! { let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = { const #dummy_const: () = {
extern crate serde as _serde; extern crate serde as _serde;
#try_replacement
#impl_block #impl_block
}; };
}; };
@@ -105,7 +109,7 @@ impl Parameters {
let this = match cont.attrs.remote() { let this = match cont.attrs.remote() {
Some(remote) => remote.clone(), Some(remote) => remote.clone(),
None => cont.ident.into(), None => cont.ident.clone().into(),
}; };
let generics = build_generics(cont); let generics = build_generics(cont);
@@ -120,8 +124,8 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to /// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods. /// various Serializer methods.
fn type_name(&self) -> &str { fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.as_ref() self.this.segments.last().unwrap().value().ident.to_string()
} }
} }
@@ -133,6 +137,9 @@ fn build_generics(cont: &Container) -> syn::Generics {
let generics = let generics =
bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound); bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
let generics =
bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound);
match cont.attrs.ser_bound() { match cont.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates), Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => bound::with_bound( None => bound::with_bound(
@@ -145,31 +152,31 @@ fn build_generics(cont: &Container) -> syn::Generics {
} }
// Fields with a `skip_serializing` or `serialize_with` attribute, or which // Fields with a `skip_serializing` or `serialize_with` attribute, or which
// belong to a variant with a `serialize_with` attribute, are not serialized by // belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
// us so we do not generate a bound. Fields with a `bound` attribute specify // are not serialized by us so we do not generate a bound. Fields with a `bound`
// their own bound so we do not generate one. All other fields may need a `T: // attribute specify their own bound so we do not generate one. All other fields
// Serialize` bound where T is the type of the field. // may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none() !field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
&& variant.map_or(true, |variant| variant.serialize_with().is_none()) && variant.map_or(true, |variant| {
!variant.skip_serializing()
&& variant.serialize_with().is_none()
&& variant.ser_bound().is_none()
})
} }
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
if let Some(type_into) = cont.attrs.type_into() { if cont.attrs.transparent() {
serialize_transparent(cont, params)
} else if let Some(type_into) = cont.attrs.type_into() {
serialize_into(params, type_into) serialize_into(params, type_into)
} else { } else {
match cont.data { match cont.data {
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs), Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, ref fields) => { Data::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(params, fields, &cont.attrs) serialize_struct(params, fields, &cont.attrs)
} }
Data::Struct(Style::Tuple, ref fields) => { Data::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
serialize_tuple_struct(params, fields, &cont.attrs) serialize_tuple_struct(params, fields, &cont.attrs)
} }
Data::Struct(Style::Newtype, ref fields) => { Data::Struct(Style::Newtype, ref fields) => {
@@ -180,6 +187,26 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
} }
} }
fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
let fields = match cont.data {
Data::Struct(_, ref fields) => fields,
Data::Enum(_) => unreachable!(),
};
let self_var = &params.self_var;
let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
let member = &transparent_field.member;
let path = match transparent_field.attrs.serialize_with() {
Some(path) => quote!(#path),
None => quote!(_serde::Serialize::serialize),
};
quote_block! {
#path(&#self_var.#member, __serializer)
}
}
fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment { fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
let self_var = &params.self_var; let self_var = &params.self_var;
quote_block! { quote_block! {
@@ -232,8 +259,28 @@ fn serialize_tuple_struct(
serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct); serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct);
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0); let mut serialized_fields = fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|(i, field)| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let index = syn::Index {
index: i as u32,
span: Span::call_site(),
};
let field_expr = get_member(params, field, &Member::Unnamed(index));
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! { quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)); let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
@@ -243,7 +290,7 @@ fn serialize_tuple_struct(
} }
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
assert!(fields.len() as u64 <= u64::from(u32::MAX)); assert!(fields.len() as u64 <= u64::from(u32::max_value()));
if cattrs.has_flatten() { if cattrs.has_flatten() {
serialize_struct_as_map(params, fields, cattrs) serialize_struct_as_map(params, fields, cattrs)
@@ -273,8 +320,7 @@ fn serialize_struct_as_struct(
.map(|field| match field.attrs.skip_serializing_if() { .map(|field| match field.attrs.skip_serializing_if() {
None => quote!(1), None => quote!(1),
Some(path) => { Some(path) => {
let ident = field.ident.expect("struct has unnamed fields"); let field_expr = get_member(params, field, &field.member);
let field_expr = get_member(params, field, &Member::Named(ident));
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) })
@@ -309,8 +355,7 @@ fn serialize_struct_as_map(
.map(|field| match field.attrs.skip_serializing_if() { .map(|field| match field.attrs.skip_serializing_if() {
None => quote!(1), None => quote!(1),
Some(path) => { Some(path) => {
let ident = field.ident.expect("struct has unnamed fields"); let field_expr = get_member(params, field, &field.member);
let field_expr = get_member(params, field, &Member::Named(ident));
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) })
@@ -326,7 +371,7 @@ fn serialize_struct_as_map(
} }
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
assert!(variants.len() as u64 <= u64::from(u32::MAX)); assert!(variants.len() as u64 <= u64::from(u32::max_value()));
let self_var = &params.self_var; let self_var = &params.self_var;
@@ -350,9 +395,9 @@ fn serialize_variant(
variant: &Variant, variant: &Variant,
variant_index: u32, variant_index: u32,
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Tokens { ) -> TokenStream {
let this = &params.this; let this = &params.this;
let variant_ident = variant.ident; let variant_ident = &variant.ident;
if variant.attrs.skip_serializing() { if variant.attrs.skip_serializing() {
let skipped_msg = format!( let skipped_msg = format!(
@@ -392,12 +437,9 @@ fn serialize_variant(
} }
} }
Style::Struct => { Style::Struct => {
let fields = variant let members = variant.fields.iter().map(|f| &f.member);
.fields
.iter()
.map(|f| f.ident.expect("struct variant has unnamed fields"));
quote! { quote! {
#this::#variant_ident { #(ref #fields),* } #this::#variant_ident { #(ref #members),* }
} }
} }
}; };
@@ -503,7 +545,7 @@ fn serialize_internally_tagged_variant(
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
let enum_ident_str = params.type_name(); let enum_ident_str = params.type_name();
let variant_ident_str = variant.ident.as_ref(); let variant_ident_str = variant.ident.to_string();
if let Some(path) = variant.attrs.serialize_with() { if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, variant); let ser = wrap_serialize_variant_with(params, path, variant);
@@ -594,9 +636,15 @@ fn serialize_adjacently_tagged_variant(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
quote_expr! { return quote_block! {
_serde::Serialize::serialize(#field_expr, __serializer) let mut __struct = try!(_serde::Serializer::serialize_struct(
} __serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, #field_expr));
_serde::ser::SerializeStruct::end(__struct)
};
} }
Style::Tuple => { Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
@@ -619,20 +667,16 @@ fn serialize_adjacently_tagged_variant(
unreachable!() unreachable!()
} }
} }
Style::Newtype => vec![Ident::new("__field0", Span::call_site())], Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
Style::Tuple => (0..variant.fields.len()) Style::Tuple => (0..variant.fields.len())
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site())) .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
.collect(),
Style::Struct => variant
.fields
.iter()
.map(|f| f.ident.expect("struct variant has unnamed fields"))
.collect(), .collect(),
Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
}; };
let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if let Style::Unit = variant.style { let wrapper_generics = if fields_ident.is_empty() {
params.generics.clone() params.generics.clone()
} else { } else {
bound::with_lifetime_bound(&params.generics, "'__a") bound::with_lifetime_bound(&params.generics, "'__a")
@@ -647,7 +691,8 @@ fn serialize_adjacently_tagged_variant(
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
let (#(#fields_ident,)*) = self.data; let (#(#fields_ident,)*) = self.data;
#inner #inner
@@ -725,8 +770,23 @@ fn serialize_tuple_variant(
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait); let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
let len = serialize_stmts.len(); let mut serialized_fields = fields
let let_mut = mut_if(len > 0); .iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|(i, field)| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context { match context {
TupleVariant::ExternallyTagged { TupleVariant::ExternallyTagged {
@@ -775,6 +835,10 @@ fn serialize_struct_variant<'a>(
fields: &[Field], fields: &[Field],
name: &str, name: &str,
) -> Fragment { ) -> Fragment {
if fields.iter().any(|field| field.attrs.flatten()) {
return serialize_struct_variant_with_flatten(context, params, fields, name);
}
let struct_trait = match context { let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant), StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => { StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
@@ -793,10 +857,10 @@ fn serialize_struct_variant<'a>(
let len = serialized_fields let len = serialized_fields
.map(|field| { .map(|field| {
let ident = field.ident.expect("struct has unnamed fields"); let member = &field.member;
match field.attrs.skip_serializing_if() { match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }), Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
None => quote!(1), None => quote!(1),
} }
}) })
@@ -849,15 +913,102 @@ fn serialize_struct_variant<'a>(
} }
} }
fn serialize_struct_variant_with_flatten<'a>(
context: StructVariant<'a>,
params: &Parameters,
fields: &[Field],
name: &str,
) -> Fragment {
let struct_trait = StructTrait::SerializeMap;
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
match context {
StructVariant::ExternallyTagged {
variant_index,
variant_name,
} => {
let this = &params.this;
let fields_ty = fields.iter().map(|f| &f.ty);
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote_block! {
struct __EnumFlatten #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let (#(#members,)*) = self.data;
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
_serde::Serializer::serialize_newtype_variant(
__serializer,
#name,
#variant_index,
#variant_name,
&__EnumFlatten {
data: (#(#members,)*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
})
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
try!(_serde::ser::SerializeMap::serialize_entry(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
}
}
fn serialize_tuple_struct_visitor( fn serialize_tuple_struct_visitor(
fields: &[Field], fields: &[Field],
params: &Parameters, params: &Parameters,
is_enum: bool, is_enum: bool,
tuple_trait: &TupleTrait, tuple_trait: &TupleTrait,
) -> Vec<Tokens> { ) -> Vec<TokenStream> {
fields fields
.iter() .iter()
.enumerate() .enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.map(|(i, field)| { .map(|(i, field)| {
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
let id = Ident::new(&format!("__field{}", i), Span::call_site()); let id = Ident::new(&format!("__field{}", i), Span::call_site());
@@ -901,17 +1052,17 @@ fn serialize_struct_visitor(
params: &Parameters, params: &Parameters,
is_enum: bool, is_enum: bool,
struct_trait: &StructTrait, struct_trait: &StructTrait,
) -> Vec<Tokens> { ) -> Vec<TokenStream> {
fields fields
.iter() .iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.map(|field| { .map(|field| {
let field_ident = field.ident.expect("struct has unnamed field"); let member = &field.member;
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
quote!(#field_ident) quote!(#member)
} else { } else {
get_member(params, field, &Member::Named(field_ident)) get_member(params, field, &member)
}; };
let key_expr = field.attrs.name().serialize_name(); let key_expr = field.attrs.name().serialize_name();
@@ -965,8 +1116,8 @@ fn wrap_serialize_field_with(
params: &Parameters, params: &Parameters,
field_ty: &syn::Type, field_ty: &syn::Type,
serialize_with: &syn::ExprPath, serialize_with: &syn::ExprPath,
field_expr: &Tokens, field_expr: &TokenStream,
) -> Tokens { ) -> TokenStream {
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
} }
@@ -974,16 +1125,18 @@ fn wrap_serialize_variant_with(
params: &Parameters, params: &Parameters,
serialize_with: &syn::ExprPath, serialize_with: &syn::ExprPath,
variant: &Variant, variant: &Variant,
) -> Tokens { ) -> TokenStream {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
let field_exprs: Vec<_> = variant let field_exprs: Vec<_> = variant
.fields .fields
.iter() .iter()
.enumerate() .map(|field| {
.map(|(i, field)| { let id = match field.member {
let id = field Member::Named(ref ident) => ident.clone(),
.ident Member::Unnamed(ref member) => {
.unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::call_site())); Ident::new(&format!("__field{}", member.index), Span::call_site())
}
};
quote!(#id) quote!(#id)
}) })
.collect(); .collect();
@@ -999,8 +1152,8 @@ fn wrap_serialize_with(
params: &Parameters, params: &Parameters,
serialize_with: &syn::ExprPath, serialize_with: &syn::ExprPath,
field_tys: &[&syn::Type], field_tys: &[&syn::Type],
field_exprs: &[Tokens], field_exprs: &[TokenStream],
) -> Tokens { ) -> TokenStream {
let this = &params.this; let this = &params.this;
let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
@@ -1026,7 +1179,8 @@ fn wrap_serialize_with(
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
#serialize_with(#(self.values.#field_access, )* __s) #serialize_with(#(self.values.#field_access, )* __s)
} }
@@ -1045,7 +1199,7 @@ fn wrap_serialize_with(
// _serde::ser::SerializeStruct::end(__serde_state) // _serde::ser::SerializeStruct::end(__serde_state)
// //
// where we want to omit the `mut` to avoid a warning. // where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> { fn mut_if(is_mut: bool) -> Option<TokenStream> {
if is_mut { if is_mut {
Some(quote!(mut)) Some(quote!(mut))
} else { } else {
@@ -1053,12 +1207,12 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
} }
} }
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens { fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
let self_var = &params.self_var; let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) { match (params.is_remote, field.attrs.getter()) {
(false, None) => quote_spanned!(Span::call_site()=> &#self_var.#member), (false, None) => quote!(&#self_var.#member),
(true, None) => { (true, None) => {
let inner = quote_spanned!(Span::call_site()=> &#self_var.#member); let inner = quote!(&#self_var.#member);
let ty = field.ty; let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(#inner)) quote!(_serde::private::ser::constrain::<#ty>(#inner))
} }
@@ -1079,7 +1233,7 @@ enum StructTrait {
} }
impl StructTrait { impl StructTrait {
fn serialize_field(&self, span: Span) -> Tokens { fn serialize_field(&self, span: Span) -> TokenStream {
match *self { match *self {
StructTrait::SerializeMap => { StructTrait::SerializeMap => {
quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry) quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
@@ -1093,7 +1247,7 @@ impl StructTrait {
} }
} }
fn skip_field(&self, span: Span) -> Option<Tokens> { fn skip_field(&self, span: Span) -> Option<TokenStream> {
match *self { match *self {
StructTrait::SerializeMap => None, StructTrait::SerializeMap => None,
StructTrait::SerializeStruct => { StructTrait::SerializeStruct => {
@@ -1113,7 +1267,7 @@ enum TupleTrait {
} }
impl TupleTrait { impl TupleTrait {
fn serialize_element(&self, span: Span) -> Tokens { fn serialize_element(&self, span: Span) -> TokenStream {
match *self { match *self {
TupleTrait::SerializeTuple => { TupleTrait::SerializeTuple => {
quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
+24
View File
@@ -0,0 +1,24 @@
use proc_macro2::{Punct, Spacing, TokenStream};
// None of our generated code requires the `From::from` error conversion
// performed by the standard library's `try!` macro. With this simplified macro
// we see a significant improvement in type checking and borrow checking time of
// the generated code and a slight improvement in binary size.
pub fn replacement() -> TokenStream {
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
let dollar = Punct::new('$', Spacing::Alone);
quote! {
#[allow(unused_macros)]
macro_rules! try {
(#dollar __expr:expr) => {
match #dollar __expr {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
}
}
}
+6 -3
View File
@@ -9,11 +9,14 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/" documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
readme = "README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[lib]
path = "lib.rs"
[dependencies] [dependencies]
proc-macro2 = "0.3" proc-macro2 = "0.4"
syn = { version = "0.13", default-features = false, features = ["derive", "parsing", "clone-impls"] } syn = { version = "0.14", default-features = false, features = ["derive", "parsing", "clone-impls"] }
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -17,11 +17,7 @@ extern crate syn;
extern crate proc_macro2; extern crate proc_macro2;
pub mod ast; #[path = "src/mod.rs"]
pub mod attr; mod internals;
mod ctxt; pub use internals::*;
pub use ctxt::Ctxt;
mod case;
mod check;
+1
View File
@@ -0,0 +1 @@
../serde_derive/src/internals/
+3 -3
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.41" # remember to update html_root_url version = "1.0.61" # 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"
@@ -12,10 +12,10 @@ readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies] [dependencies]
serde = { version = "1.0.16", path = "../serde" } serde = { version = "1.0.60", path = "../serde" }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0.16", path = "../serde", features = ["rc"] } serde = { version = "1.0", path = "../serde", features = ["rc"] }
serde_derive = { version = "1.0", path = "../serde_derive" } serde_derive = { version = "1.0", path = "../serde_derive" }
[badges] [badges]
+12 -5
View File
@@ -1,7 +1,9 @@
use std::fmt; use std::fmt;
use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, use serde::ser::{
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant}; SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
SerializeTupleStruct, SerializeTupleVariant,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
@@ -24,7 +26,8 @@ pub struct Compact<T: ?Sized>(T);
/// ///
/// impl Serialize for Example { /// impl Serialize for Example {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer, /// where
/// S: Serializer,
/// { /// {
/// if serializer.is_human_readable() { /// if serializer.is_human_readable() {
/// format!("{}.{}", self.0, self.1).serialize(serializer) /// format!("{}.{}", self.0, self.1).serialize(serializer)
@@ -36,7 +39,8 @@ pub struct Compact<T: ?Sized>(T);
/// ///
/// impl<'de> Deserialize<'de> for Example { /// impl<'de> Deserialize<'de> for Example {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> /// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>, /// where
/// D: Deserializer<'de>,
/// { /// {
/// use serde::de::Error; /// use serde::de::Error;
/// if deserializer.is_human_readable() { /// if deserializer.is_human_readable() {
@@ -476,7 +480,10 @@ use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, Varian
macro_rules! forward_deserialize_methods { macro_rules! forward_deserialize_methods {
( $wrapper : ident ( $( $name: ident ),* ) ) => { ( $wrapper : ident ( $( $name: ident ),* ) ) => {
$( $(
fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error> where V: Visitor<'de> { fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
(self.0).$name($wrapper(visitor)) (self.0).$name($wrapper(visitor))
} }
)* )*
+11 -8
View File
@@ -7,8 +7,10 @@
// except according to those terms. // except according to those terms.
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer}; use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, use serde::de::{
SeqAccess, VariantAccess, Visitor}; self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use error::Error; use error::Error;
use token::Token; use token::Token;
@@ -127,8 +129,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error; type Error = Error;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf unit seq map identifier ignored_any bytes byte_buf unit seq map identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -597,7 +599,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
{ {
match self.variant.take() { match self.variant.take() {
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => seed.deserialize(BytesDeserializer { value: variant }) Some(Token::Bytes(variant)) => seed
.deserialize(BytesDeserializer { value: variant })
.map(Some), .map(Some),
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => unexpected!(other), Some(other) => unexpected!(other),
@@ -654,8 +657,8 @@ impl<'de> de::Deserializer<'de> for BytesDeserializer {
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
+20 -12
View File
@@ -68,11 +68,13 @@
//! # } //! # }
//! # //! #
//! # impl<K, V> Serialize for LinkedHashMap<K, V> //! # impl<K, V> Serialize for LinkedHashMap<K, V>
//! # where K: Serialize, //! # where
//! # V: Serialize //! # K: Serialize,
//! # V: Serialize,
//! # { //! # {
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> //! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//! # where S: Serializer //! # where
//! # S: Serializer,
//! # { //! # {
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?; //! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
//! # for &(ref k, ref v) in &self.0 { //! # for &(ref k, ref v) in &self.0 {
@@ -85,8 +87,9 @@
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>); //! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
//! # //! #
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V> //! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
//! # where K: Deserialize<'de>, //! # where
//! # V: Deserialize<'de> //! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # { //! # {
//! # type Value = LinkedHashMap<K, V>; //! # type Value = LinkedHashMap<K, V>;
//! # //! #
@@ -95,7 +98,8 @@
//! # } //! # }
//! # //! #
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> //! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
//! # where M: MapAccess<'de> //! # where
//! # M: MapAccess<'de>,
//! # { //! # {
//! # let mut map = LinkedHashMap::new(); //! # let mut map = LinkedHashMap::new();
//! # while let Some((key, value)) = access.next_entry()? { //! # while let Some((key, value)) = access.next_entry()? {
@@ -106,11 +110,13 @@
//! # } //! # }
//! # //! #
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V> //! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
//! # where K: Deserialize<'de>, //! # where
//! # V: Deserialize<'de> //! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # { //! # {
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> //! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//! # where D: Deserializer<'de> //! # where
//! # D: Deserializer<'de>,
//! # { //! # {
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData)) //! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
//! # } //! # }
@@ -155,7 +161,7 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.41")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.61")]
#![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))]
@@ -179,8 +185,10 @@ mod assert;
mod configure; mod configure;
mod token; mod token;
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, pub use assert::{
assert_ser_tokens_error, assert_tokens}; assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens,
};
pub use token::Token; pub use token::Token;
pub use configure::{Compact, Configure, Readable}; pub use configure::{Compact, Configure, Readable};
+1 -1
View File
@@ -9,7 +9,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies] [dev-dependencies]
fnv = "1.0" fnv = "1.0"
proc-macro2 = "0.3" 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"] }
+13 -7
View File
@@ -1,8 +1,9 @@
use serde::de::{Deserializer, Visitor, SeqAccess, Error}; use serde::de::{Deserializer, Error, SeqAccess, Visitor};
use std::fmt; use std::fmt;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error> pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where D: Deserializer<'de> where
D: Deserializer<'de>,
{ {
deserializer.deserialize_byte_buf(ByteBufVisitor) deserializer.deserialize_byte_buf(ByteBufVisitor)
} }
@@ -17,7 +18,8 @@ impl<'de> Visitor<'de> for ByteBufVisitor {
} }
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: SeqAccess<'de> where
V: SeqAccess<'de>,
{ {
let mut values = Vec::new(); let mut values = Vec::new();
while let Some(value) = try!(visitor.next_element()) { while let Some(value) = try!(visitor.next_element()) {
@@ -27,25 +29,29 @@ impl<'de> Visitor<'de> for ByteBufVisitor {
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where E: Error where
E: Error,
{ {
Ok(v.to_vec()) Ok(v.to_vec())
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where E: Error where
E: Error,
{ {
Ok(v) Ok(v)
} }
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: Error where
E: Error,
{ {
Ok(v.as_bytes().to_vec()) Ok(v.as_bytes().to_vec())
} }
fn visit_string<E>(self, v: String) -> Result<Self::Value, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where E: Error where
E: Error,
{ {
Ok(v.into_bytes()) Ok(v.into_bytes())
} }
@@ -0,0 +1,15 @@
// 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.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct S<'de> {
s: &'de str, //~^^ HELP: cannot deserialize when there is a lifetime parameter called 'de
}
@@ -0,0 +1,16 @@
// 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.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct S {
string: String,
slice: [u8], //~^^^ HELP: cannot deserialize a dynamically sized struct
}
@@ -10,12 +10,11 @@
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
//~^ HELP: #[serde(flatten)] cannot be used within enums #[serde(transparent)]
enum Foo { struct S {
A { //~^^^ HELP: #[serde(transparent)] requires struct to have at most one transparent field
#[serde(flatten)] a: u8,
fields: HashMap<String, String>, b: u8,
}
} }
fn main() {} fn main() {}
@@ -0,0 +1,22 @@
// 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.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(transparent)]
struct S {
//~^^^ HELP: #[serde(transparent)] requires at least one field that is neither skipped nor has a default
#[serde(skip)]
a: u8,
#[serde(default)]
b: u8,
}
fn main() {}
@@ -0,0 +1,20 @@
// 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.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(transparent)]
struct S {
//~^^^ HELP: #[serde(transparent)] requires at least one field that is not skipped
#[serde(skip)]
a: u8,
}
fn main() {}
+461 -58
View File
@@ -12,13 +12,16 @@
extern crate serde_derive; extern crate serde_derive;
extern crate serde; extern crate serde;
use std::collections::HashMap;
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
use self::serde::de::{self, Unexpected}; use self::serde::de::{self, Unexpected};
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
use std::marker::PhantomData;
extern crate serde_test; extern crate serde_test;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, use self::serde_test::{
assert_ser_tokens_error, assert_tokens, Token}; assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens, Token,
};
trait MyDefault: Sized { trait MyDefault: Sized {
fn my_default() -> Self; fn my_default() -> Self;
@@ -114,10 +117,7 @@ struct FlattenStructEnumWrapper {
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
enum FlattenStructEnum { enum FlattenStructEnum {
InsertInteger { InsertInteger { index: u32, value: u32 },
index: u32,
value: u32
},
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -133,10 +133,7 @@ struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")] #[serde(rename_all = "snake_case", tag = "type", content = "value")]
enum FlattenStructTagContentEnum { enum FlattenStructTagContentEnum {
InsertInteger { InsertInteger { index: u32, value: u32 },
index: u32,
value: u32
},
NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant), NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
} }
@@ -529,12 +526,10 @@ enum RenameEnumSerializeDeserialize<A> {
fn test_rename_enum() { fn test_rename_enum() {
assert_tokens( assert_tokens(
&RenameEnum::Batman, &RenameEnum::Batman,
&[ &[Token::UnitVariant {
Token::UnitVariant { name: "Superhero",
name: "Superhero", variant: "bruce_wayne",
variant: "bruce_wayne", }],
},
],
); );
assert_tokens( assert_tokens(
@@ -663,6 +658,44 @@ fn test_skip_serializing_struct() {
); );
} }
#[derive(Debug, PartialEq, Serialize)]
struct SkipSerializingTupleStruct<'a, B, C>(
&'a i8,
#[serde(skip_serializing)] B,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")] C,
)
where
C: ShouldSkip;
#[test]
fn test_skip_serializing_tuple_struct() {
let a = 1;
assert_ser_tokens(
&SkipSerializingTupleStruct(&a, 2, 3),
&[
Token::TupleStruct {
name: "SkipSerializingTupleStruct",
len: 2,
},
Token::I8(1),
Token::I32(3),
Token::TupleStructEnd,
],
);
assert_ser_tokens(
&SkipSerializingTupleStruct(&a, 2, 123),
&[
Token::TupleStruct {
name: "SkipSerializingTupleStruct",
len: 1,
},
Token::I8(1),
Token::TupleStructEnd,
],
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
struct SkipStruct<B> { struct SkipStruct<B> {
a: i8, a: i8,
@@ -711,6 +744,11 @@ where
#[serde(skip_serializing_if = "ShouldSkip::should_skip")] #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
c: C, c: C,
}, },
Tuple(
&'a i8,
#[serde(skip_serializing)] B,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")] C,
),
} }
#[test] #[test]
@@ -749,6 +787,33 @@ fn test_skip_serializing_enum() {
Token::StructVariantEnd, Token::StructVariantEnd,
], ],
); );
assert_ser_tokens(
&SkipSerializingEnum::Tuple(&a, 2, 3),
&[
Token::TupleVariant {
name: "SkipSerializingEnum",
variant: "Tuple",
len: 2,
},
Token::I8(1),
Token::I32(3),
Token::TupleVariantEnd,
],
);
assert_ser_tokens(
&SkipSerializingEnum::Tuple(&a, 2, 123),
&[
Token::TupleVariant {
name: "SkipSerializingEnum",
variant: "Tuple",
len: 1,
},
Token::I8(1),
Token::TupleVariantEnd,
],
);
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@@ -1221,12 +1286,7 @@ fn test_missing_renamed_field_enum() {
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
enum InvalidLengthEnum { enum InvalidLengthEnum {
A(i32, i32, i32), A(i32, i32, i32),
B( B(#[serde(skip_deserializing)] i32, i32, i32),
#[serde(skip_deserializing)]
i32,
i32,
i32,
),
} }
#[test] #[test]
@@ -1241,7 +1301,7 @@ fn test_invalid_length_enum() {
Token::I32(1), Token::I32(1),
Token::TupleVariantEnd, Token::TupleVariantEnd,
], ],
"invalid length 1, expected tuple of 3 elements", "invalid length 1, expected tuple variant InvalidLengthEnum::A with 3 elements",
); );
assert_de_tokens_error::<InvalidLengthEnum>( assert_de_tokens_error::<InvalidLengthEnum>(
&[ &[
@@ -1253,7 +1313,7 @@ fn test_invalid_length_enum() {
Token::I32(1), Token::I32(1),
Token::TupleVariantEnd, Token::TupleVariantEnd,
], ],
"invalid length 1, expected tuple of 2 elements", "invalid length 1, expected tuple variant InvalidLengthEnum::B with 2 elements",
); );
} }
@@ -1345,7 +1405,7 @@ fn test_flatten_struct_enum() {
let change_request = FlattenStructEnumWrapper { let change_request = FlattenStructEnumWrapper {
data: FlattenStructEnum::InsertInteger { data: FlattenStructEnum::InsertInteger {
index: 0, index: 0,
value: 42 value: 42,
}, },
extra, extra,
}; };
@@ -1362,7 +1422,7 @@ fn test_flatten_struct_enum() {
Token::MapEnd, Token::MapEnd,
Token::Str("extra_key"), Token::Str("extra_key"),
Token::Str("extra value"), Token::Str("extra value"),
Token::MapEnd Token::MapEnd,
], ],
); );
assert_ser_tokens( assert_ser_tokens(
@@ -1370,7 +1430,10 @@ fn test_flatten_struct_enum() {
&[ &[
Token::Map { len: None }, Token::Map { len: None },
Token::Str("insert_integer"), Token::Str("insert_integer"),
Token::Struct { len: 2, name: "insert_integer" }, Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"), Token::Str("index"),
Token::U32(0), Token::U32(0),
Token::Str("value"), Token::Str("value"),
@@ -1378,7 +1441,7 @@ fn test_flatten_struct_enum() {
Token::StructEnd, Token::StructEnd,
Token::Str("extra_key"), Token::Str("extra_key"),
Token::Str("extra value"), Token::Str("extra value"),
Token::MapEnd Token::MapEnd,
], ],
); );
} }
@@ -1387,12 +1450,10 @@ fn test_flatten_struct_enum() {
fn test_flatten_struct_tag_content_enum() { fn test_flatten_struct_tag_content_enum() {
let change_request = FlattenStructTagContentEnumWrapper { let change_request = FlattenStructTagContentEnumWrapper {
outer: 42, outer: 42,
data: FlattenStructTagContentEnumNewtype( data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
FlattenStructTagContentEnum::InsertInteger { index: 0,
index: 0, value: 42,
value: 42 }),
}
),
}; };
assert_de_tokens( assert_de_tokens(
&change_request, &change_request,
@@ -1421,7 +1482,10 @@ fn test_flatten_struct_tag_content_enum() {
Token::Str("type"), Token::Str("type"),
Token::Str("insert_integer"), Token::Str("insert_integer"),
Token::Str("value"), Token::Str("value"),
Token::Struct { len: 2, name: "insert_integer" }, Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"), Token::Str("index"),
Token::U32(0), Token::U32(0),
Token::Str("value"), Token::Str("value"),
@@ -1436,13 +1500,9 @@ fn test_flatten_struct_tag_content_enum() {
fn test_flatten_struct_tag_content_enum_newtype() { fn test_flatten_struct_tag_content_enum_newtype() {
let change_request = FlattenStructTagContentEnumWrapper { let change_request = FlattenStructTagContentEnumWrapper {
outer: 42, outer: 42,
data: FlattenStructTagContentEnumNewtype( data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
FlattenStructTagContentEnum::NewtypeVariant( FlattenStructTagContentEnumNewtypeVariant { value: 23 },
FlattenStructTagContentEnumNewtypeVariant { )),
value: 23
}
)
),
}; };
assert_de_tokens( assert_de_tokens(
&change_request, &change_request,
@@ -1469,7 +1529,10 @@ fn test_flatten_struct_tag_content_enum_newtype() {
Token::Str("type"), Token::Str("type"),
Token::Str("newtype_variant"), Token::Str("newtype_variant"),
Token::Str("value"), Token::Str("value"),
Token::Struct { len: 1, name: "FlattenStructTagContentEnumNewtypeVariant" }, Token::Struct {
len: 1,
name: "FlattenStructTagContentEnumNewtypeVariant",
},
Token::Str("value"), Token::Str("value"),
Token::U32(23), Token::U32(23),
Token::StructEnd, Token::StructEnd,
@@ -1525,7 +1588,7 @@ fn test_complex_flatten() {
first: First, first: First,
#[serde(flatten)] #[serde(flatten)]
second: Second, second: Second,
z: u32 z: u32,
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -1552,10 +1615,8 @@ fn test_complex_flatten() {
d: "c".into(), d: "c".into(),
e: Some(2), e: Some(2),
}, },
second: Second { second: Second { f: 3 },
f: 3 z: 4,
},
z: 4
}, },
&[ &[
Token::Map { len: None }, Token::Map { len: None },
@@ -1592,10 +1653,8 @@ fn test_complex_flatten() {
d: "c".into(), d: "c".into(),
e: Some(2), e: Some(2),
}, },
second: Second { second: Second { f: 3 },
f: 3 z: 4,
},
z: 4
}, },
&[ &[
Token::Map { len: None }, Token::Map { len: None },
@@ -1652,7 +1711,7 @@ fn test_flatten_unsupported_type() {
Token::Str("foo"), Token::Str("foo"),
Token::Str("a"), Token::Str("a"),
Token::Str("b"), Token::Str("b"),
Token::MapEnd Token::MapEnd,
], ],
"can only flatten structs and maps", "can only flatten structs and maps",
); );
@@ -1671,7 +1730,11 @@ fn test_non_string_keys() {
let mut mapping = HashMap::new(); let mut mapping = HashMap::new();
mapping.insert(0, 42); mapping.insert(0, 42);
assert_tokens( assert_tokens(
&TestStruct { name: "peter".into(), age: 3, mapping }, &TestStruct {
name: "peter".into(),
age: 3,
mapping,
},
&[ &[
Token::Map { len: None }, Token::Map { len: None },
Token::Str("name"), Token::Str("name"),
@@ -1720,7 +1783,9 @@ fn test_lifetime_propagation_for_flatten() {
let mut borrowed_map = HashMap::new(); let mut borrowed_map = HashMap::new();
borrowed_map.insert("x", 42u32); borrowed_map.insert("x", 42u32);
assert_ser_tokens( assert_ser_tokens(
&B { t: borrowed_map.clone() }, &B {
t: borrowed_map.clone(),
},
&[ &[
Token::Map { len: None }, Token::Map { len: None },
Token::BorrowedStr("x"), Token::BorrowedStr("x"),
@@ -1742,7 +1807,9 @@ fn test_lifetime_propagation_for_flatten() {
let mut borrowed_map = HashMap::new(); let mut borrowed_map = HashMap::new();
borrowed_map.insert(&b"x"[..], 42u32); borrowed_map.insert(&b"x"[..], 42u32);
assert_ser_tokens( assert_ser_tokens(
&C { t: borrowed_map.clone() }, &C {
t: borrowed_map.clone(),
},
&[ &[
Token::Map { len: None }, Token::Map { len: None },
Token::Seq { len: Some(1) }, Token::Seq { len: Some(1) },
@@ -1797,3 +1864,339 @@ fn test_flatten_enum_newtype() {
], ],
); );
} }
#[test]
fn test_flatten_internally_tagged() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
let s = S {
x: X::B { b: 1 },
y: Y::D { d: 2 },
};
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn test_externally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::NewtypeVariant {
name: "Data",
variant: "A",
},
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_internally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t")]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("t"),
Token::Str("A"),
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_adjacently_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t", content = "c")]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::Struct {
name: "Data",
len: 2,
},
Token::Str("t"),
Token::Str("A"),
Token::Str("c"),
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
Token::StructEnd,
],
);
}
#[test]
fn test_untagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_untagged_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Outer {
#[serde(flatten)]
inner: Inner,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Inner {
Variant { a: i32 },
}
let data = Outer {
inner: Inner::Variant { a: 0 },
};
assert_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_option() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Outer {
#[serde(flatten)]
inner1: Option<Inner1>,
#[serde(flatten)]
inner2: Option<Inner2>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Inner1 {
inner1: i32,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Inner2 {
inner2: i32,
}
assert_tokens(
&Outer {
inner1: Some(Inner1 { inner1: 1 }),
inner2: Some(Inner2 { inner2: 2 }),
},
&[
Token::Map { len: None },
Token::Str("inner1"),
Token::I32(1),
Token::Str("inner2"),
Token::I32(2),
Token::MapEnd,
],
);
assert_tokens(
&Outer {
inner1: Some(Inner1 { inner1: 1 }),
inner2: None,
},
&[
Token::Map { len: None },
Token::Str("inner1"),
Token::I32(1),
Token::MapEnd,
],
);
assert_tokens(
&Outer {
inner1: None,
inner2: Some(Inner2 { inner2: 2 }),
},
&[
Token::Map { len: None },
Token::Str("inner2"),
Token::I32(2),
Token::MapEnd,
],
);
assert_tokens(
&Outer {
inner1: None,
inner2: None,
},
&[Token::Map { len: None }, Token::MapEnd],
);
}
#[test]
fn test_transparent_struct() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(transparent)]
struct Transparent {
#[serde(skip)]
a: bool,
b: u32,
#[serde(skip)]
c: bool,
d: PhantomData<()>,
}
assert_tokens(
&Transparent {
a: false,
b: 1,
c: false,
d: PhantomData,
},
&[Token::U32(1)],
);
}
#[test]
fn test_transparent_tuple_struct() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(transparent)]
struct Transparent(
#[serde(skip)] bool,
u32,
#[serde(skip)] bool,
PhantomData<()>,
);
assert_tokens(&Transparent(false, 1, false, PhantomData), &[Token::U32(1)]);
}
+70 -6
View File
@@ -12,20 +12,20 @@
extern crate serde_derive; extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::time::{Duration, UNIX_EPOCH};
use std::default::Default; use std::default::Default;
use std::ffi::{CString, OsString}; use std::ffi::{CString, OsString};
use std::rc::Rc; use std::net;
use std::sync::Arc;
use std::num::Wrapping; use std::num::Wrapping;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use std::ffi::CStr; use std::ffi::CStr;
extern crate serde; extern crate serde;
use serde::Deserialize; use serde::{Deserialize, Deserializer};
extern crate fnv; extern crate fnv;
use self::fnv::FnvHasher; use self::fnv::FnvHasher;
@@ -182,6 +182,27 @@ macro_rules! declare_error_tests {
} }
} }
#[derive(Debug)]
struct SkipPartialEq<T>(T);
impl<'de, T> Deserialize<'de> for SkipPartialEq<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(SkipPartialEq)
}
}
impl<T> PartialEq for SkipPartialEq<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) {
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
struct IgnoreBase { struct IgnoreBase {
@@ -238,6 +259,27 @@ declare_tests! {
0f32 => &[Token::F32(0.)], 0f32 => &[Token::F32(0.)],
0f64 => &[Token::F64(0.)], 0f64 => &[Token::F64(0.)],
} }
test_small_int_to_128 {
1i128 => &[Token::I8(1)],
1i128 => &[Token::I16(1)],
1i128 => &[Token::I32(1)],
1i128 => &[Token::I64(1)],
1i128 => &[Token::U8(1)],
1i128 => &[Token::U16(1)],
1i128 => &[Token::U32(1)],
1i128 => &[Token::U64(1)],
1u128 => &[Token::I8(1)],
1u128 => &[Token::I16(1)],
1u128 => &[Token::I32(1)],
1u128 => &[Token::I64(1)],
1u128 => &[Token::U8(1)],
1u128 => &[Token::U16(1)],
1u128 => &[Token::U32(1)],
1u128 => &[Token::U64(1)],
}
test_char { test_char {
'a' => &[Token::Char('a')], 'a' => &[Token::Char('a')],
'a' => &[Token::Str("a")], 'a' => &[Token::Str("a")],
@@ -788,11 +830,33 @@ declare_tests! {
Token::Bool(true), Token::Bool(true),
], ],
} }
test_rc_weak_some {
SkipPartialEq(RcWeak::<bool>::new()) => &[
Token::Some,
Token::Bool(true),
],
}
test_rc_weak_none {
SkipPartialEq(RcWeak::<bool>::new()) => &[
Token::None,
],
}
test_arc { test_arc {
Arc::new(true) => &[ Arc::new(true) => &[
Token::Bool(true), Token::Bool(true),
], ],
} }
test_arc_weak_some {
SkipPartialEq(ArcWeak::<bool>::new()) => &[
Token::Some,
Token::Bool(true),
],
}
test_arc_weak_none {
SkipPartialEq(ArcWeak::<bool>::new()) => &[
Token::None,
],
}
test_wrapping { test_wrapping {
Wrapping(1usize) => &[ Wrapping(1usize) => &[
Token::U32(1), Token::U32(1),
+134 -44
View File
@@ -17,8 +17,8 @@
extern crate serde_derive; extern crate serde_derive;
extern crate serde; extern crate serde;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{DeserializeOwned, Deserializer}; use self::serde::de::{DeserializeOwned, Deserializer};
use self::serde::ser::{Serialize, Serializer};
use std::borrow::Cow; use std::borrow::Cow;
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -92,14 +92,10 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
enum EnumWith<T> { enum EnumWith<T> {
Unit, Unit,
Newtype( Newtype(#[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X),
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X,
),
Tuple( Tuple(
T, T,
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X,
X,
), ),
Struct { Struct {
t: T, t: T,
@@ -122,17 +118,13 @@ fn test_gen() {
assert_ser::<MultipleRef<i32>>(); assert_ser::<MultipleRef<i32>>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Newtype( struct Newtype(#[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X);
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X,
);
assert::<Newtype>(); assert::<Newtype>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Tuple<T>( struct Tuple<T>(
T, T,
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X,
X,
); );
assert::<Tuple<i32>>(); assert::<Tuple<i32>>();
@@ -191,12 +183,16 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(bound = "D: SerializeWith + DeserializeWith")] #[serde(bound = "D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> { struct WithTraits1<D, E> {
#[serde(serialize_with = "SerializeWith::serialize_with", #[serde(
deserialize_with = "DeserializeWith::deserialize_with")] serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with"
)]
d: D, d: D,
#[serde(serialize_with = "SerializeWith::serialize_with", #[serde(
deserialize_with = "DeserializeWith::deserialize_with", serialize_with = "SerializeWith::serialize_with",
bound = "E: SerializeWith + DeserializeWith")] deserialize_with = "DeserializeWith::deserialize_with",
bound = "E: SerializeWith + DeserializeWith"
)]
e: E, e: E,
} }
assert::<WithTraits1<X, X>>(); assert::<WithTraits1<X, X>>();
@@ -204,17 +200,58 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))] #[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
struct WithTraits2<D, E> { struct WithTraits2<D, E> {
#[serde(serialize_with = "SerializeWith::serialize_with", #[serde(
deserialize_with = "DeserializeWith::deserialize_with")] serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with"
)]
d: D, d: D,
#[serde(serialize_with = "SerializeWith::serialize_with", #[serde(
bound(serialize = "E: SerializeWith"))] serialize_with = "SerializeWith::serialize_with", bound(serialize = "E: SerializeWith")
#[serde(deserialize_with = "DeserializeWith::deserialize_with", )]
bound(deserialize = "E: DeserializeWith"))] #[serde(
deserialize_with = "DeserializeWith::deserialize_with",
bound(deserialize = "E: DeserializeWith")
)]
e: E, e: E,
} }
assert::<WithTraits2<X, X>>(); assert::<WithTraits2<X, X>>();
#[derive(Serialize, Deserialize)]
#[serde(bound = "D: SerializeWith + DeserializeWith")]
enum VariantWithTraits1<D, E> {
#[serde(
serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with"
)]
D(D),
#[serde(
serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with",
bound = "E: SerializeWith + DeserializeWith"
)]
E(E),
}
assert::<VariantWithTraits1<X, X>>();
#[derive(Serialize, Deserialize)]
#[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
enum VariantWithTraits2<D, E> {
#[serde(
serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with"
)]
D(D),
#[serde(
serialize_with = "SerializeWith::serialize_with", bound(serialize = "E: SerializeWith")
)]
#[serde(
deserialize_with = "DeserializeWith::deserialize_with",
bound(deserialize = "E: DeserializeWith")
)]
E(E),
}
assert::<VariantWithTraits2<X, X>>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct CowStr<'a>(Cow<'a, str>); struct CowStr<'a>(Cow<'a, str>);
assert::<CowStr>(); assert::<CowStr>();
@@ -270,17 +307,11 @@ fn test_gen() {
struct EmptyTupleDenyUnknown(); struct EmptyTupleDenyUnknown();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct TupleSkipAll( struct TupleSkipAll(#[serde(skip_deserializing)] u8);
#[serde(skip_deserializing)]
u8,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct TupleSkipAllDenyUnknown( struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
#[serde(skip_deserializing)]
u8,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
enum EmptyEnum {} enum EmptyEnum {}
@@ -305,10 +336,7 @@ fn test_gen() {
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
f: u8, f: u8,
}, },
TupleSkip( TupleSkip(#[serde(skip_deserializing)] u8),
#[serde(skip_deserializing)]
u8,
),
} }
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
@@ -321,10 +349,7 @@ fn test_gen() {
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
f: u8, f: u8,
}, },
TupleSkip( TupleSkip(#[serde(skip_deserializing)] u8),
#[serde(skip_deserializing)]
u8,
),
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -344,9 +369,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(untagged, remote = "Or")] #[serde(untagged, remote = "Or")]
enum OrDef<A, B> { enum OrDef<A, B> {
#[allow(dead_code)]
A(A), A(A),
#[allow(dead_code)]
B(B), B(B),
} }
@@ -503,6 +526,13 @@ fn test_gen() {
} }
assert_ser::<UntaggedVariantWith>(); assert_ser::<UntaggedVariantWith>();
#[derive(Serialize, Deserialize)]
struct FlattenWith {
#[serde(flatten, serialize_with = "ser_x", deserialize_with = "de_x")]
x: X,
}
assert::<FlattenWith>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct StaticStrStruct<'a> { struct StaticStrStruct<'a> {
a: &'a str, a: &'a str,
@@ -531,7 +561,9 @@ fn test_gen() {
assert::<SkippedStaticStr>(); assert::<SkippedStaticStr>();
macro_rules! T { macro_rules! T {
() => { () } () => {
()
};
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -559,7 +591,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct AssocDerive<T: AssocSerde> { struct AssocDerive<T: AssocSerde> {
assoc: T::Assoc assoc: T::Assoc,
} }
assert::<AssocDerive<NoSerdeImpl>>(); assert::<AssocDerive<NoSerdeImpl>>();
@@ -571,6 +603,64 @@ fn test_gen() {
} }
assert::<AssocDeriveMulti<i32, NoSerdeImpl>>(); assert::<AssocDeriveMulti<i32, NoSerdeImpl>>();
#[derive(Serialize)]
#[serde(tag = "t", content = "c")]
enum EmptyAdjacentlyTagged {
#[allow(dead_code)]
Struct {},
#[allow(dead_code)]
Tuple(),
}
assert_ser::<EmptyAdjacentlyTagged>();
mod restricted {
mod inner {
#[derive(Serialize, Deserialize)]
struct Restricted {
pub(super) a: usize,
pub(in super::inner) b: usize,
}
}
}
#[derive(Deserialize)]
#[serde(tag = "t", content = "c")]
enum AdjacentlyTaggedVoid {}
#[derive(Serialize, Deserialize)]
enum SkippedVariant<T> {
#[serde(skip)]
#[allow(dead_code)]
T(T),
Unit,
}
assert::<SkippedVariant<X>>();
#[derive(Deserialize)]
struct ImpliciltyBorrowedOption<'a> {
option: std::option::Option<&'a str>,
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum UntaggedNewtypeVariantWith {
Newtype(
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
X,
),
}
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct TransparentWith {
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
x: X,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+88 -35
View File
@@ -7,7 +7,6 @@
// except according to those terms. // except according to those terms.
#![deny(trivial_numeric_casts)] #![deny(trivial_numeric_casts)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))] #![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
#[macro_use] #[macro_use]
@@ -18,8 +17,9 @@ extern crate serde_test;
mod bytes; mod bytes;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, use self::serde_test::{
Token}; assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token,
};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -226,12 +226,10 @@ fn test_de_named_map() {
fn test_ser_enum_unit() { fn test_ser_enum_unit() {
assert_ser_tokens( assert_ser_tokens(
&SerEnum::Unit::<u32, u32, u32>, &SerEnum::Unit::<u32, u32, u32>,
&[ &[Token::UnitVariant {
Token::UnitVariant { name: "SerEnum",
name: "SerEnum", variant: "Unit",
variant: "Unit", }],
},
],
); );
} }
@@ -296,12 +294,10 @@ fn test_ser_enum_map() {
fn test_de_enum_unit() { fn test_de_enum_unit() {
assert_tokens( assert_tokens(
&DeEnum::Unit::<u32, u32, u32>, &DeEnum::Unit::<u32, u32, u32>,
&[ &[Token::UnitVariant {
Token::UnitVariant { name: "DeEnum",
name: "DeEnum", variant: "Unit",
variant: "Unit", }],
},
],
); );
} }
@@ -446,6 +442,51 @@ fn test_generic_newtype_struct() {
); );
} }
#[test]
fn test_untagged_newtype_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum E {
Newtype(GenericNewTypeStruct<u32>),
Null,
}
assert_tokens(
&E::Newtype(GenericNewTypeStruct(5u32)),
&[
Token::NewtypeStruct {
name: "GenericNewTypeStruct",
},
Token::U32(5),
],
);
}
#[test]
fn test_adjacently_tagged_newtype_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "t", content = "c")]
enum E {
Newtype(GenericNewTypeStruct<u32>),
Null,
}
assert_de_tokens(
&E::Newtype(GenericNewTypeStruct(5u32)),
&[
Token::Struct { name: "E", len: 2 },
Token::Str("c"),
Token::NewtypeStruct {
name: "GenericNewTypeStruct",
},
Token::U32(5),
Token::Str("t"),
Token::Str("Newtype"),
Token::StructEnd,
],
);
}
#[test] #[test]
fn test_generic_tuple_struct() { fn test_generic_tuple_struct() {
assert_tokens( assert_tokens(
@@ -466,12 +507,10 @@ fn test_generic_tuple_struct() {
fn test_generic_enum_unit() { fn test_generic_enum_unit() {
assert_tokens( assert_tokens(
&GenericEnum::Unit::<u32, u32>, &GenericEnum::Unit::<u32, u32>,
&[ &[Token::UnitVariant {
Token::UnitVariant { name: "GenericEnum",
name: "GenericEnum", variant: "Unit",
variant: "Unit", }],
},
],
); );
} }
@@ -798,7 +837,9 @@ fn test_internally_tagged_bytes() {
} }
assert_de_tokens( assert_de_tokens(
&InternallyTagged::String { string: "\0".to_owned() }, &InternallyTagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "String", name: "String",
@@ -813,7 +854,9 @@ fn test_internally_tagged_bytes() {
); );
assert_de_tokens( assert_de_tokens(
&InternallyTagged::String { string: "\0".to_owned() }, &InternallyTagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "String", name: "String",
@@ -828,7 +871,9 @@ fn test_internally_tagged_bytes() {
); );
assert_de_tokens( assert_de_tokens(
&InternallyTagged::String { string: "\0".to_owned() }, &InternallyTagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "String", name: "String",
@@ -843,7 +888,9 @@ fn test_internally_tagged_bytes() {
); );
assert_de_tokens( assert_de_tokens(
&InternallyTagged::String { string: "\0".to_owned() }, &InternallyTagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "String", name: "String",
@@ -1354,12 +1401,10 @@ fn test_enum_in_untagged_enum() {
assert_tokens( assert_tokens(
&Outer::Inner(Inner::Unit), &Outer::Inner(Inner::Unit),
&[ &[Token::UnitVariant {
Token::UnitVariant { name: "Inner",
name: "Inner", variant: "Unit",
variant: "Unit", }],
},
],
); );
assert_tokens( assert_tokens(
@@ -1417,7 +1462,9 @@ fn test_untagged_bytes() {
} }
assert_de_tokens( assert_de_tokens(
&Untagged::String { string: "\0".to_owned() }, &Untagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "Untagged", name: "Untagged",
@@ -1430,7 +1477,9 @@ fn test_untagged_bytes() {
); );
assert_de_tokens( assert_de_tokens(
&Untagged::String { string: "\0".to_owned() }, &Untagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "Untagged", name: "Untagged",
@@ -1443,7 +1492,9 @@ fn test_untagged_bytes() {
); );
assert_de_tokens( assert_de_tokens(
&Untagged::String { string: "\0".to_owned() }, &Untagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "Untagged", name: "Untagged",
@@ -1456,7 +1507,9 @@ fn test_untagged_bytes() {
); );
assert_de_tokens( assert_de_tokens(
&Untagged::String { string: "\0".to_owned() }, &Untagged::String {
string: "\0".to_owned(),
},
&[ &[
Token::Struct { Token::Struct {
name: "Untagged", name: "Untagged",
+6 -23
View File
@@ -121,10 +121,7 @@ struct UnitDef;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePriv")] #[serde(remote = "remote::PrimitivePriv")]
struct PrimitivePrivDef( struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
#[serde(getter = "remote::PrimitivePriv::get")]
u8,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePub")] #[serde(remote = "remote::PrimitivePub")]
@@ -132,34 +129,22 @@ struct PrimitivePubDef(u8);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePriv")] #[serde(remote = "remote::NewtypePriv")]
struct NewtypePrivDef( struct NewtypePrivDef(#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit);
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePub")] #[serde(remote = "remote::NewtypePub")]
struct NewtypePubDef( struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
#[serde(with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePriv")] #[serde(remote = "remote::TuplePriv")]
struct TuplePrivDef( struct TuplePrivDef(
#[serde(getter = "remote::TuplePriv::first")] #[serde(getter = "remote::TuplePriv::first")] u8,
u8, #[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit,
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")]
remote::Unit,
); );
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePub")] #[serde(remote = "remote::TuplePub")]
struct TuplePubDef( struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
u8,
#[serde(with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPriv")] #[serde(remote = "remote::StructPriv")]
@@ -175,10 +160,8 @@ struct StructPrivDef {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPub")] #[serde(remote = "remote::StructPub")]
struct StructPubDef { struct StructPubDef {
#[allow(dead_code)]
a: u8, a: u8,
#[allow(dead_code)]
#[serde(with = "UnitDef")] #[serde(with = "UnitDef")]
b: remote::Unit, b: remote::Unit,
} }
+43 -5
View File
@@ -10,13 +10,14 @@
extern crate serde_derive; extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::time::{Duration, UNIX_EPOCH};
use std::ffi::CString; use std::ffi::CString;
use std::rc::Rc; use std::mem;
use std::sync::Arc; use std::net;
use std::num::Wrapping; use std::num::Wrapping;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(unix)] #[cfg(unix)]
use std::str; use std::str;
@@ -398,11 +399,41 @@ declare_tests! {
Token::Bool(true), Token::Bool(true),
], ],
} }
test_rc_weak_some {
{
let rc = Rc::new(true);
mem::forget(rc.clone());
Rc::downgrade(&rc)
} => &[
Token::Some,
Token::Bool(true),
],
}
test_rc_weak_none {
RcWeak::<bool>::new() => &[
Token::None,
],
}
test_arc { test_arc {
Arc::new(true) => &[ Arc::new(true) => &[
Token::Bool(true), Token::Bool(true),
], ],
} }
test_arc_weak_some {
{
let arc = Arc::new(true);
mem::forget(arc.clone());
Arc::downgrade(&arc)
} => &[
Token::Some,
Token::Bool(true),
],
}
test_arc_weak_none {
ArcWeak::<bool>::new() => &[
Token::None,
],
}
test_wrapping { test_wrapping {
Wrapping(1usize) => &[ Wrapping(1usize) => &[
Token::U64(1), Token::U64(1),
@@ -555,3 +586,10 @@ fn test_enum_skipped() {
"the enum variant Enum::SkippedMap cannot be serialized", "the enum variant Enum::SkippedMap cannot be serialized",
); );
} }
#[test]
fn test_integer128() {
assert_ser_tokens_error(&1i128, &[], "i128 is not supported");
assert_ser_tokens_error(&1u128, &[], "u128 is not supported");
}
+1 -1
View File
@@ -10,8 +10,8 @@
extern crate serde_derive; extern crate serde_derive;
extern crate serde; extern crate serde;
use serde::Deserialize;
use serde::de::{value, IntoDeserializer}; use serde::de::{value, IntoDeserializer};
use serde::Deserialize;
#[test] #[test]
fn test_u32_to_enum() { fn test_u32_to_enum() {
+6
View File
@@ -87,4 +87,10 @@ else
channel build --no-default-features channel build --no-default-features
cd "$DIR/serde_test" cd "$DIR/serde_test"
channel build channel build
CHANNEL=1.15.0
cd "$DIR"
cargo clean
cd "$DIR/serde_derive"
channel build
fi fi