Compare commits

...

213 Commits

Author SHA1 Message Date
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
David Tolnay 382f3c2771 Release 1.0.41 2018-04-19 22:13:45 -07:00
David Tolnay 85ca12a8c3 Deserialize any integer from any buffered integer type 2018-04-19 22:11:14 -07:00
David Tolnay 541f9180cf Release 1.0.40 2018-04-19 10:31:33 -07:00
David Tolnay 3c4961c48e Lenient byte and string deserialization from buffered content 2018-04-19 10:21:55 -07:00
David Tolnay 184264ee92 Release 1.0.39 2018-04-17 11:35:45 -07:00
David Tolnay 6050229e7e Simplify counting remaining elements 2018-04-17 00:15:09 -07:00
David Tolnay e1db820c9f Implement all &Content deserializer hints 2018-04-17 00:15:05 -07:00
David Tolnay 0081cc961d Implement all Content deserializer hints 2018-04-17 00:14:59 -07:00
David Tolnay 9bc05803fe Fix clippy lint about literal in format string 2018-04-15 22:07:47 -07:00
David Tolnay 8d113e67d6 Release 1.0.38 2018-04-14 20:30:18 -07:00
David Tolnay 6e206ce053 Name formatter args with a leading double underscore 2018-04-13 00:21:21 -07:00
David Tolnay 47fc9af472 Emit borrowed methods only if collect_other_fields
Without collect_other_fields, the visit_borrowed_str and
visit_borrowed_bytes implementations that were being generated were
identical to their default implementation of forwarding to visit_str and
visit_bytes.
2018-04-13 00:17:34 -07:00
David Tolnay 1651f86d56 Simplify Option that is always Some 2018-04-13 00:17:30 -07:00
David Tolnay 1157ac0118 Eliminate unnecessary braces in wrap_deserialize_variant_with 2018-04-12 23:48:38 -07:00
David Tolnay 202c10147e Fix deserialize_with on a struct variant with one field 2018-04-12 23:44:53 -07:00
David Tolnay 9f38ca032e Format with rustfmt 0.4.1 2018-04-12 23:04:47 -07:00
David Tolnay 00178ba795 Eliminate generic functions in bound.rs 2018-04-12 22:48:31 -07:00
David Tolnay 24700ebeb6 Move associated type search into with_bounds 2018-04-12 22:46:53 -07:00
David Tolnay f06001c086 Name type_params consistently with Syn 2018-04-12 22:04:34 -07:00
David Tolnay ec773fb7db Make use of Generics::type_params iterator 2018-04-12 22:03:40 -07:00
David Tolnay da8b457f66 Simplify with_where_predicates_from_fields 2018-04-12 21:47:08 -07:00
David Tolnay a6e94e7122 Merge pull request #1213 from Osspial/assoc_type_derive
Support #[derive(Serialize, Deserialize)] when using associated types
2018-04-12 18:13:46 -07:00
Osspial 629bf7b354 Fix clippy warnings 2018-04-12 18:40:06 -04:00
Osspial 4415d10c61 Fix associated types only working for first generic parameter
Also, removes extraneous `where for`
2018-04-12 16:44:34 -04:00
Osspial def8d6e8af Add associated type test 2018-04-10 11:16:32 -04:00
Osspial 2e824e9aba Limit type bounds to associated types 2018-04-10 10:53:37 -04:00
Osspial fd14332729 Ignore skipped fields 2018-04-09 23:57:20 -04:00
Osspial c413775574 Add partially-working where bounds for associated types 2018-04-09 23:22:18 -04:00
David Tolnay 5efb22ebee Format no_std test code with rustfmt 0.4.1 2018-04-07 19:22:24 -07:00
David Tolnay 3e535325e1 Remove unused compiler_builtins_lib feature 2018-04-07 19:20:55 -07:00
David Tolnay 5653e5b15c Remove eh_unwind_resume lang item
It appears this is no longer needed.
2018-04-07 19:20:07 -07:00
David Tolnay 8d85860064 Remove no longer needed compiler_builtins
The `compiler_builtins` crate is now automatically injected whenever the
`core` crate is injected.
2018-04-07 19:18:38 -07:00
David Tolnay eed18ffab2 Release 1.0.37 2018-04-01 22:30:32 -07:00
David Tolnay f8e1fa8ebc Use Generics::make_where_clause helper 2018-04-01 22:25:50 -07:00
David Tolnay 860241aa88 Merge pull request #1205 from mitsuhiko/bugfix/tuple-struct-flatten
Produce error message for use of flatten in tuple structs
2018-04-02 07:09:39 +02:00
David Tolnay 6f6c60867d Merge pull request #1204 from mitsuhiko/bugfix/flatten-struct-variant
Produce error message for use of flatten within struct variant
2018-04-02 07:09:23 +02:00
Armin Ronacher 77376f39ea Produce error message for use of flatten in tuple structs 2018-04-01 22:11:21 +02:00
Armin Ronacher 302fac91a3 Produce error message for use of flatten within struct variant 2018-04-01 22:01:24 +02:00
David Tolnay 9c659d9d86 Format with rustfmt 0.4.1 2018-04-01 00:06:54 +02:00
David Tolnay 21698f264a Merge pull request #1201 from alexcrichton/proc-macro2-v3
Update to syn/quote/proc-macro2 new apis
2018-03-31 23:56:29 +02:00
David Tolnay ba002e1119 Update signature of Lifetime::new 2018-03-31 23:46:25 +02:00
David Tolnay 8b44eb8bfc Add parens to TraitBound 2018-03-31 23:45:30 +02:00
David Tolnay d82a0cc5ff Remove use of Span::located_at 2018-03-31 23:44:50 +02:00
David Tolnay 801fd1dc19 Drop the patch dependencies 2018-03-31 23:09:01 +02:00
David Tolnay 222779d46c Document that rc impls require a feature
Fixes #1203.
2018-03-30 10:31:54 +02:00
Alex Crichton b1c1d964e1 Update to syn/quote/proc-macro2 new apis 2018-03-29 00:54:05 -07:00
David Tolnay b77cfb635d Less eye-catching rustc version badge 2018-03-28 14:59:53 +02:00
David Tolnay c42c08a25b Merge pull request #1199 from serde-rs/rustc
Rustc version badge
2018-03-28 14:44:12 +02:00
David Tolnay 48997cbb5b Rustc version badge 2018-03-28 14:35:01 +02:00
David Tolnay d8ccd8809e Merge pull request #1198 from serde-rs/call_site
Prefer call site spans
2018-03-28 11:03:01 +02:00
David Tolnay d2b65e0a5d Prefer call site spans 2018-03-28 10:49:30 +02:00
David Tolnay 7c04c98e0e Release 1.0.36 2018-03-27 11:35:45 +02:00
David Tolnay a2fa4c2570 Merge pull request #1196 from serde-rs/self
Special case remote = "Self"
2018-03-27 11:12:04 +02:00
David Tolnay 42430902e2 Special case remote = "Self" 2018-03-27 10:56:05 +02:00
David Tolnay 23e2e92237 Release 1.0.35 2018-03-25 12:59:02 +02:00
David Tolnay 273b2c11c6 Keep using deprecated AsciiExt on old compilers 2018-03-25 12:45:31 +02:00
David Tolnay c1602a4d76 Deserialize map in place cannot have flatten attributes 2018-03-25 12:42:36 +02:00
David Tolnay c23be3f855 Revert flatten change in deserialize in place 2018-03-25 12:39:20 +02:00
David Tolnay 5c9c97c0ce Remove test that fails to parse flatten attribute 2018-03-25 12:33:50 +02:00
David Tolnay e5ed440136 Always check flatten assertions 2018-03-25 12:32:06 +02:00
David Tolnay d45ca2f5e4 Re-export NonZero* types from ::lib 2018-03-25 12:30:35 +02:00
David Tolnay d7f9f8209d Indicate that NonZero<T> is deprecated 2018-03-25 12:26:06 +02:00
David Tolnay 4a2612ecff Merge pull request #1191 from SimonSapin/nonzero
impl Serialize and Deserialize for std::num::NonZero*
2018-03-25 03:24:51 -07:00
Simon Sapin 05b22a06d7 impl Serialize and Deserialize for std::num::NonZero*
… gated on the `unstable` Cargo feature.

These are new standard library types.
2018-03-25 12:23:55 +02:00
David Tolnay 3145bcc46e Merge pull request 1159 from niklasad1/patch-1 2018-03-24 19:42:14 +01:00
David Tolnay 2b18b57d84 Release 1.0.34 2018-03-22 15:06:21 -07:00
David Tolnay 5520202262 Merge pull request #1179 from mitsuhiko/feature/flatten
Support for Flattening
2018-03-22 14:14:23 -07:00
Armin Ronacher 3d647f4063 Fixed a compilefail test for flatten on enums 2018-03-20 23:26:22 +01:00
Armin Ronacher 0fde3c2ee8 Fix a warning caused by no-default-features 2018-03-20 23:06:55 +01:00
Armin Ronacher 27f935f036 Correctly serialize newtype variants for flatten 2018-03-20 23:05:05 +01:00
Armin Ronacher 99614c7266 Added flatten on enum compile fail test 2018-03-20 22:15:47 +01:00
Armin Ronacher bb2ecb3bc4 Added compilefail tests for flatten conflicts 2018-03-20 22:04:12 +01:00
Armin Ronacher 96393bfcc7 Added checks for flatten attribute 2018-03-20 21:48:25 +01:00
Armin Ronacher 1d92569abc Added explanatory comment about fetching data from buffered content 2018-03-20 21:24:00 +01:00
Armin Ronacher e4ef087735 Added support for borrowing when flattening 2018-03-20 15:19:36 +01:00
Armin Ronacher 695c3eedcb Do not imply flatten from skip_serialize 2018-03-20 14:45:14 +01:00
Armin Ronacher 50c636a923 Remove now dead as_map detection (can be cattrs.has_flatten) 2018-03-20 13:43:23 +01:00
Armin Ronacher 5b884b5bf9 Added some missing UFCs 2018-03-20 13:38:22 +01:00
Armin Ronacher 8637dda60f Refactored a test 2018-03-20 13:38:08 +01:00
Armin Ronacher abeea89147 Fully qualify some calls in generated code and fix a bad comment 2018-03-20 13:35:16 +01:00
Armin Ronacher 6e324e887d Some refactoring to use a bit less unwrap() 2018-03-20 13:20:56 +01:00
Armin Ronacher 7c596c7136 Remove unnecessary as_str 2018-03-20 13:11:17 +01:00
Armin Ronacher f02dbf381b Added non string key support for flattening 2018-03-19 00:57:58 +01:00
Armin Ronacher 7cf184624a Use more consistent error messages for bad flattening 2018-03-18 23:46:28 +01:00
Armin Ronacher c5a3128492 Added a more complex flattening test 2018-03-18 23:01:13 +01:00
Armin Ronacher 205f606962 Various clippy fixes 2018-03-18 22:59:27 +01:00
Armin Ronacher ad40f976db Switch to using Content keys internally for flattening to later support arbitrary keys 2018-03-18 21:07:08 +01:00
Armin Ronacher 58d52e784b Remove #[serde(repr = "map")] 2018-03-18 18:30:46 +01:00
Armin Ronacher d44f12907b Do not emit an in-place deserialization path for struct as map 2018-03-18 18:27:35 +01:00
Armin Ronacher 61b167be9a Attempted support for in_place deserialization for structs as map 2018-03-18 18:22:06 +01:00
Armin Ronacher f1af2dc5ab Added support for newtype variant serialization 2018-03-18 13:10:54 +01:00
Armin Ronacher ebc61baab2 Added newtype struct support for flattening 2018-03-18 13:02:00 +01:00
Armin Ronacher ffcde25b6e Fixed some clippy warnings 2018-03-17 00:49:00 +01:00
Armin Ronacher 2f57cecf13 format! -> format_args! for an error message 2018-03-16 23:38:50 +01:00
Armin Ronacher bfdcbae9db Fixed an unused import error 2018-03-16 23:30:55 +01:00
Armin Ronacher ca41e16e92 Added some missing conditionals for feature compilation 2018-03-16 23:20:14 +01:00
Armin Ronacher 352fe7b451 Removed an unused field that was left over from a merge conflict 2018-03-16 23:07:31 +01:00
Armin Ronacher 49e302d17d Improved error message for flattening on unsupported types 2018-03-16 23:05:48 +01:00
Armin Ronacher b8602a7e43 Added test for tag/content enum flattening 2018-03-16 23:05:48 +01:00
Armin Ronacher a8c8c2028e Added support for struct variant enum serialization 2018-03-16 23:05:48 +01:00
Armin Ronacher d1833c5602 Added support for basic enums in flatten 2018-03-16 23:05:48 +01:00
Armin Ronacher b4ef7ac323 Updated tests for flatten 2018-03-16 23:05:48 +01:00
Armin Ronacher ebf80ac965 Implement deserialization support for flatten 2018-03-16 23:05:48 +01:00
Armin Ronacher 112dfd7428 Correctly suppress the end() call for flattened serialization 2018-03-16 23:05:48 +01:00
Armin Ronacher b692923321 Non working changes to the flatten serializer 2018-03-16 23:05:48 +01:00
Armin Ronacher 9e8cda4c37 Added basic not fully working FlatMapSerializer 2018-03-16 23:05:48 +01:00
Jan Michael Auer 5457394f5b Fixed various issues with combinding flatten and deny_unknown_fields 2018-03-16 23:05:48 +01:00
Jan Michael Auer 6627540dd6 Added support basic deserialization in derive 2018-03-16 23:05:48 +01:00
Jan Michael Auer 5ae06bba49 Store flatten flag in container attributes 2018-03-16 23:05:47 +01:00
Jan Michael Auer 571bb8caed Derive serialization for serde(flatten) 2018-03-16 23:05:47 +01:00
Jan Michael Auer 299cd2dbd0 Replace unknown_fields_into with serde(flatten) 2018-03-16 23:05:47 +01:00
Armin Ronacher 583c0d8d14 Make proc-macro2/nightly happy 2018-03-16 23:05:22 +01:00
Armin Ronacher 07d07347b3 Make clippy happy 2018-03-16 23:05:22 +01:00
Armin Ronacher 77b07f3fbf Added tests for unknown_fields_into 2018-03-16 23:05:22 +01:00
Armin Ronacher 1bd2c6129c Explicitly pass value requirements for the capture path 2018-03-16 23:05:22 +01:00
Armin Ronacher 39413c8ce7 Implement deserializer for map mode and collection fields 2018-03-16 23:05:22 +01:00
Armin Ronacher b4dbae250b Added support for serialization of structs as maps 2018-03-16 23:05:22 +01:00
Armin Ronacher 5a91ac5ba5 Initial work on supporting structs as map with unknown field collection 2018-03-16 23:05:22 +01:00
David Tolnay 7ad836e6a9 Release 1.0.33 2018-03-15 10:03:42 -07:00
David Tolnay 72ecb9064c Fix parsing of qself in paths in attributes 2018-03-15 10:02:40 -07:00
niklasad1 f9946ee0ca add some comments about alloc in no_std 2018-02-17 10:03:21 +01:00
Niklas Adolfsson a164f52315 Update README.md
Add some information about ```no_std``` because it was not obvious to me
2018-02-16 19:59:28 +01:00
61 changed files with 5988 additions and 1611 deletions
+7
View File
@@ -0,0 +1,7 @@
---
name: Problem
about: Something does not seem right
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Feature request
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
---
+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 -1
View File
@@ -1,9 +1,11 @@
# Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] # Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.13+]][rustc]
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master [Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
[travis]: https://travis-ci.org/serde-rs/serde [travis]: https://travis-ci.org/serde-rs/serde
[Latest Version]: https://img.shields.io/crates/v/serde.svg [Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde [crates.io]: https://crates.io/crates/serde
[Rustc Version 1.13+]: https://img.shields.io/badge/rustc-1.13+-lightgray.svg
[rustc]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
-1
View File
@@ -1,2 +1 @@
error_on_line_overflow = false error_on_line_overflow = false
same_line_attributes = false
+1 -6
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.32" # remember to update html_root_url version = "1.0.55" # 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"
@@ -61,8 +61,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"]
+132 -42
View File
@@ -9,33 +9,33 @@
use lib::*; use lib::*;
macro_rules! int_to_int { macro_rules! int_to_int {
($dst:ident, $n:ident) => ( ($dst:ident, $n:ident) => {
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 { if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
Some($n as $dst) Some($n as $dst)
} else { } else {
None None
} }
) };
} }
macro_rules! int_to_uint { macro_rules! int_to_uint {
($dst:ident, $n:ident) => ( ($dst:ident, $n:ident) => {
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 { if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst) Some($n as $dst)
} else { } else {
None None
} }
) };
} }
macro_rules! uint_to { macro_rules! uint_to {
($dst:ident, $n:ident) => ( ($dst:ident, $n:ident) => {
if $n as u64 <= $dst::max_value() as u64 { if $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst) Some($n as $dst)
} else { } else {
None None
} }
) };
} }
pub trait FromPrimitive: Sized { pub trait FromPrimitive: Sized {
@@ -52,54 +52,144 @@ 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> { int_to_int!($t, n) } fn from_isize(n: isize) -> Option<Self> {
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) } int_to_int!($t, n)
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) } }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) } #[inline]
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) } fn from_i8(n: i8) -> Option<Self> {
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) } int_to_int!($t, n)
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) } }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) } #[inline]
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) } fn from_i16(n: i16) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_usize(n: usize) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
uint_to!($t, n)
}
} }
) };
} }
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> { int_to_uint!($t, n) } fn from_isize(n: isize) -> Option<Self> {
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) } int_to_uint!($t, n)
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) } }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) } #[inline]
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) } fn from_i8(n: i8) -> Option<Self> {
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) } int_to_uint!($t, n)
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) } }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) } #[inline]
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) } fn from_i16(n: i16) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_usize(n: usize) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
uint_to!($t, n)
}
} }
) };
} }
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> { Some(n as Self) } fn from_isize(n: isize) -> Option<Self> {
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) } Some(n as Self)
#[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) } }
#[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) } #[inline]
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) } fn from_i8(n: i8) -> Option<Self> {
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) } Some(n as Self)
#[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) } }
#[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) } #[inline]
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) } fn from_i16(n: i16) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_usize(n: usize) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as Self)
}
} }
) };
} }
impl_from_primitive_for_int!(isize); impl_from_primitive_for_int!(isize);
+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
+205 -86
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>,
{ {
@@ -177,7 +178,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 +186,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 +200,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 +223,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 +247,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 +269,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 +278,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 +286,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 +300,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 +319,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 +417,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 +431,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 +462,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>,
{ {
@@ -470,7 +471,11 @@ impl<'de> Deserialize<'de> for CString {
} }
macro_rules! forwarded_impl { macro_rules! forwarded_impl {
(( $($id: ident),* ), $ty: ty, $func: expr) => { (
$(#[doc = $doc:tt])*
( $($id: ident),* ), $ty: ty, $func: expr
) => {
$(#[doc = $doc])*
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty { impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -502,7 +507,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,
{ {
@@ -510,7 +515,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,
{ {
@@ -518,19 +523,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>,
{ {
@@ -560,7 +573,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,
{ {
@@ -569,7 +582,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>,
{ {
@@ -654,7 +667,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>,
{ {
@@ -766,7 +779,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>,
{ {
@@ -776,7 +789,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>,
{ {
@@ -798,7 +811,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>,
{ {
@@ -824,7 +837,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>,
{ {
@@ -846,7 +859,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>,
{ {
@@ -906,7 +919,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>,
{ {
@@ -923,7 +936,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>,
{ {
@@ -957,7 +970,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>,
{ {
@@ -1073,7 +1086,7 @@ map_impl!(
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! parse_ip_impl { macro_rules! parse_ip_impl {
($ty:ty; $size: expr) => { ($ty:ty; $size:expr) => {
impl<'de> Deserialize<'de> for $ty { impl<'de> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -1087,7 +1100,7 @@ macro_rules! parse_ip_impl {
} }
} }
} }
} };
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -1230,7 +1243,7 @@ parse_ip_impl!(net::Ipv6Addr; 16);
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! parse_socket_impl { macro_rules! parse_socket_impl {
($ty:ty, $new: expr) => { ($ty:ty, $new:expr) => {
impl<'de> Deserialize<'de> for $ty { impl<'de> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -1244,7 +1257,7 @@ macro_rules! parse_socket_impl {
} }
} }
} }
} };
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -1272,10 +1285,7 @@ parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
#[cfg(feature = "std")] #[cfg(feature = "std")]
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new( parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(
ip, ip, port, 0, 0
port,
0,
0
)); ));
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1329,14 +1339,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,
{ {
@@ -1346,7 +1356,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>,
{ {
@@ -1379,7 +1389,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>,
{ {
@@ -1394,7 +1404,7 @@ 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>,
{ {
@@ -1412,7 +1422,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,10 +1442,28 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
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(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
forwarded_impl!((T), Arc<T>, Arc::new); forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Arc` will not attempt to
/// deduplicate `Arc` references to the same data. Every deserialized `Arc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
(T), Arc<T>, Arc::new
}
#[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
forwarded_impl!((T), Rc<T>, Rc::new); forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Rc` will not attempt to
/// deduplicate `Rc` references to the same data. Every deserialized `Rc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
(T), Rc<T>, Rc::new
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
@@ -1444,7 +1472,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>,
{ {
@@ -1454,9 +1482,51 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// 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(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
($t:ident) => { (
$(#[doc = $doc:tt])*
$t:ident
) => {
$(#[doc = $doc])*
impl<'de, T: ?Sized> Deserialize<'de> for $t<T> impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
where where
Box<T>: Deserialize<'de>, Box<T>: Deserialize<'de>,
@@ -1468,14 +1538,32 @@ macro_rules! box_forwarded_impl {
Box::deserialize(deserializer).map(Into::into) Box::deserialize(deserializer).map(Into::into)
} }
} }
} };
} }
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
box_forwarded_impl!(Rc); box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Rc` will not attempt to
/// deduplicate `Rc` references to the same data. Every deserialized `Rc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
Rc
}
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
box_forwarded_impl!(Arc); box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Arc` will not attempt to
/// deduplicate `Arc` references to the same data. Every deserialized `Arc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
Arc
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1483,7 +1571,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>,
{ {
@@ -1525,7 +1613,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>,
{ {
@@ -1538,7 +1626,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,
{ {
@@ -1549,7 +1637,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,
{ {
@@ -1577,7 +1665,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>,
{ {
@@ -1596,7 +1684,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>,
{ {
@@ -1650,7 +1738,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>,
{ {
@@ -1663,7 +1751,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,
{ {
@@ -1674,7 +1762,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,
{ {
@@ -1702,7 +1790,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>,
{ {
@@ -1721,7 +1809,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>,
{ {
@@ -1794,7 +1882,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>,
{ {
@@ -1807,7 +1895,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,
{ {
@@ -1818,7 +1906,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,
{ {
@@ -1851,7 +1939,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>,
{ {
@@ -1870,7 +1958,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>,
{ {
@@ -1918,11 +2006,12 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
#[allow(deprecated)]
impl<'de, T> Deserialize<'de> for NonZero<T> impl<'de, T> Deserialize<'de> for NonZero<T>
where where
T: Deserialize<'de> + Zeroable, T: Deserialize<'de> + Zeroable,
{ {
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1934,6 +2023,36 @@ where
} }
} }
macro_rules! nonzero_integers {
( $( $T: ty, )+ ) => {
$(
#[cfg(feature = "unstable")]
impl<'de> Deserialize<'de> for $T {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value = try!(Deserialize::deserialize(deserializer));
match <$T>::new(value) {
Some(nonzero) => Ok(nonzero),
None => Err(Error::custom("expected a non-zero value")),
}
}
}
)+
};
}
nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8,
NonZeroU16,
NonZeroU32,
NonZeroU64,
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
NonZeroUsize,
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
impl<'de, T, E> Deserialize<'de> for Result<T, E> impl<'de, T, E> Deserialize<'de> for Result<T, E>
@@ -1941,7 +2060,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>,
{ {
@@ -1956,7 +2075,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>,
{ {
@@ -1969,7 +2088,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,
{ {
@@ -1983,7 +2102,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,
{ {
@@ -1994,7 +2113,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,
{ {
@@ -2028,7 +2147,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>,
{ {
@@ -2052,7 +2171,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>,
{ {
+83 -35
View File
@@ -98,7 +98,8 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - NonZero\<T\> (unstable) //! - NonZero\<T\> (unstable, deprecated)
//! - num::NonZero* (unstable)
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -171,7 +172,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)
@@ -195,6 +197,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))
} }
@@ -212,6 +215,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))
} }
@@ -225,12 +229,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",
@@ -244,6 +250,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",
@@ -258,12 +265,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))
} }
@@ -298,7 +307,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))
/// } /// }
@@ -422,7 +432,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))
/// } /// }
@@ -435,7 +446,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"));
@@ -549,11 +561,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> {}
@@ -629,7 +643,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
@@ -637,14 +652,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 = ();
/// ///
@@ -653,7 +670,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.
@@ -672,7 +690,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.
@@ -683,7 +702,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();
@@ -699,7 +719,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)?;
@@ -1084,7 +1105,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".
@@ -1135,7 +1157,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())
@@ -1506,6 +1529,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(())
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1815,15 +1847,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!() }
/// # } /// # }
/// ``` /// ```
@@ -1850,7 +1885,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;
@@ -1858,11 +1894,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!() }
/// # } /// # }
/// ``` /// ```
@@ -1903,13 +1941,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;
@@ -1917,7 +1959,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!() }
/// # } /// # }
/// ``` /// ```
@@ -1945,17 +1988,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;
+8 -11
View File
@@ -37,10 +37,10 @@
use lib::*; use lib::*;
use self::private::{First, Second};
use de::{self, Expected, IntoDeserializer, SeqAccess}; use de::{self, Expected, IntoDeserializer, SeqAccess};
use private::de::size_hint; use private::de::size_hint;
use ser; use ser;
use self::private::{First, Second};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -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,
@@ -652,11 +655,8 @@ where
{ {
/// Check for remaining elements after passing a `SeqDeserializer` to /// Check for remaining elements after passing a `SeqDeserializer` to
/// `Visitor::visit_seq`. /// `Visitor::visit_seq`.
pub fn end(mut self) -> Result<(), E> { pub fn end(self) -> Result<(), E> {
let mut remaining = 0; let remaining = self.iter.count();
while self.iter.next().is_some() {
remaining += 1;
}
if remaining == 0 { if remaining == 0 {
Ok(()) Ok(())
} else { } else {
@@ -849,11 +849,8 @@ where
{ {
/// Check for remaining elements after passing a `MapDeserializer` to /// Check for remaining elements after passing a `MapDeserializer` to
/// `Visitor::visit_map`. /// `Visitor::visit_map`.
pub fn end(mut self) -> Result<(), E> { pub fn end(self) -> Result<(), E> {
let mut remaining = 0; let remaining = self.iter.count();
while self.iter.next().is_some() {
remaining += 1;
}
if remaining == 0 { if remaining == 0 {
Ok(()) Ok(())
} else { } else {
+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::*;
+41 -34
View File
@@ -79,7 +79,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.32")] #![doc(html_root_url = "https://docs.rs/serde/1.0.55")]
// 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
@@ -90,10 +90,13 @@
#![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
#![cfg_attr(feature = "cargo-clippy", #![cfg_attr(
allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist, feature = "cargo-clippy",
needless_pass_by_value, redundant_field_names, type_complexity, allow(
unreadable_literal, zero_prefixed_literal))] cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value,
redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal
)
)]
// Whitelisted clippy_pedantic lints // Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow( #![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts // integer and float ser/de requires these sorts of casts
@@ -135,16 +138,16 @@ extern crate core;
/// module. /// module.
mod lib { mod lib {
mod core { mod core {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
pub use core::*; pub use core::*;
#[cfg(feature = "std")]
pub use std::*;
} }
pub use self::core::{cmp, iter, mem, ops, slice, str}; pub use self::core::{cmp, iter, mem, ops, slice, str};
pub use self::core::{isize, i16, i32, i64, i8};
pub use self::core::{usize, u16, u32, u64, u8};
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::{u16, u32, u64, u8, usize};
pub use self::core::cell::{Cell, RefCell}; pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone}; pub use self::core::clone::{self, Clone};
@@ -155,40 +158,40 @@ mod lib {
pub use self::core::option::{self, Option}; pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result}; pub use self::core::result::{self, Result};
#[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::borrow::{Cow, ToOwned}; pub use alloc::borrow::{Cow, ToOwned};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::string::String; pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::string::{String, ToString}; pub use alloc::string::{String, ToString};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::vec::Vec; pub use std::string::String;
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::vec::Vec; pub use alloc::vec::Vec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::boxed::Box; pub use std::vec::Vec;
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::boxed::Box; pub use alloc::boxed::Box;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::Arc;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; pub use std::boxed::Box;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "rc", feature = "std"))]
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};
#[cfg(feature = "std")]
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::{error, net}; pub use std::{error, net};
@@ -206,12 +209,16 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::path::{Path, PathBuf}; pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock}; pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
#[allow(deprecated)]
pub use core::nonzero::{NonZero, Zeroable}; pub use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "unstable")]
pub use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -219,13 +226,13 @@ mod lib {
#[macro_use] #[macro_use]
mod macros; mod macros;
pub mod ser;
pub mod de; pub mod de;
pub mod ser;
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)] #[doc(inline)]
pub use de::{Deserialize, Deserializer}; pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};
// Generated code uses these to support no_std. Not public API. // Generated code uses these to support no_std. Not public API.
#[doc(hidden)] #[doc(hidden)]
+8 -4
View File
@@ -31,14 +31,16 @@
/// # 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)
/// } /// }
@@ -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;
@@ -105,7 +108,8 @@
/// # 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!()
/// # } /// # }
+910 -79
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -8,5 +8,5 @@
mod macros; mod macros;
pub mod ser;
pub mod de; pub mod de;
pub mod ser;
+319 -13
View File
@@ -11,7 +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::{SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue}; use self::content::{
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.
@@ -58,10 +60,11 @@ enum Unsupported {
ByteArray, ByteArray,
Optional, Optional,
Unit, Unit,
#[cfg(any(feature = "std", feature = "alloc"))]
UnitStruct,
Sequence, Sequence,
Tuple, Tuple,
TupleStruct, TupleStruct,
#[cfg(not(any(feature = "std", feature = "alloc")))]
Enum, Enum,
} }
@@ -76,10 +79,11 @@ impl Display for Unsupported {
Unsupported::ByteArray => formatter.write_str("a byte array"), Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"), Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"), Unsupported::Unit => formatter.write_str("unit"),
#[cfg(any(feature = "std", feature = "alloc"))]
Unsupported::UnitStruct => formatter.write_str("unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "alloc")))]
Unsupported::Enum => formatter.write_str("an enum"), Unsupported::Enum => formatter.write_str("an enum"),
} }
} }
@@ -459,7 +463,7 @@ mod content {
} }
#[derive(Debug)] #[derive(Debug)]
enum Content { pub enum Content {
Bool(bool), Bool(bool),
U8(u8), U8(u8),
@@ -584,12 +588,12 @@ mod content {
} }
} }
struct ContentSerializer<E> { pub struct ContentSerializer<E> {
error: PhantomData<E>, error: PhantomData<E>,
} }
impl<E> ContentSerializer<E> { impl<E> ContentSerializer<E> {
fn new() -> Self { pub fn new() -> Self {
ContentSerializer { error: PhantomData } ContentSerializer { error: PhantomData }
} }
} }
@@ -804,7 +808,7 @@ mod content {
} }
} }
struct SerializeSeq<E> { pub struct SerializeSeq<E> {
elements: Vec<Content>, elements: Vec<Content>,
error: PhantomData<E>, error: PhantomData<E>,
} }
@@ -830,7 +834,7 @@ mod content {
} }
} }
struct SerializeTuple<E> { pub struct SerializeTuple<E> {
elements: Vec<Content>, elements: Vec<Content>,
error: PhantomData<E>, error: PhantomData<E>,
} }
@@ -856,7 +860,7 @@ mod content {
} }
} }
struct SerializeTupleStruct<E> { pub struct SerializeTupleStruct<E> {
name: &'static str, name: &'static str,
fields: Vec<Content>, fields: Vec<Content>,
error: PhantomData<E>, error: PhantomData<E>,
@@ -883,7 +887,7 @@ mod content {
} }
} }
struct SerializeTupleVariant<E> { pub struct SerializeTupleVariant<E> {
name: &'static str, name: &'static str,
variant_index: u32, variant_index: u32,
variant: &'static str, variant: &'static str,
@@ -917,7 +921,7 @@ mod content {
} }
} }
struct SerializeMap<E> { pub struct SerializeMap<E> {
entries: Vec<(Content, Content)>, entries: Vec<(Content, Content)>,
key: Option<Content>, key: Option<Content>,
error: PhantomData<E>, error: PhantomData<E>,
@@ -967,7 +971,7 @@ mod content {
} }
} }
struct SerializeStruct<E> { pub struct SerializeStruct<E> {
name: &'static str, name: &'static str,
fields: Vec<(&'static str, Content)>, fields: Vec<(&'static str, Content)>,
error: PhantomData<E>, error: PhantomData<E>,
@@ -994,7 +998,7 @@ mod content {
} }
} }
struct SerializeStructVariant<E> { pub struct SerializeStructVariant<E> {
name: &'static str, name: &'static str,
variant_index: u32, variant_index: u32,
variant: &'static str, variant: &'static str,
@@ -1028,3 +1032,305 @@ mod content {
} }
} }
} }
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializer<'a, M: 'a>(pub &'a mut M);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> FlatMapSerializer<'a, M>
where
M: SerializeMap + 'a,
{
fn bad_type(self, what: Unsupported) -> M::Error {
ser::Error::custom(format_args!(
"can only flatten structs and maps (got {})",
what
))
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> Serializer for FlatMapSerializer<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
type SerializeSeq = Impossible<Self::Ok, M::Error>;
type SerializeTuple = Impossible<Self::Ok, M::Error>;
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
type SerializeMap = FlatMapSerializeMap<'a, M>;
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_newtype_struct<T: ?Sized>(
self,
_: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_: &'static str,
_: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
try!(self.0.serialize_key(variant));
self.0.serialize_value(value)
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Ok(FlatMapSerializeMap(self.0))
}
fn serialize_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Ok(FlatMapSerializeStruct(self.0))
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
inner_variant: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
try!(self.0.serialize_key(inner_variant));
Ok(FlatMapSerializeStructVariantAsMapValue::new(
self.0,
inner_variant,
))
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeMap<'a, M: 'a>(&'a mut M);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> ser::SerializeMap for FlatMapSerializeMap<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
self.0.serialize_key(key)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
self.0.serialize_value(value)
}
fn end(self) -> Result<(), Self::Error> {
Ok(())
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeStruct<'a, M: 'a>(&'a mut M);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
self.0.serialize_entry(key, value)
}
fn end(self) -> Result<(), Self::Error> {
Ok(())
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
map: &'a mut M,
name: &'static str,
fields: Vec<(&'static str, Content)>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> FlatMapSerializeStructVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
FlatMapSerializeStructVariantAsMapValue {
map: map,
name: name,
fields: Vec::new(),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<(), Self::Error> {
try!(
self.map
.serialize_value(&Content::Struct(self.name, self.fields))
);
Ok(())
}
}
+91 -8
View File
@@ -320,8 +320,12 @@ map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! deref_impl { macro_rules! deref_impl {
($($desc:tt)+) => { (
impl $($desc)+ { $(#[doc = $doc:tt])*
<$($desc:tt)+
) => {
$(#[doc = $doc])*
impl <$($desc)+ {
#[inline] #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -340,17 +344,72 @@ deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize); deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T: ?Sized> Serialize for Rc<T> where T: Serialize); deref_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Serializing a data structure containing `Rc` will serialize a copy of
/// the contents of the `Rc` each time the `Rc` is referenced within the
/// data structure. Serialization will not attempt to deduplicate these
/// repeated data.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
<T: ?Sized> Serialize for Rc<T> where T: Serialize
}
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T: ?Sized> Serialize for Arc<T> where T: Serialize); deref_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Serializing a data structure containing `Arc` will serialize a copy of
/// the contents of the `Arc` each time the `Arc` is referenced within the
/// data structure. Serialization will not attempt to deduplicate these
/// repeated data.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
<T: ?Sized> Serialize for Arc<T> where T: Serialize
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned); deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// 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 RcWeak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: 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)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
#[allow(deprecated)]
impl<T> Serialize for NonZero<T> impl<T> Serialize for NonZero<T>
where where
T: Serialize + Zeroable + Clone, T: Serialize + Zeroable + Clone,
@@ -363,6 +422,32 @@ where
} }
} }
macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => {
$(
#[cfg(feature = "unstable")]
impl Serialize for $T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.get().serialize(serializer)
}
}
)+
}
}
nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8,
NonZeroU16,
NonZeroU32,
NonZeroU64,
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
NonZeroUsize,
}
impl<T> Serialize for Cell<T> impl<T> Serialize for Cell<T>
where where
T: Serialize + Copy, T: Serialize + Copy,
@@ -494,11 +579,9 @@ macro_rules! serialize_display_bounded_length {
// write! only provides fmt::Formatter to Display implementations, which // write! only provides fmt::Formatter to Display implementations, which
// has methods write_str and write_char but no method to write arbitrary // has methods write_str and write_char but no method to write arbitrary
// bytes. Therefore `written` must be valid UTF-8. // bytes. Therefore `written` must be valid UTF-8.
let written_str = unsafe { let written_str = unsafe { str::from_utf8_unchecked(written) };
str::from_utf8_unchecked(written)
};
$serializer.serialize_str(written_str) $serializer.serialize_str(written_str)
}} }};
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
+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.
+112 -59
View File
@@ -93,7 +93,8 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - NonZero\<T\> (unstable) //! - NonZero\<T\> (unstable, deprecated)
//! - num::NonZero* (unstable)
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -151,7 +152,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),
@@ -222,7 +224,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)?;
@@ -376,7 +379,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)
/// } /// }
@@ -402,7 +406,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)
/// } /// }
@@ -428,7 +433,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)
/// } /// }
@@ -454,7 +460,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)
/// } /// }
@@ -476,7 +483,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)
/// } /// }
@@ -502,7 +510,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)
/// } /// }
@@ -528,7 +537,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)
/// } /// }
@@ -554,7 +564,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)
/// } /// }
@@ -576,7 +587,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)
/// } /// }
@@ -602,7 +614,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)
/// } /// }
@@ -624,7 +637,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)
/// } /// }
@@ -649,7 +663,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)
/// } /// }
@@ -671,7 +686,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)
/// } /// }
@@ -736,10 +752,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),
@@ -769,10 +787,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),
@@ -801,7 +821,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()
/// } /// }
@@ -822,7 +843,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")
/// } /// }
@@ -846,7 +868,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"),
@@ -875,7 +898,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)
/// } /// }
@@ -905,7 +929,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),
@@ -955,10 +980,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 {
@@ -987,12 +1014,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)?;
@@ -1011,7 +1040,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[..] {
@@ -1037,7 +1067,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)?;
@@ -1071,7 +1102,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) => {
@@ -1129,11 +1161,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 {
@@ -1163,7 +1197,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)?;
@@ -1196,7 +1231,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 } => {
@@ -1233,7 +1269,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))
/// } /// }
@@ -1271,7 +1308,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, ())))
/// } /// }
@@ -1311,7 +1349,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(),
@@ -1351,7 +1390,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(),
@@ -1392,7 +1432,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".
@@ -1441,10 +1482,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 {
@@ -1484,12 +1527,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)?;
@@ -1528,10 +1573,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 {
@@ -1566,7 +1613,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)?;
@@ -1604,7 +1652,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) => {
@@ -1665,11 +1714,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 {
@@ -1753,7 +1804,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)?;
@@ -1801,7 +1853,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.32" # remember to update html_root_url version = "1.0.55" # 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.2" proc-macro2 = "0.3"
quote = "0.4" quote = "0.5.2"
serde_derive_internals = { version = "=0.20.1", default-features = false, path = "../serde_derive_internals" } syn = { version = "0.13", features = ["visit"] }
syn = { version = "0.12", features = ["visit"] }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0", path = "../serde" } serde = { version = "1.0", path = "../serde" }
+141 -151
View File
@@ -8,13 +8,14 @@
use std::collections::HashSet; use std::collections::HashSet;
use syn::{self, visit}; use syn;
use syn::punctuated::Punctuated; use syn::punctuated::{Pair, Punctuated};
use syn::visit::{self, Visit};
use internals::ast::{Data, Container}; use internals::ast::{Container, Data};
use internals::attr; use internals::attr;
use proc_macro2::{Span, Term}; use proc_macro2::Span;
// Remove the default from every type parameter because in the generated impls // Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not // they look like associated types: "error: associated type bindings are not
@@ -25,13 +26,11 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
.params .params
.iter() .iter()
.map(|param| match *param { .map(|param| match *param {
syn::GenericParam::Type(ref param) => { syn::GenericParam::Type(ref param) => syn::GenericParam::Type(syn::TypeParam {
syn::GenericParam::Type(syn::TypeParam { eq_token: None,
eq_token: None, default: None,
default: None, ..param.clone()
..param.clone() }),
})
}
_ => param.clone(), _ => param.clone(),
}) })
.collect(), .collect(),
@@ -44,45 +43,47 @@ pub fn with_where_predicates(
predicates: &[syn::WherePredicate], predicates: &[syn::WherePredicate],
) -> syn::Generics { ) -> syn::Generics {
let mut generics = generics.clone(); let mut generics = generics.clone();
if generics.where_clause.is_none() { generics
generics.where_clause = Some(syn::WhereClause { .make_where_clause()
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates .predicates
.extend(predicates.into_iter().cloned()); .extend(predicates.into_iter().cloned());
generics generics
} }
pub fn with_where_predicates_from_fields<F>( pub fn with_where_predicates_from_fields(
cont: &Container, cont: &Container,
generics: &syn::Generics, generics: &syn::Generics,
from_field: F, from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics ) -> syn::Generics {
where
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
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());
let mut generics = generics.clone(); let mut generics = generics.clone();
if generics.where_clause.is_none() { generics.make_where_clause().predicates.extend(predicates);
generics.where_clause = Some(syn::WhereClause { generics
where_token: Default::default(), }
predicates: Punctuated::new(),
}); pub fn with_where_predicates_from_variants(
} cont: &Container,
generics.where_clause generics: &syn::Generics,
.as_mut() from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
.unwrap() ) -> syn::Generics {
.predicates let variants = match cont.data {
.extend(predicates); 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 generics
} }
@@ -97,26 +98,39 @@ where
// #[serde(skip_serializing)] // #[serde(skip_serializing)]
// c: C, // c: C,
// } // }
pub fn with_bound<F>( pub fn with_bound(
cont: &Container, cont: &Container,
generics: &syn::Generics, generics: &syn::Generics,
filter: F, filter: fn(&attr::Field, Option<&attr::Variant>) -> bool,
bound: &syn::Path, bound: &syn::Path,
) -> syn::Generics ) -> syn::Generics {
where struct FindTyParams<'ast> {
F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in // Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front. // the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>, all_type_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter // Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees // returns true (A and B in the example). Filled in as the visitor sees
// them. // them.
relevant_ty_params: HashSet<syn::Ident>, relevant_type_params: HashSet<syn::Ident>,
// Fields whose type is an associated type of one of the generic type
// parameters.
associated_type_usage: Vec<&'ast syn::TypePath>,
} }
impl<'ast> visit::Visit<'ast> for FindTyParams { impl<'ast> Visit<'ast> for FindTyParams<'ast> {
fn visit_path(&mut self, path: &syn::Path) { fn visit_field(&mut self, field: &'ast syn::Field) {
if let syn::Type::Path(ref ty) = field.ty {
if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() {
if self.all_type_params.contains(&t.ident) {
self.associated_type_usage.push(ty);
}
}
}
self.visit_type(&field.ty);
}
fn visit_path(&mut self, path: &'ast syn::Path) {
if let Some(seg) = path.segments.last() { if let Some(seg) = path.segments.last() {
if seg.into_value().ident == "PhantomData" { if seg.into_value().ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements // Hardcoded exception, because PhantomData<T> implements
@@ -126,8 +140,8 @@ where
} }
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_ty_params.contains(&id) { if self.all_type_params.contains(&id) {
self.relevant_ty_params.insert(id); self.relevant_type_params.insert(id);
} }
} }
visit::visit_path(self, path); visit::visit_path(self, path);
@@ -139,21 +153,15 @@ where
// mac: T!(), // mac: T!(),
// marker: PhantomData<T>, // marker: PhantomData<T>,
// } // }
fn visit_macro(&mut self, _mac: &syn::Macro) {} fn visit_macro(&mut self, _mac: &'ast syn::Macro) {}
} }
let all_ty_params: HashSet<_> = generics let all_type_params = generics.type_params().map(|param| param.ident).collect();
.params
.iter()
.filter_map(|param| match *param {
syn::GenericParam::Type(ref param) => Some(param.ident),
_ => None,
})
.collect();
let mut visitor = FindTyParams { let mut visitor = FindTyParams {
all_ty_params: all_ty_params, all_type_params: all_type_params,
relevant_ty_params: HashSet::new(), relevant_type_params: HashSet::new(),
associated_type_usage: Vec::new(),
}; };
match cont.data { match cont.data {
Data::Enum(ref variants) => for variant in variants.iter() { Data::Enum(ref variants) => for variant in variants.iter() {
@@ -162,54 +170,47 @@ where
.iter() .iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs))); .filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields { for field in relevant_fields {
visit::visit_type(&mut visitor, field.ty); visitor.visit_field(field.original);
} }
}, },
Data::Struct(_, ref fields) => { Data::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) { for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visit::visit_type(&mut visitor, field.ty); visitor.visit_field(field.original);
} }
} }
} }
let relevant_type_params = visitor.relevant_type_params;
let associated_type_usage = visitor.associated_type_usage;
let new_predicates = generics let new_predicates = generics
.params .type_params()
.iter() .map(|param| param.ident)
.filter_map(|param| match *param { .filter(|id| relevant_type_params.contains(id))
syn::GenericParam::Type(ref param) => Some(param.ident), .map(|id| syn::TypePath {
_ => None, qself: None,
path: id.into(),
}) })
.filter(|id| visitor.relevant_ty_params.contains(id)) .chain(associated_type_usage.into_iter().cloned())
.map(|id| { .map(|bounded_ty| {
syn::WherePredicate::Type(syn::PredicateType { syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None, lifetimes: None,
// the type parameter that is being bounded e.g. T // the type parameter that is being bounded e.g. T
bounded_ty: syn::Type::Path(syn::TypePath { bounded_ty: syn::Type::Path(bounded_ty),
qself: None,
path: id.into(),
}),
colon_token: Default::default(), colon_token: Default::default(),
// the bound e.g. Serialize // the bound e.g. Serialize
bounds: vec![ bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
syn::TypeParamBound::Trait(syn::TraitBound { paren_token: None,
modifier: syn::TraitBoundModifier::None, modifier: syn::TraitBoundModifier::None,
lifetimes: None, lifetimes: None,
path: bound.clone(), path: bound.clone(),
}), })].into_iter()
].into_iter().collect(), .collect(),
}) })
}); });
let mut generics = generics.clone(); let mut generics = generics.clone();
if generics.where_clause.is_none() { generics
generics.where_clause = Some(syn::WhereClause { .make_where_clause()
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates .predicates
.extend(new_predicates); .extend(new_predicates);
generics generics
@@ -221,15 +222,8 @@ pub fn with_self_bound(
bound: &syn::Path, bound: &syn::Path,
) -> syn::Generics { ) -> syn::Generics {
let mut generics = generics.clone(); let mut generics = generics.clone();
if generics.where_clause.is_none() { generics
generics.where_clause = Some(syn::WhereClause { .make_where_clause()
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates .predicates
.push(syn::WherePredicate::Type(syn::PredicateType { .push(syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None, lifetimes: None,
@@ -237,19 +231,19 @@ pub fn with_self_bound(
bounded_ty: type_of_item(cont), bounded_ty: type_of_item(cont),
colon_token: Default::default(), colon_token: Default::default(),
// the bound e.g. Default // the bound e.g. Default
bounds: vec![ bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
syn::TypeParamBound::Trait(syn::TraitBound { paren_token: None,
modifier: syn::TraitBoundModifier::None, modifier: syn::TraitBoundModifier::None,
lifetimes: None, lifetimes: None,
path: bound.clone(), path: bound.clone(),
}), })].into_iter()
].into_iter().collect(), .collect(),
})); }));
generics generics
} }
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics { pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let bound = syn::Lifetime::new(Term::intern(lifetime), Span::def_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,
@@ -259,21 +253,18 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
let params = Some(syn::GenericParam::Lifetime(def)) let params = Some(syn::GenericParam::Lifetime(def))
.into_iter() .into_iter()
.chain(generics.params .chain(generics.params.iter().cloned().map(|mut param| {
.iter() match param {
.cloned() syn::GenericParam::Lifetime(ref mut param) => {
.map(|mut param| { param.bounds.push(bound);
match param {
syn::GenericParam::Lifetime(ref mut param) => {
param.bounds.push(bound);
}
syn::GenericParam::Type(ref mut param) => {
param.bounds.push(syn::TypeParamBound::Lifetime(bound));
}
syn::GenericParam::Const(_) => {}
} }
param syn::GenericParam::Type(ref mut param) => {
})) param.bounds.push(syn::TypeParamBound::Lifetime(bound));
}
syn::GenericParam::Const(_) => {}
}
param
}))
.collect(); .collect();
syn::Generics { syn::Generics {
@@ -287,36 +278,35 @@ fn type_of_item(cont: &Container) -> syn::Type {
qself: None, qself: None,
path: syn::Path { path: syn::Path {
leading_colon: None, leading_colon: None,
segments: vec![ segments: vec![syn::PathSegment {
syn::PathSegment { ident: cont.ident,
ident: cont.ident, 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.into(), }))
})) }
} syn::GenericParam::Lifetime(ref param) => {
syn::GenericParam::Lifetime(ref param) => { syn::GenericArgument::Lifetime(param.lifetime)
syn::GenericArgument::Lifetime(param.lifetime) }
} syn::GenericParam::Const(_) => {
syn::GenericParam::Const(_) => { panic!("Serde does not support const generics yet");
panic!("Serde does not support const generics yet"); }
} })
}) .collect(),
.collect(), gt_token: Default::default(),
gt_token: Default::default(), },
}, ),
), }].into_iter()
}, .collect(),
].into_iter().collect(),
}, },
}) })
} }
+612 -224
View File
File diff suppressed because it is too large Load Diff
@@ -6,10 +6,10 @@
// 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::attr;
use internals::check;
use internals::Ctxt;
use syn; use syn;
use attr;
use check;
use Ctxt;
use syn::punctuated::Punctuated; use syn::punctuated::Punctuated;
pub struct Container<'a> { pub struct Container<'a> {
@@ -48,7 +48,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) -> Container<'a> {
let 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 {
syn::Data::Enum(ref data) => { syn::Data::Enum(ref data) => {
@@ -63,18 +63,29 @@ impl<'a> Container<'a> {
} }
}; };
let mut has_flatten = false;
match data { match data {
Data::Enum(ref mut variants) => for variant in variants { Data::Enum(ref mut variants) => for variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all()); variant.attrs.rename_by_rule(attrs.rename_all());
for field in &mut variant.fields { for field in &mut variant.fields {
if field.attrs.flatten() {
has_flatten = true;
}
field.attrs.rename_by_rule(variant.attrs.rename_all()); field.attrs.rename_by_rule(variant.attrs.rename_all());
} }
}, },
Data::Struct(_, ref mut fields) => for field in fields { Data::Struct(_, ref mut fields) => for field in fields {
if field.attrs.flatten() {
has_flatten = true;
}
field.attrs.rename_by_rule(attrs.rename_all()); field.attrs.rename_by_rule(attrs.rename_all());
}, },
} }
if has_flatten {
attrs.mark_has_flatten();
}
let item = Container { let item = Container {
ident: item.ident, ident: item.ident,
attrs: attrs, attrs: attrs,
@@ -6,16 +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 Ctxt; use internals::Ctxt;
use proc_macro2::{Group, Span, TokenStream, TokenTree};
use std::collections::BTreeSet;
use std::str::FromStr;
use syn; use syn;
use syn::punctuated::Punctuated;
use syn::synom::{ParseError, Synom};
use syn::Ident; use syn::Ident;
use syn::Meta::{List, NameValue, Word}; use syn::Meta::{List, NameValue, Word};
use syn::NestedMeta::{Literal, Meta}; use syn::NestedMeta::{Literal, Meta};
use syn::punctuated::Punctuated;
use syn::synom::{Synom, ParseError};
use std::collections::BTreeSet;
use std::str::FromStr;
use proc_macro2::{Span, TokenStream, TokenNode, TokenTree};
// 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,8 +25,9 @@ use proc_macro2::{Span, TokenStream, TokenNode, TokenTree};
// 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)]
struct Attr<'c, T> { struct Attr<'c, T> {
cx: &'c Ctxt, cx: &'c Ctxt,
name: &'static str, name: &'static str,
@@ -114,6 +115,7 @@ pub struct Container {
type_into: Option<syn::Type>, type_into: Option<syn::Type>,
remote: Option<syn::Path>, remote: Option<syn::Path>,
identifier: Identifier, identifier: Identifier,
has_flatten: bool,
} }
/// Styles of representing an enum. /// Styles of representing an enum.
@@ -165,6 +167,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,
@@ -232,7 +235,10 @@ impl Container {
// Parse `#[serde(default)]` // Parse `#[serde(default)]`
Meta(Word(word)) if word == "default" => match item.data { Meta(Word(word)) if word == "default" => match item.data {
syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => { syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(_),
..
}) => {
default.set(Default::Default); default.set(Default::Default);
} }
_ => cx.error( _ => cx.error(
@@ -243,9 +249,12 @@ 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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
match item.data { match item.data {
syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => { syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(_),
..
}) => {
default.set(Default::Path(path)); default.set(Default::Path(path));
} }
_ => cx.error( _ => cx.error(
@@ -330,7 +339,11 @@ impl Container {
// 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.as_ref(), &m.lit) {
remote.set(path); if is_primitive_path(&path, "Self") {
remote.set(item.ident.into());
} else {
remote.set(path);
}
} }
} }
@@ -373,6 +386,7 @@ impl Container {
type_into: type_into.get(), type_into: type_into.get(),
remote: remote.get(), remote: remote.get(),
identifier: decide_identifier(cx, item, &field_identifier, &variant_identifier), identifier: decide_identifier(cx, item, &field_identifier, &variant_identifier),
has_flatten: false,
} }
} }
@@ -419,6 +433,14 @@ impl Container {
pub fn identifier(&self) -> Identifier { pub fn identifier(&self) -> Identifier {
self.identifier self.identifier
} }
pub fn has_flatten(&self) -> bool {
self.has_flatten
}
pub fn mark_has_flatten(&mut self) {
self.has_flatten = true;
}
} }
fn decide_tag( fn decide_tag(
@@ -488,13 +510,11 @@ fn decide_identifier(
} }
(&syn::Data::Enum(_), true, false) => Identifier::Field, (&syn::Data::Enum(_), true, false) => Identifier::Field,
(&syn::Data::Enum(_), false, true) => Identifier::Variant, (&syn::Data::Enum(_), false, true) => Identifier::Variant,
(&syn::Data::Struct(_), true, false) (&syn::Data::Struct(_), true, false) | (&syn::Data::Union(_), true, false) => {
| (&syn::Data::Union(_), true, false) => {
cx.error("`field_identifier` can only be used on an enum"); cx.error("`field_identifier` can only be used on an enum");
Identifier::No Identifier::No
} }
(&syn::Data::Struct(_), false, true) (&syn::Data::Struct(_), false, true) | (&syn::Data::Union(_), false, true) => {
| (&syn::Data::Union(_), false, true) => {
cx.error("`variant_identifier` can only be used on an enum"); cx.error("`variant_identifier` can only be used on an enum");
Identifier::No Identifier::No
} }
@@ -507,11 +527,13 @@ 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,
serialize_with: Option<syn::Path>, serialize_with: Option<syn::ExprPath>,
deserialize_with: Option<syn::Path>, deserialize_with: Option<syn::ExprPath>,
borrow: Option<syn::Meta>, borrow: Option<syn::Meta>,
} }
@@ -522,6 +544,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");
@@ -560,6 +584,12 @@ impl Variant {
} }
} }
// Parse `#[serde(skip)]`
Meta(Word(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(word)) if word == "skip_deserializing" => {
skip_deserializing.set_true(); skip_deserializing.set_true();
@@ -575,28 +605,52 @@ impl Variant {
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.as_ref(), m.ident.as_ref(), &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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path.segments.push(Ident::new("serialize", Span::call_site()).into()); ser_path
.path
.segments
.push(Ident::new("serialize", Span::call_site()).into());
serialize_with.set(ser_path); serialize_with.set(ser_path);
let mut de_path = path; let mut de_path = path;
de_path.segments.push(Ident::new("deserialize", Span::call_site()).into()); de_path
.path
.segments
.push(Ident::new("deserialize", Span::call_site()).into());
deserialize_with.set(de_path); deserialize_with.set(de_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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
@@ -637,6 +691,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(),
@@ -663,6 +719,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
} }
@@ -675,11 +739,11 @@ impl Variant {
self.other self.other
} }
pub fn serialize_with(&self) -> Option<&syn::Path> { pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
self.serialize_with.as_ref() self.serialize_with.as_ref()
} }
pub fn deserialize_with(&self) -> Option<&syn::Path> { pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
self.deserialize_with.as_ref() self.deserialize_with.as_ref()
} }
} }
@@ -691,14 +755,15 @@ pub struct Field {
de_renamed: bool, de_renamed: bool,
skip_serializing: bool, skip_serializing: bool,
skip_deserializing: bool, skip_deserializing: bool,
skip_serializing_if: Option<syn::Path>, skip_serializing_if: Option<syn::ExprPath>,
default: Default, default: Default,
serialize_with: Option<syn::Path>, serialize_with: Option<syn::ExprPath>,
deserialize_with: Option<syn::Path>, deserialize_with: Option<syn::ExprPath>,
ser_bound: Option<Vec<syn::WherePredicate>>, ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>, de_bound: Option<Vec<syn::WherePredicate>>,
borrowed_lifetimes: BTreeSet<syn::Lifetime>, borrowed_lifetimes: BTreeSet<syn::Lifetime>,
getter: Option<syn::Path>, getter: Option<syn::ExprPath>,
flatten: bool,
} }
/// Represents the default to use for a field when deserializing. /// Represents the default to use for a field when deserializing.
@@ -708,7 +773,17 @@ pub enum Default {
/// The default is given by `std::default::Default::default()`. /// The default is given by `std::default::Default::default()`.
Default, Default,
/// The default is given by this function. /// The default is given by this function.
Path(syn::Path), Path(syn::ExprPath),
}
impl Default {
#[cfg(feature = "deserialize_in_place")]
pub fn is_none(&self) -> bool {
match *self {
Default::None => true,
Default::Default | Default::Path(_) => false,
}
}
} }
impl Field { impl Field {
@@ -732,6 +807,7 @@ impl Field {
let mut de_bound = Attr::none(cx, "bound"); let mut de_bound = Attr::none(cx, "bound");
let mut borrowed_lifetimes = Attr::none(cx, "borrow"); let mut borrowed_lifetimes = Attr::none(cx, "borrow");
let mut getter = Attr::none(cx, "getter"); let mut getter = Attr::none(cx, "getter");
let mut flatten = BoolAttr::none(cx, "flatten");
let ident = match field.ident { let ident = match field.ident {
Some(ref ident) => ident.to_string(), Some(ref ident) => ident.to_string(),
@@ -739,9 +815,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
@@ -775,7 +849,7 @@ impl Field {
// 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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
default.set(Default::Path(path)); default.set(Default::Path(path));
} }
} }
@@ -798,33 +872,39 @@ impl Field {
// 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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path.segments.push(Ident::new("serialize", Span::call_site()).into()); ser_path
.path
.segments
.push(Ident::new("serialize", Span::call_site()).into());
serialize_with.set(ser_path); serialize_with.set(ser_path);
let mut de_path = path; let mut de_path = path;
de_path.segments.push(Ident::new("deserialize", Span::call_site()).into()); de_path
.path
.segments
.push(Ident::new("deserialize", Span::call_site()).into());
deserialize_with.set(de_path); deserialize_with.set(de_path);
} }
} }
@@ -856,7 +936,9 @@ 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) = parse_lit_into_lifetimes(cx, m.ident.as_ref(), &m.lit) { if let Ok(lifetimes) =
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) {
@@ -873,11 +955,16 @@ 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_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
getter.set(path); getter.set(path);
} }
} }
// Parse `#[serde(flatten)]`
Meta(Word(word)) if word == "flatten" => {
flatten.set_true();
}
Meta(ref meta_item) => { Meta(ref meta_item) => {
cx.error(format!( cx.error(format!(
"unknown serde field attribute `{}`", "unknown serde field attribute `{}`",
@@ -917,23 +1004,41 @@ impl Field {
leading_colon: None, leading_colon: None,
segments: Punctuated::new(), segments: Punctuated::new(),
}; };
path.segments.push(Ident::new("_serde", Span::def_site()).into()); path.segments
path.segments.push(Ident::new("private", Span::def_site()).into()); .push(Ident::new("_serde", Span::call_site()).into());
path.segments.push(Ident::new("de", Span::def_site()).into()); path.segments
path.segments.push(Ident::new("borrow_cow_str", Span::def_site()).into()); .push(Ident::new("private", Span::call_site()).into());
deserialize_with.set_if_none(path); path.segments
.push(Ident::new("de", Span::call_site()).into());
path.segments
.push(Ident::new("borrow_cow_str", Span::call_site()).into());
let expr = syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: path,
};
deserialize_with.set_if_none(expr);
} else if is_cow(&field.ty, is_slice_u8) { } else if is_cow(&field.ty, is_slice_u8) {
let mut path = syn::Path { let mut path = syn::Path {
leading_colon: None, leading_colon: None,
segments: Punctuated::new(), segments: Punctuated::new(),
}; };
path.segments.push(Ident::new("_serde", Span::def_site()).into()); path.segments
path.segments.push(Ident::new("private", Span::def_site()).into()); .push(Ident::new("_serde", Span::call_site()).into());
path.segments.push(Ident::new("de", Span::def_site()).into()); path.segments
path.segments.push(Ident::new("borrow_cow_bytes", Span::def_site()).into()); .push(Ident::new("private", Span::call_site()).into());
deserialize_with.set_if_none(path); path.segments
.push(Ident::new("de", Span::call_site()).into());
path.segments
.push(Ident::new("borrow_cow_bytes", Span::call_site()).into());
let expr = syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: path,
};
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);
@@ -960,6 +1065,7 @@ impl Field {
de_bound: de_bound.get(), de_bound: de_bound.get(),
borrowed_lifetimes: borrowed_lifetimes, borrowed_lifetimes: borrowed_lifetimes,
getter: getter.get(), getter: getter.get(),
flatten: flatten.get(),
} }
} }
@@ -984,7 +1090,7 @@ impl Field {
self.skip_deserializing self.skip_deserializing
} }
pub fn skip_serializing_if(&self) -> Option<&syn::Path> { pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> {
self.skip_serializing_if.as_ref() self.skip_serializing_if.as_ref()
} }
@@ -992,11 +1098,11 @@ impl Field {
&self.default &self.default
} }
pub fn serialize_with(&self) -> Option<&syn::Path> { pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
self.serialize_with.as_ref() self.serialize_with.as_ref()
} }
pub fn deserialize_with(&self) -> Option<&syn::Path> { pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
self.deserialize_with.as_ref() self.deserialize_with.as_ref()
} }
@@ -1012,9 +1118,13 @@ impl Field {
&self.borrowed_lifetimes &self.borrowed_lifetimes
} }
pub fn getter(&self) -> Option<&syn::Path> { pub fn getter(&self) -> Option<&syn::ExprPath> {
self.getter.as_ref() self.getter.as_ref()
} }
pub fn flatten(&self) -> bool {
self.flatten
}
} }
type SerAndDe<T> = (Option<T>, Option<T>); type SerAndDe<T> = (Option<T>, Option<T>);
@@ -1060,7 +1170,10 @@ where
Ok((ser_meta.get(), de_meta.get())) Ok((ser_meta.get(), de_meta.get()))
} }
fn get_renames<'a>(cx: &Ctxt, items: &'a Punctuated<syn::NestedMeta, Token![,]>) -> Result<SerAndDe<&'a syn::LitStr>, ()> { fn get_renames<'a>(
cx: &Ctxt,
items: &'a Punctuated<syn::NestedMeta, Token![,]>,
) -> Result<SerAndDe<&'a syn::LitStr>, ()> {
get_ser_and_de(cx, "rename", items, get_lit_str) get_ser_and_de(cx, "rename", items, get_lit_str)
} }
@@ -1104,7 +1217,18 @@ 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: &str, 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).map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value()))) parse_lit_str(string)
.map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
}
fn parse_lit_into_expr_path(
cx: &Ctxt,
attr_name: &str,
lit: &syn::Lit,
) -> Result<syn::ExprPath, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
parse_lit_str(string)
.map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
} }
fn parse_lit_into_where( fn parse_lit_into_where(
@@ -1118,7 +1242,7 @@ fn parse_lit_into_where(
return Ok(Vec::new()); return Ok(Vec::new());
} }
let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span); let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span());
parse_lit_str::<syn::WhereClause>(&where_string) parse_lit_str::<syn::WhereClause>(&where_string)
.map(|wh| wh.predicates.into_iter().collect()) .map(|wh| wh.predicates.into_iter().collect())
@@ -1131,7 +1255,8 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::
parse_lit_str(string).map_err(|_| { parse_lit_str(string).map_err(|_| {
cx.error(format!( cx.error(format!(
"failed to parse type: {} = {:?}", "failed to parse type: {} = {:?}",
attr_name, string.value() attr_name,
string.value()
)) ))
}) })
} }
@@ -1168,10 +1293,21 @@ fn parse_lit_into_lifetimes(
return Ok(set); return Ok(set);
} }
cx.error(format!("failed to parse borrowed lifetimes: {:?}", string.value())); cx.error(format!(
"failed to parse borrowed lifetimes: {:?}",
string.value()
));
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.
// //
@@ -1213,14 +1349,35 @@ fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
return false; return false;
} }
}; };
seg.ident == "Cow" seg.ident == "Cow" && args.len() == 2 && match (&args[0], &args[1]) {
&& args.len() == 2 (&syn::GenericArgument::Lifetime(_), &syn::GenericArgument::Type(ref arg)) => elem(arg),
&& match (&args[0], &args[1]) { _ => false,
(&syn::GenericArgument::Lifetime(_), &syn::GenericArgument::Type(ref arg)) => { }
elem(arg) }
}
_ => false, 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
@@ -1243,39 +1400,36 @@ 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) => { syn::Type::Reference(ref ty) => ty.mutability.is_none() && elem(&ty.elem),
ty.mutability.is_none() && elem(&ty.elem)
}
_ => false, _ => false,
} }
} }
fn is_str(ty: &syn::Type) -> bool { fn is_str(ty: &syn::Type) -> bool {
is_primitive_path(ty, "str") is_primitive_type(ty, "str")
} }
fn is_slice_u8(ty: &syn::Type) -> bool { fn is_slice_u8(ty: &syn::Type) -> bool {
match *ty { match *ty {
syn::Type::Slice(ref ty) => is_primitive_path(&ty.elem, "u8"), syn::Type::Slice(ref ty) => is_primitive_type(&ty.elem, "u8"),
_ => false, _ => false,
} }
} }
fn is_primitive_path(ty: &syn::Type, primitive: &str) -> bool { fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool {
match *ty { match *ty {
syn::Type::Path(ref ty) => { syn::Type::Path(ref ty) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive),
ty.qself.is_none()
&& ty.path.leading_colon.is_none()
&& ty.path.segments.len() == 1
&& ty.path.segments[0].ident == primitive
&& ty.path.segments[0].arguments.is_empty()
}
_ => false, _ => false,
} }
} }
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.segments[0].arguments.is_empty()
}
// All lifetimes that this type could borrow from a Deserializer. // All lifetimes that this type could borrow from a Deserializer.
// //
// For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand // For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand
@@ -1365,21 +1519,20 @@ where
fn spanned_tokens(s: &syn::LitStr) -> Result<TokenStream, ParseError> { fn spanned_tokens(s: &syn::LitStr) -> Result<TokenStream, ParseError> {
let stream = try!(syn::parse_str(&s.value())); let stream = try!(syn::parse_str(&s.value()));
Ok(respan_token_stream(stream, s.span)) Ok(respan_token_stream(stream, s.span()))
} }
fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream { fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
stream.into_iter().map(|token| respan_token_tree(token, span)).collect() stream
.into_iter()
.map(|token| respan_token_tree(token, span))
.collect()
} }
fn respan_token_tree(token: TokenTree, span: Span) -> TokenTree { fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
TokenTree { if let TokenTree::Group(ref mut g) = token {
span: span, *g = Group::new(g.delimiter(), respan_token_stream(g.stream().clone(), span));
kind: match token.kind {
TokenNode::Group(delimiter, nested) => {
TokenNode::Group(delimiter, respan_token_stream(nested, span))
}
other => other,
},
} }
token.set_span(span);
token
} }
@@ -7,7 +7,7 @@
// except according to those terms. // except according to those terms.
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726 // See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
#[allow(unused_imports)] #[allow(deprecated, unused_imports)]
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::str::FromStr; use std::str::FromStr;
@@ -113,14 +113,7 @@ impl FromStr for RenameRule {
fn rename_variants() { fn rename_variants() {
for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[ for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
( (
"Outcome", "Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
"outcome",
"OUTCOME",
"outcome",
"outcome",
"OUTCOME",
"outcome",
"OUTCOME",
), ),
( (
"VeryTasty", "VeryTasty",
@@ -154,13 +147,7 @@ fn rename_variants() {
fn rename_fields() { fn rename_fields() {
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[ for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
( (
"outcome", "outcome", "OUTCOME", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
"OUTCOME",
"Outcome",
"outcome",
"OUTCOME",
"outcome",
"OUTCOME",
), ),
( (
"very_tasty", "very_tasty",
@@ -6,14 +6,15 @@
// 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::{Data, Container, Style}; use internals::ast::{Container, Data, Field, Style};
use attr::{Identifier, EnumTag}; use internals::attr::{EnumTag, Identifier};
use Ctxt; use internals::Ctxt;
/// 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: &Container) {
check_getter(cx, cont); check_getter(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);
@@ -40,6 +41,55 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
} }
} }
/// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(ref variants) => {
for variant in variants {
for field in &variant.fields {
check_flatten_field(cx, variant.style, field);
}
}
}
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)]",
);
}
}
/// The `other` attribute must be used at most once and it must be the last /// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute. /// variant of an enum that has the `field_identifier` attribute.
/// ///
@@ -176,10 +226,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
/// the same as either one of its fields, as this would result in /// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in /// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input. /// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict( fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
cx: &Ctxt,
cont: &Container,
) {
let variants = match cont.data { let variants = match cont.data {
Data::Enum(ref variants) => variants, Data::Enum(ref variants) => variants,
Data::Struct(_, _) => return, Data::Struct(_, _) => return,
@@ -191,10 +238,7 @@ fn check_internal_tag_field_name_conflict(
}; };
let diagnose_conflict = || { let diagnose_conflict = || {
let message = format!( let message = format!("variant field name `{}` conflicts with internal tag", tag);
"variant field name `{}` conflicts with internal tag",
tag
);
cx.error(message); cx.error(message);
}; };
@@ -213,8 +257,8 @@ fn check_internal_tag_field_name_conflict(
return; return;
} }
} }
}, }
Style::Unit | Style::Newtype | Style::Tuple => {}, Style::Unit | Style::Newtype | Style::Tuple => {}
} }
} }
} }
@@ -223,7 +267,10 @@ fn check_internal_tag_field_name_conflict(
/// contents tag must differ, for the same reason. /// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) { fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
let (type_tag, content_tag) = match *cont.attrs.tag() { let (type_tag, content_tag) = match *cont.attrs.tag() {
EnumTag::Adjacent { ref tag, ref content } => (tag, content), EnumTag::Adjacent {
ref tag,
ref content,
} => (tag, content),
EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return, EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
}; };
@@ -6,8 +6,8 @@
// 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 std::fmt::Display;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::Display;
use std::thread; use std::thread;
#[derive(Default)] #[derive(Default)]
+16
View File
@@ -0,0 +1,16 @@
// 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;
+24 -7
View File
@@ -22,22 +22,37 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.32")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.55")]
#![cfg_attr(feature = "cargo-clippy", allow(enum_variant_names, redundant_field_names, #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
too_many_arguments, used_underscore_binding))] // Whitelisted clippy lints
#![cfg_attr(
feature = "cargo-clippy",
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 = "256"] #![recursion_limit = "512"]
#[macro_use] #[macro_use]
extern crate quote; 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;
@@ -46,8 +61,10 @@ mod bound;
#[macro_use] #[macro_use]
mod fragment; mod fragment;
mod ser;
mod de; mod de;
mod pretend;
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 {
+141
View File
@@ -0,0 +1,141 @@
use proc_macro2::Span;
use quote::Tokens;
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) -> Tokens {
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) -> Tokens {
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) -> Tokens {
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 names = variant.fields.iter().map(|field| field.ident);
quote!({ #(#names: #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]) -> Tokens {
let names = fields.iter().map(|field| field.ident);
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#names: ref #placeholders),* })
}
+305 -93
View File
@@ -6,17 +6,17 @@
// 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 syn::{self, Ident, Index, Member};
use syn::spanned::Spanned;
use quote::Tokens;
use proc_macro2::Span; use proc_macro2::Span;
use quote::Tokens;
use syn::spanned::Spanned;
use syn::{self, Ident, Index, Member};
use bound; use bound;
use fragment::{Fragment, Match, Stmts}; use fragment::{Fragment, Match, Stmts};
use internals::ast::{Data, Container, Field, Style, Variant}; use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, Ctxt}; use internals::{attr, Ctxt};
use pretend;
use std::u32; use try;
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> { pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = Ctxt::new(); let ctxt = Ctxt::new();
@@ -24,20 +24,22 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
precondition(&ctxt, &cont); precondition(&ctxt, &cont);
try!(ctxt.check()); try!(ctxt.check());
let ident = &cont.ident; let ident = cont.ident;
let params = Parameters::new(&cont); let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::def_site()); let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::call_site());
let body = Stmts(serialize_body(&cont, &params)); let body = Stmts(serialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
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 +49,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 +58,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
}; };
}; };
@@ -98,9 +103,9 @@ impl Parameters {
fn new(cont: &Container) -> Self { fn new(cont: &Container) -> Self {
let is_remote = cont.attrs.remote().is_some(); let is_remote = cont.attrs.remote().is_some();
let self_var = if is_remote { let self_var = if is_remote {
Ident::new("__self", Span::def_site()) Ident::new("__self", Span::call_site())
} else { } else {
Ident::new("self", Span::def_site()) Ident::new("self", Span::call_site())
}; };
let this = match cont.attrs.remote() { let this = match cont.attrs.remote() {
@@ -133,6 +138,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,13 +153,16 @@ 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 {
@@ -181,7 +192,7 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
} }
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! {
_serde::Serialize::serialize( _serde::Serialize::serialize(
&_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)), &_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
@@ -204,15 +215,19 @@ fn serialize_newtype_struct(
) -> Fragment { ) -> Fragment {
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
let mut field_expr = get_member(params, field, &Member::Unnamed(Index { let mut field_expr = get_member(
index: 0, params,
span: Span::call_site(), field,
})); &Member::Unnamed(Index {
index: 0,
span: Span::call_site(),
}),
);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
let span = Span::def_site().located_at(field.original.span()); let span = field.original.span();
let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct); let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
quote_expr! { quote_expr! {
#func(__serializer, #type_name, #field_expr) #func(__serializer, #type_name, #field_expr)
@@ -224,16 +239,32 @@ fn serialize_tuple_struct(
fields: &[Field], fields: &[Field],
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Fragment { ) -> Fragment {
let serialize_stmts = serialize_tuple_struct_visitor( let serialize_stmts =
fields, serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct);
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,14 +274,22 @@ 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()));
let serialize_fields = serialize_struct_visitor( if cattrs.has_flatten() {
fields, serialize_struct_as_map(params, fields, cattrs)
params, } else {
false, serialize_struct_as_struct(params, fields, cattrs)
&StructTrait::SerializeStruct, }
); }
fn serialize_struct_as_struct(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
@@ -279,10 +318,48 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
} }
} }
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { fn serialize_struct_as_map(
assert!(variants.len() as u64 <= u64::from(u32::MAX)); params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
let self_var = &params.self_var; let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = if cattrs.has_flatten() {
quote!(_serde::export::None)
} else {
let len = serialized_fields
.map(|field| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let ident = field.ident.expect("struct has unnamed fields");
let field_expr = get_member(params, field, &Member::Named(ident));
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote!(_serde::export::Some(#len))
};
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
assert!(variants.len() as u64 <= u64::from(u32::max_value()));
let self_var = params.self_var;
let arms: Vec<_> = variants let arms: Vec<_> = variants
.iter() .iter()
@@ -339,8 +416,8 @@ fn serialize_variant(
} }
} }
Style::Tuple => { Style::Tuple => {
let field_names = let field_names = (0..variant.fields.len())
(0..variant.fields.len()).map(|i| Ident::new(&format!("__field{}", i), Span::def_site())); .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
quote! { quote! {
#this::#variant_ident(#(ref #field_names),*) #this::#variant_ident(#(ref #field_names),*)
} }
@@ -548,9 +625,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)
@@ -573,9 +656,9 @@ fn serialize_adjacently_tagged_variant(
unreachable!() unreachable!()
} }
} }
Style::Newtype => vec![Ident::new("__field0", Span::def_site())], Style::Newtype => vec![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::def_site())) .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()))
.collect(), .collect(),
Style::Struct => variant Style::Struct => variant
.fields .fields
@@ -586,7 +669,7 @@ fn serialize_adjacently_tagged_variant(
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")
@@ -601,7 +684,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
@@ -679,8 +763,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 {
@@ -729,13 +828,15 @@ 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 { .. } => ( StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
StructTrait::SerializeStructVariant StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
), (StructTrait::SerializeStruct)
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => ( }
StructTrait::SerializeStruct
),
}; };
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
@@ -805,6 +906,92 @@ 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 fields_ident = &fields.iter().map(|f| f.ident).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 (#(#fields_ident,)*) = 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: (#(#fields_ident,)*),
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,
@@ -814,15 +1001,20 @@ fn serialize_tuple_struct_visitor(
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::def_site()); let id = Ident::new(&format!("__field{}", i), Span::call_site());
quote!(#id) quote!(#id)
} else { } else {
get_member(params, field, &Member::Unnamed(Index { get_member(
index: i as u32, params,
span: Span::call_site(), field,
})) &Member::Unnamed(Index {
index: i as u32,
span: Span::call_site(),
}),
)
}; };
let skip = field let skip = field
@@ -834,7 +1026,7 @@ fn serialize_tuple_struct_visitor(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
let span = Span::def_site().located_at(field.original.span()); let span = field.original.span();
let func = tuple_trait.serialize_element(span); let func = tuple_trait.serialize_element(span);
let ser = quote! { let ser = quote! {
try!(#func(&mut __serde_state, #field_expr)); try!(#func(&mut __serde_state, #field_expr));
@@ -859,6 +1051,7 @@ fn serialize_struct_visitor(
.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 field_ident = field.ident.expect("struct has unnamed field");
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
quote!(#field_ident) quote!(#field_ident)
} else { } else {
@@ -876,21 +1069,34 @@ fn serialize_struct_visitor(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
let span = Span::def_site().located_at(field.original.span()); let span = field.original.span();
let func = struct_trait.serialize_field(span); let ser = if field.attrs.flatten() {
let ser = quote! { quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr)); try!(_serde::Serialize::serialize(&#field_expr, _serde::private::ser::FlatMapSerializer(&mut __serde_state)));
}
} else {
let func = struct_trait.serialize_field(span);
quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
}
}; };
match skip { match skip {
None => ser, None => ser,
Some(skip) => { Some(skip) => {
let skip_func = struct_trait.skip_field(span); if let Some(skip_func) = struct_trait.skip_field(span) {
quote! { quote! {
if !#skip { if !#skip {
#ser #ser
} else { } else {
try!(#skip_func(&mut __serde_state, #key_expr)); try!(#skip_func(&mut __serde_state, #key_expr));
}
}
} else {
quote! {
if !#skip {
#ser
}
} }
} }
} }
@@ -902,7 +1108,7 @@ fn serialize_struct_visitor(
fn wrap_serialize_field_with( fn wrap_serialize_field_with(
params: &Parameters, params: &Parameters,
field_ty: &syn::Type, field_ty: &syn::Type,
serialize_with: &syn::Path, serialize_with: &syn::ExprPath,
field_expr: &Tokens, field_expr: &Tokens,
) -> Tokens { ) -> Tokens {
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
@@ -910,7 +1116,7 @@ fn wrap_serialize_field_with(
fn wrap_serialize_variant_with( fn wrap_serialize_variant_with(
params: &Parameters, params: &Parameters,
serialize_with: &syn::Path, serialize_with: &syn::ExprPath,
variant: &Variant, variant: &Variant,
) -> Tokens { ) -> Tokens {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
@@ -921,7 +1127,7 @@ fn wrap_serialize_variant_with(
.map(|(i, field)| { .map(|(i, field)| {
let id = field let id = field
.ident .ident
.unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::def_site())); .unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::call_site()));
quote!(#id) quote!(#id)
}) })
.collect(); .collect();
@@ -935,7 +1141,7 @@ fn wrap_serialize_variant_with(
fn wrap_serialize_with( fn wrap_serialize_with(
params: &Parameters, params: &Parameters,
serialize_with: &syn::Path, serialize_with: &syn::ExprPath,
field_tys: &[&syn::Type], field_tys: &[&syn::Type],
field_exprs: &[Tokens], field_exprs: &[Tokens],
) -> Tokens { ) -> Tokens {
@@ -949,10 +1155,12 @@ fn wrap_serialize_with(
}; };
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
let field_access = (0..field_exprs.len()).map(|n| Member::Unnamed(Index { let field_access = (0..field_exprs.len()).map(|n| {
index: n as u32, Member::Unnamed(Index {
span: Span::call_site(), index: n as u32,
})); span: Span::call_site(),
})
});
quote!({ quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause { struct __SerializeWith #wrapper_impl_generics #where_clause {
@@ -962,7 +1170,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)
} }
@@ -990,13 +1199,11 @@ 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) -> Tokens {
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) => { (false, None) => quote!(&#self_var.#member),
quote_spanned!(Span::call_site()=> &#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))
} }
@@ -1011,6 +1218,7 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
} }
enum StructTrait { enum StructTrait {
SerializeMap,
SerializeStruct, SerializeStruct,
SerializeStructVariant, SerializeStructVariant,
} }
@@ -1018,6 +1226,9 @@ enum StructTrait {
impl StructTrait { impl StructTrait {
fn serialize_field(&self, span: Span) -> Tokens { fn serialize_field(&self, span: Span) -> Tokens {
match *self { match *self {
StructTrait::SerializeMap => {
quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
}
StructTrait::SerializeStruct => { StructTrait::SerializeStruct => {
quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field) quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
} }
@@ -1027,13 +1238,14 @@ impl StructTrait {
} }
} }
fn skip_field(&self, span: Span) -> Tokens { fn skip_field(&self, span: Span) -> Option<Tokens> {
match *self { match *self {
StructTrait::SerializeMap => None,
StructTrait::SerializeStruct => { StructTrait::SerializeStruct => {
quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field) Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field))
} }
StructTrait::SerializeStructVariant => { StructTrait::SerializeStructVariant => {
quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field) Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field))
} }
} }
} }
+25
View File
@@ -0,0 +1,25 @@
use proc_macro2::{Op, Spacing};
use quote::Tokens;
// 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() -> Tokens {
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
let dollar = Op::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);
}
}
}
}
}
}
+7 -4
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.20.1" # remember to update html_root_url version = "0.23.1" # 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 = "AST representation used by Serde derive macros. Unstable." description = "AST representation used by Serde derive macros. Unstable."
@@ -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.2" proc-macro2 = "0.3"
syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls"] } syn = { version = "0.13", default-features = false, features = ["derive", "parsing", "clone-impls"] }
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -6,20 +6,18 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.20.1")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")]
#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity, doc_markdown, match_same_arms, #![cfg_attr(
redundant_field_names))] feature = "cargo-clippy",
allow(cyclomatic_complexity, doc_markdown, match_same_arms, redundant_field_names)
)]
#[macro_use] #[macro_use]
extern crate syn; 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/
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.32" # remember to update html_root_url version = "1.0.55" # 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"
File diff suppressed because it is too large Load Diff
+15 -13
View File
@@ -6,9 +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 serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
SeqAccess, VariantAccess, Visitor};
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer}; use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use serde::de::{
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use error::Error; use error::Error;
use token::Token; use token::Token;
@@ -22,28 +24,28 @@ macro_rules! assert_next_token {
($de:expr, $expected:expr) => { ($de:expr, $expected:expr) => {
match $de.next_token_opt() { match $de.next_token_opt() {
Some(token) if token == $expected => {} Some(token) if token == $expected => {}
Some(other) => { Some(other) => panic!(
panic!("expected Token::{} but deserialization wants Token::{}", "expected Token::{} but deserialization wants Token::{}",
other, $expected) other, $expected
} ),
None => { None => panic!(
panic!("end of tokens but deserialization wants Token::{}", "end of tokens but deserialization wants Token::{}",
$expected) $expected
} ),
} }
} };
} }
macro_rules! unexpected { macro_rules! unexpected {
($token:expr) => { ($token:expr) => {
panic!("deserialization did not expect this token: {}", $token) panic!("deserialization did not expect this token: {}", $token)
} };
} }
macro_rules! end_of_tokens { macro_rules! end_of_tokens {
() => { () => {
panic!("ran out of tokens to deserialize") panic!("ran out of tokens to deserialize")
} };
} }
impl<'de> Deserializer<'de> { impl<'de> Deserializer<'de> {
+29 -17
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,29 +161,35 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.32")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.55")]
#![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))]
// Whitelisted clippy_pedantic lints // Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", #![cfg_attr(
allow(empty_line_after_outer_attr, missing_docs_in_private_items, feature = "cargo-clippy",
redundant_field_names, stutter, use_debug, use_self))] allow(
empty_line_after_outer_attr, missing_docs_in_private_items, redundant_field_names, stutter,
use_debug, use_self
)
)]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
mod ser;
mod de; mod de;
mod error; mod error;
mod ser;
mod assert;
mod configure; mod configure;
mod token; mod token;
mod assert;
pub use assert::{
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 assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
assert_ser_tokens_error, assert_tokens};
pub use configure::{Compact, Configure, Readable}; pub use configure::{Compact, Configure, Readable};
+3 -3
View File
@@ -45,7 +45,7 @@ macro_rules! assert_next_token {
($ser:expr, $expected:ident($v:expr)) => { ($ser:expr, $expected:ident($v:expr)) => {
assert_next_token!( assert_next_token!(
$ser, $ser,
format_args!("{}({:?})", stringify!($expected), $v), format_args!(concat!(stringify!($expected), "({:?})"), $v),
Token::$expected(v), Token::$expected(v),
v == $v v == $v
); );
@@ -56,13 +56,13 @@ macro_rules! assert_next_token {
use std::fmt::Write; use std::fmt::Write;
let mut buffer = String::new(); let mut buffer = String::new();
$( $(
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap(); write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
)* )*
buffer buffer
}; };
assert_next_token!( assert_next_token!(
$ser, $ser,
format_args!("{} {{ {}}}", stringify!($expected), field_format()), format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
Token::$expected { $($k),* }, Token::$expected { $($k),* },
($($k,)*) == compare ($($k,)*) == compare
); );
+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.2" proc-macro2 = "0.3"
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"] }
+11 -12
View File
@@ -6,11 +6,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![feature(lang_items, start, compiler_builtins_lib)] #![feature(lang_items, start)]
#![no_std] #![no_std]
extern crate libc; extern crate libc;
extern crate compiler_builtins;
#[start] #[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize { fn start(_argc: isize, _argv: *const *const u8) -> isize {
@@ -19,19 +18,17 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
#[lang = "eh_personality"] #[lang = "eh_personality"]
#[no_mangle] #[no_mangle]
pub extern fn rust_eh_personality() {} pub extern "C" fn rust_eh_personality() {}
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {}
#[lang = "panic_fmt"] #[lang = "panic_fmt"]
#[no_mangle] #[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, pub extern "C" fn rust_begin_panic(
_file: &'static str, _msg: core::fmt::Arguments,
_line: u32) -> ! { _file: &'static str,
_line: u32,
) -> ! {
unsafe { unsafe {
libc::abort() libc::abort();
} }
} }
@@ -50,7 +47,9 @@ struct Newtype(u8);
struct Tuple(u8, u8); struct Tuple(u8, u8);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Struct { f: u8 } struct Struct {
f: u8,
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
enum Enum { enum Enum {
+58
View File
@@ -0,0 +1,58 @@
use serde::de::{Deserializer, Error, SeqAccess, Visitor};
use std::fmt;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_byte_buf(ByteBufVisitor)
}
struct ByteBufVisitor;
impl<'de> Visitor<'de> for ByteBufVisitor {
type Value = Vec<u8>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'de>,
{
let mut values = Vec::new();
while let Some(value) = try!(visitor.next_element()) {
values.push(value);
}
Ok(values)
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v.to_vec())
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v.as_bytes().to_vec())
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v.into_bytes())
}
}
@@ -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(Serialize)] //~ ERROR: proc-macro derive panicked
//~^ HELP: #[serde(flatten)] cannot be used on newtype structs
struct Foo(#[serde(flatten)] HashMap<String, String>);
fn main() {}
@@ -0,0 +1,24 @@
// 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
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_deserializing)]
struct Foo {
#[serde(flatten, skip_deserializing)]
other: Other,
}
#[derive(Deserialize)]
struct Other {
x: u32
}
fn main() {}
@@ -0,0 +1,24 @@
// 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
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_serializing_if = "...")]
struct Foo {
#[serde(flatten, skip_serializing_if="Option::is_none")]
other: Option<Other>,
}
#[derive(Serialize)]
struct Other {
x: u32
}
fn main() {}
@@ -0,0 +1,24 @@
// 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
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_serializing)]
struct Foo {
#[serde(flatten, skip_serializing)]
other: Other,
}
#[derive(Serialize)]
struct Other {
x: u32
}
fn main() {}
@@ -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(Serialize)] //~ ERROR: proc-macro derive panicked
//~^ HELP: #[serde(flatten)] cannot be used on tuple structs
struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
fn main() {}
@@ -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
}
File diff suppressed because it is too large Load Diff
+49 -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 {
@@ -788,11 +809,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),
+170 -55
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),
} }
@@ -386,10 +409,11 @@ fn test_gen() {
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
enum ExternallyTaggedVariantWith { #[serde(remote = "Self")]
#[allow(dead_code)] struct RemoteSelf;
Normal { f1: String },
#[derive(Serialize, Deserialize)]
enum ExternallyTaggedVariantWith {
#[serde(serialize_with = "ser_x")] #[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")] #[serde(deserialize_with = "de_x")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -400,6 +424,11 @@ fn test_gen() {
#[allow(dead_code)] #[allow(dead_code)]
Tuple(String, u8), Tuple(String, u8),
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
#[allow(dead_code)]
Struct1 { x: X },
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -415,14 +444,16 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(tag = "t")] #[serde(tag = "t")]
enum InternallyTaggedVariantWith { enum InternallyTaggedVariantWith {
#[allow(dead_code)]
Normal { f1: String },
#[serde(serialize_with = "ser_x")] #[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")] #[serde(deserialize_with = "de_x")]
#[allow(dead_code)] #[allow(dead_code)]
Newtype(X), Newtype(X),
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
#[allow(dead_code)]
Struct1 { x: X },
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -438,9 +469,6 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(tag = "t", content = "c")] #[serde(tag = "t", content = "c")]
enum AdjacentlyTaggedVariantWith { enum AdjacentlyTaggedVariantWith {
#[allow(dead_code)]
Normal { f1: String },
#[serde(serialize_with = "ser_x")] #[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")] #[serde(deserialize_with = "de_x")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -451,6 +479,11 @@ fn test_gen() {
#[allow(dead_code)] #[allow(dead_code)]
Tuple(String, u8), Tuple(String, u8),
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
#[allow(dead_code)]
Struct1 { x: X },
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -466,9 +499,6 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
enum UntaggedVariantWith { enum UntaggedVariantWith {
#[allow(dead_code)]
Normal { f1: String },
#[serde(serialize_with = "ser_x")] #[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")] #[serde(deserialize_with = "de_x")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -479,6 +509,11 @@ fn test_gen() {
#[allow(dead_code)] #[allow(dead_code)]
Tuple(String, u8), Tuple(String, u8),
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
#[allow(dead_code)]
Struct1 { x: X },
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
@@ -491,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,
@@ -519,7 +561,9 @@ fn test_gen() {
assert::<SkippedStaticStr>(); assert::<SkippedStaticStr>();
macro_rules! T { macro_rules! T {
() => { () } () => {
()
};
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -528,6 +572,77 @@ fn test_gen() {
marker: PhantomData<T>, marker: PhantomData<T>,
} }
assert::<TypeMacro<X>>(); assert::<TypeMacro<X>>();
#[derive(Serialize)]
struct BigArray {
#[serde(serialize_with = "<[_]>::serialize")]
array: [u8; 256],
}
assert_ser::<BigArray>();
trait AssocSerde {
type Assoc;
}
struct NoSerdeImpl;
impl AssocSerde for NoSerdeImpl {
type Assoc = u32;
}
#[derive(Serialize, Deserialize)]
struct AssocDerive<T: AssocSerde> {
assoc: T::Assoc,
}
assert::<AssocDerive<NoSerdeImpl>>();
#[derive(Serialize, Deserialize)]
struct AssocDeriveMulti<S, T: AssocSerde> {
s: S,
assoc: T::Assoc,
}
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>,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+370 -27
View File
@@ -7,15 +7,19 @@
// 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]
extern crate serde_derive; extern crate serde_derive;
extern crate serde;
extern crate serde_test; extern crate serde_test;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens,
Token}; mod bytes;
use self::serde_test::{
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;
@@ -222,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", }],
},
],
); );
} }
@@ -292,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", }],
},
],
); );
} }
@@ -442,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(
@@ -462,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", }],
},
],
); );
} }
@@ -779,6 +822,166 @@ fn test_internally_tagged_enum() {
); );
} }
#[test]
fn test_internally_tagged_bytes() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "type")]
enum InternallyTagged {
String {
string: String,
},
Bytes {
#[serde(with = "bytes")]
bytes: Vec<u8>,
},
}
assert_de_tokens(
&InternallyTagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "String",
len: 2,
},
Token::Str("type"),
Token::Str("String"),
Token::Str("string"),
Token::Str("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "String",
len: 2,
},
Token::Str("type"),
Token::Str("String"),
Token::Str("string"),
Token::String("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "String",
len: 2,
},
Token::Str("type"),
Token::Str("String"),
Token::Str("string"),
Token::Bytes(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "String",
len: 2,
},
Token::Str("type"),
Token::Str("String"),
Token::Str("string"),
Token::ByteBuf(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Bytes",
len: 2,
},
Token::Str("type"),
Token::Str("Bytes"),
Token::Str("bytes"),
Token::Str("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Bytes",
len: 2,
},
Token::Str("type"),
Token::Str("Bytes"),
Token::Str("bytes"),
Token::String("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Bytes",
len: 2,
},
Token::Str("type"),
Token::Str("Bytes"),
Token::Str("bytes"),
Token::Bytes(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Bytes",
len: 2,
},
Token::Str("type"),
Token::Str("Bytes"),
Token::Str("bytes"),
Token::ByteBuf(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Bytes",
len: 2,
},
Token::Str("type"),
Token::Str("Bytes"),
Token::Str("bytes"),
Token::Seq { len: Some(1) },
Token::U8(0),
Token::SeqEnd,
Token::StructEnd,
],
);
}
#[test] #[test]
fn test_internally_tagged_struct_variant_containing_unit_variant() { fn test_internally_tagged_struct_variant_containing_unit_variant() {
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -1198,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(
@@ -1246,6 +1447,148 @@ fn test_enum_in_untagged_enum() {
); );
} }
#[test]
fn test_untagged_bytes() {
#[derive(Debug, PartialEq, Deserialize)]
#[serde(untagged)]
enum Untagged {
String {
string: String,
},
Bytes {
#[serde(with = "bytes")]
bytes: Vec<u8>,
},
}
assert_de_tokens(
&Untagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("string"),
Token::Str("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("string"),
Token::String("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("string"),
Token::Bytes(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::String {
string: "\0".to_owned(),
},
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("string"),
Token::ByteBuf(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("bytes"),
Token::Str("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("bytes"),
Token::String("\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("bytes"),
Token::Bytes(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("bytes"),
Token::ByteBuf(b"\0"),
Token::StructEnd,
],
);
assert_de_tokens(
&Untagged::Bytes { bytes: vec![0] },
&[
Token::Struct {
name: "Untagged",
len: 1,
},
Token::Str("bytes"),
Token::Seq { len: Some(1) },
Token::U8(0),
Token::SeqEnd,
Token::StructEnd,
],
);
}
#[test] #[test]
fn test_rename_all() { fn test_rename_all() {
#[derive(Serialize, Deserialize, Debug, PartialEq)] #[derive(Serialize, Deserialize, Debug, PartialEq)]
+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,
} }
+36 -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),
+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