Compare commits

...

271 Commits

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

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

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

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

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

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

Instead the new implementation does simply:

    _serde::ser::SerializeStruct::serialize_field(
        &mut __struct,
        "content",
        __field0,
    )?;
2018-04-21 11:41:39 -07:00
David Tolnay b37cf858ce Remove unneeded quote_spanned that uses call_site 2018-04-21 11:33:39 -07:00
David Tolnay 5f8fa33756 Quote's default has changed to call_site 2018-04-21 11:33:38 -07:00
David Tolnay f3f006f411 Merge pull request #1226 from serde-rs/try
More efficient try!() alternative
2018-04-21 11:33:28 -07:00
David Tolnay 607966dcf7 Fix error message type inference in compile-fail/remote/wrong_de.rs 2018-04-21 11:21:13 -07:00
David Tolnay 6a8c39b2aa More efficient try!() alternative 2018-04-21 10:53:13 -07:00
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
68 changed files with 6960 additions and 1914 deletions
+7
View File
@@ -0,0 +1,7 @@
---
name: Problem
about: Something does not seem right
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Suggestion
about: Share how Serde could support your use case better
---
@@ -0,0 +1,7 @@
---
name: Documentation
about: Certainly there is room for improvement
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Help or discussion
about: This is the right place
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Anything else!
about: Whatever is on your mind
---
+1
View File
@@ -5,6 +5,7 @@ cache: cargo
# run builds for all the trains (and more) # run builds for all the trains (and more)
rust: rust:
- 1.13.0 - 1.13.0
- 1.15.0
- stable - stable
- beta - beta
- nightly - nightly
+3 -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
+3 -7
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.61" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
@@ -10,7 +10,8 @@ documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"] categories = ["encoding"]
readme = "README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "build.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs"
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -61,8 +62,3 @@ alloc = ["unstable"]
# does not preserve identity and may result in multiple copies of the same data. # does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature. # Be sure that this is what you want before enabling this feature.
rc = [] rc = []
# Get serde_derive picked up by the Integer 32 playground. Not public API.
#
# http://play.integer32.com/
playground = ["serde_derive"]
+60
View File
@@ -0,0 +1,60 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
fn main() {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return,
};
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return;
}
let next = match pieces.next() {
Some(next) => next,
None => return,
};
let minor = match u32::from_str(next) {
Ok(minor) => minor,
Err(_) => return,
};
// CString::into_boxed_c_str stabilized in Rust 1.20:
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
if minor >= 20 {
println!("cargo:rustc-cfg=de_boxed_c_str");
}
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
if minor >= 21 {
println!("cargo:rustc-cfg=de_rc_dst");
}
// 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
if minor >= 26 {
println!("cargo:rustc-cfg=integer128");
}
// Non-zero integers stabilized in Rust 1.28:
// https://github.com/rust-lang/rust/pull/50808
if minor >= 28 {
println!("cargo:rustc-cfg=num_nonzero");
}
}
+196 -44
View File
@@ -9,42 +9,40 @@
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 {
fn from_isize(n: isize) -> Option<Self>;
fn from_i8(n: i8) -> Option<Self>; fn from_i8(n: i8) -> Option<Self>;
fn from_i16(n: i16) -> Option<Self>; fn from_i16(n: i16) -> Option<Self>;
fn from_i32(n: i32) -> Option<Self>; fn from_i32(n: i32) -> Option<Self>;
fn from_i64(n: i64) -> Option<Self>; fn from_i64(n: i64) -> Option<Self>;
fn from_usize(n: usize) -> Option<Self>;
fn from_u8(n: u8) -> Option<Self>; fn from_u8(n: u8) -> Option<Self>;
fn from_u16(n: u16) -> Option<Self>; fn from_u16(n: u16) -> Option<Self>;
fn from_u32(n: u32) -> Option<Self>; fn from_u32(n: u32) -> Option<Self>;
@@ -52,54 +50,120 @@ 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_i8(n: i8) -> 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_i16(n: i16) -> 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_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_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_i8(n: i8) -> 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_i16(n: i16) -> 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_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_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_i8(n: i8) -> 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_i16(n: i16) -> 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_i32(n: i32) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i64(n: i64) -> 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);
@@ -114,3 +178,91 @@ impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64); impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32); impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64); impl_from_primitive_for_float!(f64);
serde_if_integer128! {
impl FromPrimitive for i128 {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as i128)
}
}
impl FromPrimitive for u128 {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as u128)
}
}
}
+10 -5
View File
@@ -45,7 +45,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// } /// }
/// ///
/// impl<'de, T> Visitor<'de> for NthElement<T> /// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// type Value = T; /// type Value = T;
/// ///
@@ -54,7 +55,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// } /// }
/// ///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> /// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de> /// where
/// A: SeqAccess<'de>,
/// { /// {
/// // Skip over the first `n` elements. /// // Skip over the first `n` elements.
/// for i in 0..self.n { /// for i in 0..self.n {
@@ -82,19 +84,22 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// } /// }
/// ///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T> /// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// type Value = T; /// type Value = T;
/// ///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> /// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// deserializer.deserialize_seq(self) /// deserializer.deserialize_seq(self)
/// } /// }
/// } /// }
/// ///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> /// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de> /// # where
/// # D: Deserializer<'de>,
/// # { /// # {
/// // Deserialize only the sequence element at index 3 from this deserializer. /// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and /// // The element at index 3 is required to be a string. Elements before and
+295 -107
View File
@@ -8,8 +8,9 @@
use lib::*; use lib::*;
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, use de::{
Visitor}; Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::MapAccess; use de::MapAccess;
@@ -31,7 +32,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
formatter.write_str("unit") formatter.write_str("unit")
} }
fn visit_unit<E>(self) -> Result<(), E> fn visit_unit<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -40,7 +41,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
} }
impl<'de> Deserialize<'de> for () { impl<'de> Deserialize<'de> for () {
fn deserialize<D>(deserializer: D) -> Result<(), D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -59,7 +60,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
formatter.write_str("a boolean") formatter.write_str("a boolean")
} }
fn visit_bool<E>(self, v: bool) -> Result<bool, E> fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -68,7 +69,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
} }
impl<'de> Deserialize<'de> for bool { impl<'de> Deserialize<'de> for bool {
fn deserialize<D>(deserializer: D) -> Result<bool, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -109,7 +110,7 @@ macro_rules! impl_deserialize_num {
($ty:ident, $method:ident, $($visit:ident),*) => { ($ty:ident, $method:ident, $($visit:ident),*) => {
impl<'de> Deserialize<'de> for $ty { impl<'de> Deserialize<'de> for $ty {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -165,6 +166,92 @@ impl_deserialize_num!(usize, deserialize_u64, integer);
impl_deserialize_num!(f32, deserialize_f32, integer, float); impl_deserialize_num!(f32, deserialize_f32, integer, float);
impl_deserialize_num!(f64, deserialize_f64, integer, float); impl_deserialize_num!(f64, deserialize_f64, integer, float);
serde_if_integer128! {
impl<'de> Deserialize<'de> for i128 {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PrimitiveVisitor;
impl<'de> Visitor<'de> for PrimitiveVisitor {
type Value = i128;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("i128")
}
impl_deserialize_num!(integer i128);
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v)
}
#[inline]
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
if v <= i128::max_value() as u128 {
Ok(v as i128)
} else {
Err(Error::invalid_value(Unexpected::Other("u128"), &self))
}
}
}
deserializer.deserialize_i128(PrimitiveVisitor)
}
}
impl<'de> Deserialize<'de> for u128 {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PrimitiveVisitor;
impl<'de> Visitor<'de> for PrimitiveVisitor {
type Value = u128;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("u128")
}
impl_deserialize_num!(integer u128);
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
if v >= 0 {
Ok(v as u128)
} else {
Err(Error::invalid_value(Unexpected::Other("i128"), &self))
}
}
#[inline]
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v)
}
}
deserializer.deserialize_u128(PrimitiveVisitor)
}
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct CharVisitor; struct CharVisitor;
@@ -177,7 +264,7 @@ impl<'de> Visitor<'de> for CharVisitor {
} }
#[inline] #[inline]
fn visit_char<E>(self, v: char) -> Result<char, E> fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -185,7 +272,7 @@ impl<'de> Visitor<'de> for CharVisitor {
} }
#[inline] #[inline]
fn visit_str<E>(self, v: &str) -> Result<char, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -199,7 +286,7 @@ impl<'de> Visitor<'de> for CharVisitor {
impl<'de> Deserialize<'de> for char { impl<'de> Deserialize<'de> for char {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<char, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -222,21 +309,21 @@ impl<'de> Visitor<'de> for StringVisitor {
formatter.write_str("a string") formatter.write_str("a string")
} }
fn visit_str<E>(self, v: &str) -> Result<String, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
Ok(v.to_owned()) Ok(v.to_owned())
} }
fn visit_string<E>(self, v: String) -> Result<String, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
Ok(v) Ok(v)
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<String, E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -246,7 +333,7 @@ impl<'de> Visitor<'de> for StringVisitor {
} }
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<String, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -268,7 +355,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
formatter.write_str("a string") formatter.write_str("a string")
} }
fn visit_str<E>(self, v: &str) -> Result<(), E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -277,7 +364,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
Ok(()) Ok(())
} }
fn visit_string<E>(self, v: String) -> Result<(), E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -285,7 +372,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
Ok(()) Ok(())
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -299,7 +386,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
} }
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -318,7 +405,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for String { impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -416,7 +503,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
formatter.write_str("byte array") formatter.write_str("byte array")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<CString, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -430,28 +517,28 @@ impl<'de> Visitor<'de> for CStringVisitor {
CString::new(values).map_err(Error::custom) CString::new(values).map_err(Error::custom)
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<CString, E> fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
CString::new(v).map_err(Error::custom) CString::new(v).map_err(Error::custom)
} }
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<CString, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
CString::new(v).map_err(Error::custom) CString::new(v).map_err(Error::custom)
} }
fn visit_str<E>(self, v: &str) -> Result<CString, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
CString::new(v).map_err(Error::custom) CString::new(v).map_err(Error::custom)
} }
fn visit_string<E>(self, v: String) -> Result<CString, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -461,7 +548,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de> Deserialize<'de> for CString { impl<'de> Deserialize<'de> for CString {
fn deserialize<D>(deserializer: D) -> Result<CString, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -470,7 +557,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
@@ -482,7 +573,7 @@ macro_rules! forwarded_impl {
} }
} }
#[cfg(all(feature = "std", feature = "unstable"))] #[cfg(all(feature = "std", de_boxed_c_str))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str); forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -502,7 +593,7 @@ where
} }
#[inline] #[inline]
fn visit_unit<E>(self) -> Result<Option<T>, E> fn visit_unit<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -510,7 +601,7 @@ where
} }
#[inline] #[inline]
fn visit_none<E>(self) -> Result<Option<T>, E> fn visit_none<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -518,19 +609,27 @@ where
} }
#[inline] #[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Option<T>, D::Error> fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
T::deserialize(deserializer).map(Some) T::deserialize(deserializer).map(Some)
} }
#[doc(hidden)]
fn __private_visit_untagged_option<D>(self, deserializer: D) -> Result<Self::Value, ()>
where
D: Deserializer<'de>,
{
Ok(T::deserialize(deserializer).ok())
}
} }
impl<'de, T> Deserialize<'de> for Option<T> impl<'de, T> Deserialize<'de> for Option<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Option<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -560,7 +659,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
} }
#[inline] #[inline]
fn visit_unit<E>(self) -> Result<PhantomData<T>, E> fn visit_unit<E>(self) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -569,7 +668,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
} }
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> { impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -654,7 +753,7 @@ macro_rules! seq_impl {
} }
#[inline] #[inline]
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error> fn visit_seq<A>(mut self, mut $access: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -766,7 +865,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
} }
#[inline] #[inline]
fn visit_seq<A>(self, _: A) -> Result<[T; 0], A::Error> fn visit_seq<A>(self, _: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -776,7 +875,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
// Does not require T: Deserialize<'de>. // Does not require T: Deserialize<'de>.
impl<'de, T> Deserialize<'de> for [T; 0] { impl<'de, T> Deserialize<'de> for [T; 0] {
fn deserialize<D>(deserializer: D) -> Result<[T; 0], D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -798,7 +897,7 @@ macro_rules! array_impls {
} }
#[inline] #[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -824,7 +923,7 @@ macro_rules! array_impls {
} }
#[inline] #[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -846,7 +945,7 @@ macro_rules! array_impls {
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -906,7 +1005,7 @@ macro_rules! tuple_impls {
$( $(
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -923,7 +1022,7 @@ macro_rules! tuple_impls {
#[inline] #[inline]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -957,7 +1056,7 @@ macro_rules! tuple_impls {
#[inline] #[inline]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1073,7 +1172,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 +1186,7 @@ macro_rules! parse_ip_impl {
} }
} }
} }
} };
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -1230,7 +1329,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 +1343,7 @@ macro_rules! parse_socket_impl {
} }
} }
} }
} };
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -1272,10 +1371,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 +1425,14 @@ impl<'de> Visitor<'de> for PathBufVisitor {
formatter.write_str("path string") formatter.write_str("path string")
} }
fn visit_str<E>(self, v: &str) -> Result<PathBuf, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
Ok(From::from(v)) Ok(From::from(v))
} }
fn visit_string<E>(self, v: String) -> Result<PathBuf, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1346,7 +1442,7 @@ impl<'de> Visitor<'de> for PathBufVisitor {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de> Deserialize<'de> for PathBuf { impl<'de> Deserialize<'de> for PathBuf {
fn deserialize<D>(deserializer: D) -> Result<PathBuf, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1379,7 +1475,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
} }
#[cfg(unix)] #[cfg(unix)]
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
@@ -1394,14 +1490,15 @@ impl<'de> Visitor<'de> for OsStringVisitor {
} }
#[cfg(windows)] #[cfg(windows)]
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
use std::os::windows::ffi::OsStringExt; use std::os::windows::ffi::OsStringExt;
match try!(data.variant()) { match try!(data.variant()) {
(OsStringKind::Windows, v) => v.newtype_variant::<Vec<u16>>() (OsStringKind::Windows, v) => v
.newtype_variant::<Vec<u16>>()
.map(|vec| OsString::from_wide(&vec)), .map(|vec| OsString::from_wide(&vec)),
(OsStringKind::Unix, _) => Err(Error::custom( (OsStringKind::Unix, _) => Err(Error::custom(
"cannot deserialize Unix OS string on Windows", "cannot deserialize Unix OS string on Windows",
@@ -1412,7 +1509,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
#[cfg(all(feature = "std", any(unix, windows)))] #[cfg(all(feature = "std", any(unix, windows)))]
impl<'de> Deserialize<'de> for OsString { impl<'de> Deserialize<'de> for OsString {
fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1431,11 +1528,29 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
forwarded_impl!((), Box<str>, String::into_boxed_str); forwarded_impl!((), Box<str>, String::into_boxed_str);
#[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(not(de_rc_dst), feature = "rc", any(feature = "std", feature = "alloc")))]
forwarded_impl!((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(de_rc_dst), 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 +1559,7 @@ where
T::Owned: Deserialize<'de>, T::Owned: Deserialize<'de>,
{ {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<Cow<'a, T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1454,9 +1569,51 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] /// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
Ok(RcWeak::new())
}
}
/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
Ok(ArcWeak::new())
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
($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 +1625,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(de_rc_dst, 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(de_rc_dst, 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 +1658,7 @@ impl<'de, T> Deserialize<'de> for Cell<T>
where where
T: Deserialize<'de> + Copy, T: Deserialize<'de> + Copy,
{ {
fn deserialize<D>(deserializer: D) -> Result<Cell<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1525,7 +1700,7 @@ impl<'de> Deserialize<'de> for Duration {
}; };
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1538,7 +1713,7 @@ impl<'de> Deserialize<'de> for Duration {
formatter.write_str("`secs` or `nanos`") formatter.write_str("`secs` or `nanos`")
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1549,7 +1724,7 @@ impl<'de> Deserialize<'de> for Duration {
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1577,7 +1752,7 @@ impl<'de> Deserialize<'de> for Duration {
formatter.write_str("struct Duration") formatter.write_str("struct Duration")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1596,7 +1771,7 @@ impl<'de> Deserialize<'de> for Duration {
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
@@ -1650,7 +1825,7 @@ impl<'de> Deserialize<'de> for SystemTime {
}; };
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1663,7 +1838,7 @@ impl<'de> Deserialize<'de> for SystemTime {
formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`") formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`")
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1674,7 +1849,7 @@ impl<'de> Deserialize<'de> for SystemTime {
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1702,7 +1877,7 @@ impl<'de> Deserialize<'de> for SystemTime {
formatter.write_str("struct SystemTime") formatter.write_str("struct SystemTime")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1721,7 +1896,7 @@ impl<'de> Deserialize<'de> for SystemTime {
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
@@ -1794,7 +1969,7 @@ where
}; };
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1807,7 +1982,7 @@ where
formatter.write_str("`start` or `end`") formatter.write_str("`start` or `end`")
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1818,7 +1993,7 @@ where
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1851,7 +2026,7 @@ where
formatter.write_str("struct Range") formatter.write_str("struct Range")
} }
fn visit_seq<A>(self, mut seq: A) -> Result<ops::Range<Idx>, A::Error> fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1870,7 +2045,7 @@ where
Ok(start..end) Ok(start..end)
} }
fn visit_map<A>(self, mut map: A) -> Result<ops::Range<Idx>, A::Error> fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
@@ -1917,21 +2092,34 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")] macro_rules! nonzero_integers {
impl<'de, T> Deserialize<'de> for NonZero<T> ( $( $T: ident, )+ ) => {
where $(
T: Deserialize<'de> + Zeroable, #[cfg(num_nonzero)]
{ impl<'de> Deserialize<'de> for num::$T {
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>,
{ {
let value = try!(Deserialize::deserialize(deserializer)); let value = try!(Deserialize::deserialize(deserializer));
match NonZero::new(value) { match <num::$T>::new(value) {
Some(nonzero) => Ok(nonzero), Some(nonzero) => Ok(nonzero),
None => Err(Error::custom("expected a non-zero value")), None => Err(Error::custom("expected a non-zero value")),
} }
} }
}
)+
};
}
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,
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1941,7 +2129,7 @@ where
T: Deserialize<'de>, T: Deserialize<'de>,
E: Deserialize<'de>, E: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1956,7 +2144,7 @@ where
impl<'de> Deserialize<'de> for Field { impl<'de> Deserialize<'de> for Field {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -1969,7 +2157,7 @@ where
formatter.write_str("`Ok` or `Err`") formatter.write_str("`Ok` or `Err`")
} }
fn visit_u32<E>(self, value: u32) -> Result<Field, E> fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1983,7 +2171,7 @@ where
} }
} }
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -1994,7 +2182,7 @@ where
} }
} }
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where where
E: Error, E: Error,
{ {
@@ -2028,7 +2216,7 @@ where
formatter.write_str("enum Result") formatter.write_str("enum Result")
} }
fn visit_enum<A>(self, data: A) -> Result<Result<T, E>, A::Error> fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
@@ -2052,7 +2240,7 @@ impl<'de, T> Deserialize<'de> for Wrapping<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
+144 -42
View File
@@ -52,8 +52,8 @@
//! //!
//! - **Primitive types**: //! - **Primitive types**:
//! - bool //! - bool
//! - i8, i16, i32, i64, isize //! - i8, i16, i32, i64, i128, isize
//! - u8, u16, u32, u64, usize //! - u8, u16, u32, u64, u128, usize
//! - f32, f64 //! - f32, f64
//! - char //! - char
//! - **Compound types**: //! - **Compound types**:
@@ -84,7 +84,6 @@
//! - LinkedList\<T\> //! - LinkedList\<T\>
//! - VecDeque\<T\> //! - VecDeque\<T\>
//! - Vec\<T\> //! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **Zero-copy types**: //! - **Zero-copy types**:
//! - &str //! - &str
//! - &[u8] //! - &[u8]
@@ -98,7 +97,7 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - NonZero\<T\> (unstable) //! - num::NonZero*
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -171,7 +170,8 @@ macro_rules! declare_error_trait {
/// ///
/// impl<'de> Deserialize<'de> for IpAddr { /// impl<'de> Deserialize<'de> for IpAddr {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> /// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// let s = try!(String::deserialize(deserializer)); /// let s = try!(String::deserialize(deserializer));
/// s.parse().map_err(de::Error::custom) /// s.parse().map_err(de::Error::custom)
@@ -195,6 +195,7 @@ macro_rules! declare_error_trait {
/// For example if we try to deserialize a String out of a JSON file /// For example if we try to deserialize a String out of a JSON file
/// containing an integer, the unexpected type is the integer and the /// containing an integer, the unexpected type is the integer and the
/// expected type is the string. /// expected type is the string.
#[cold]
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self { fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
} }
@@ -212,6 +213,7 @@ macro_rules! declare_error_trait {
/// For example if we try to deserialize a String out of some binary data /// For example if we try to deserialize a String out of some binary data
/// that is not valid UTF-8, the unexpected value is the bytes and the /// that is not valid UTF-8, the unexpected value is the bytes and the
/// expected value is a string. /// expected value is a string.
#[cold]
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self { fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp)) Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
} }
@@ -225,12 +227,14 @@ macro_rules! declare_error_trait {
/// The `exp` argument provides information about what data was being /// The `exp` argument provides information about what data was being
/// expected. For example `exp` might say that a tuple of size 6 was /// expected. For example `exp` might say that a tuple of size 6 was
/// expected. /// expected.
#[cold]
fn invalid_length(len: usize, exp: &Expected) -> Self { fn invalid_length(len: usize, exp: &Expected) -> Self {
Error::custom(format_args!("invalid length {}, expected {}", len, exp)) Error::custom(format_args!("invalid length {}, expected {}", len, exp))
} }
/// Raised when a `Deserialize` enum type received a variant with an /// Raised when a `Deserialize` enum type received a variant with an
/// unrecognized name. /// unrecognized name.
#[cold]
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() { if expected.is_empty() {
Error::custom(format_args!("unknown variant `{}`, there are no variants", Error::custom(format_args!("unknown variant `{}`, there are no variants",
@@ -244,6 +248,7 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type received a field with an /// Raised when a `Deserialize` struct type received a field with an
/// unrecognized name. /// unrecognized name.
#[cold]
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() { if expected.is_empty() {
Error::custom(format_args!("unknown field `{}`, there are no fields", Error::custom(format_args!("unknown field `{}`, there are no fields",
@@ -258,12 +263,14 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type expected to receive a required /// Raised when a `Deserialize` struct type expected to receive a required
/// field with a particular name but that field was not present in the /// field with a particular name but that field was not present in the
/// input. /// input.
#[cold]
fn missing_field(field: &'static str) -> Self { fn missing_field(field: &'static str) -> Self {
Error::custom(format_args!("missing field `{}`", field)) Error::custom(format_args!("missing field `{}`", field))
} }
/// Raised when a `Deserialize` struct type received more than one of the /// Raised when a `Deserialize` struct type received more than one of the
/// same field. /// same field.
#[cold]
fn duplicate_field(field: &'static str) -> Self { fn duplicate_field(field: &'static str) -> Self {
Error::custom(format_args!("duplicate field `{}`", field)) Error::custom(format_args!("duplicate field `{}`", field))
} }
@@ -298,7 +305,8 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// # } /// # }
/// # /// #
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> /// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
/// where E: de::Error /// where
/// E: de::Error,
/// { /// {
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self)) /// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
/// } /// }
@@ -422,7 +430,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # } /// # }
/// # /// #
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> /// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
/// where E: de::Error /// where
/// E: de::Error,
/// { /// {
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self)) /// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
/// } /// }
@@ -435,7 +444,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # use serde::de::{self, Unexpected}; /// # use serde::de::{self, Unexpected};
/// # /// #
/// # fn example<E>() -> Result<(), E> /// # fn example<E>() -> Result<(), E>
/// # where E: de::Error /// # where
/// # E: de::Error,
/// # { /// # {
/// # let v = true; /// # let v = true;
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); /// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
@@ -549,11 +559,13 @@ pub trait Deserialize<'de>: Sized {
/// # /// #
/// # trait Ignore { /// # trait Ignore {
/// fn from_str<'a, T>(s: &'a str) -> Result<T> /// fn from_str<'a, T>(s: &'a str) -> Result<T>
/// where T: Deserialize<'a>; /// where
/// T: Deserialize<'a>;
/// ///
/// fn from_reader<R, T>(rdr: R) -> Result<T> /// fn from_reader<R, T>(rdr: R) -> Result<T>
/// where R: Read, /// where
/// T: DeserializeOwned; /// R: Read,
/// T: DeserializeOwned;
/// # } /// # }
/// ``` /// ```
pub trait DeserializeOwned: for<'de> Deserialize<'de> {} pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
@@ -629,7 +641,8 @@ where
/// struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>); /// struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);
/// ///
/// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T> /// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// // The return type of the `deserialize` method. This implementation /// // The return type of the `deserialize` method. This implementation
/// // appends onto an existing vector but does not create any new data /// // appends onto an existing vector but does not create any new data
@@ -637,14 +650,16 @@ where
/// type Value = (); /// type Value = ();
/// ///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> /// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// // Visitor implementation that will walk an inner array of the JSON /// // Visitor implementation that will walk an inner array of the JSON
/// // input. /// // input.
/// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>); /// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
/// ///
/// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T> /// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// type Value = (); /// type Value = ();
/// ///
@@ -653,7 +668,8 @@ where
/// } /// }
/// ///
/// fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error> /// fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
/// where A: SeqAccess<'de> /// where
/// A: SeqAccess<'de>,
/// { /// {
/// // Visit each element in the inner array and push it onto /// // Visit each element in the inner array and push it onto
/// // the existing vector. /// // the existing vector.
@@ -672,7 +688,8 @@ where
/// struct FlattenedVecVisitor<T>(PhantomData<T>); /// struct FlattenedVecVisitor<T>(PhantomData<T>);
/// ///
/// impl<'de, T> Visitor<'de> for FlattenedVecVisitor<T> /// impl<'de, T> Visitor<'de> for FlattenedVecVisitor<T>
/// where T: Deserialize<'de> /// where
/// T: Deserialize<'de>,
/// { /// {
/// // This Visitor constructs a single Vec<T> to hold the flattened /// // This Visitor constructs a single Vec<T> to hold the flattened
/// // contents of the inner arrays. /// // contents of the inner arrays.
@@ -683,7 +700,8 @@ where
/// } /// }
/// ///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error> /// fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
/// where A: SeqAccess<'de> /// where
/// A: SeqAccess<'de>,
/// { /// {
/// // Create a single Vec to hold the flattened contents. /// // Create a single Vec to hold the flattened contents.
/// let mut vec = Vec::new(); /// let mut vec = Vec::new();
@@ -699,7 +717,8 @@ where
/// } /// }
/// ///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> /// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de> /// # where
/// # D: Deserializer<'de>,
/// # { /// # {
/// let visitor = FlattenedVecVisitor(PhantomData); /// let visitor = FlattenedVecVisitor(PhantomData);
/// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?; /// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?;
@@ -738,7 +757,7 @@ where
/// Serde. /// Serde.
/// ///
/// The role of this trait is to define the deserialization half of the Serde /// The role of this trait is to define the deserialization half of the Serde
/// data model, which is a way to categorize every Rust data type into one of 27 /// data model, which is a way to categorize every Rust data type into one of 29
/// possible types. Each method of the `Serializer` trait corresponds to one of /// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model. /// the types of the data model.
/// ///
@@ -748,10 +767,10 @@ where
/// ///
/// The types that make up the Serde data model are: /// The types that make up the Serde data model are:
/// ///
/// - **12 primitive types** /// - **14 primitive types**
/// - bool /// - bool
/// - i8, i16, i32, i64 /// - i8, i16, i32, i64, i128
/// - u8, u16, u32, u64 /// - u8, u16, u32, u64, u128
/// - f32, f64 /// - f32, f64
/// - char /// - char
/// - **string** /// - **string**
@@ -865,6 +884,20 @@ pub trait Deserializer<'de>: Sized {
where where
V: Visitor<'de>; V: Visitor<'de>;
serde_if_integer128! {
/// Hint that the `Deserialize` type is expecting an `i128` value.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>
{
let _ = visitor;
Err(Error::custom("i128 is not supported"))
}
}
/// Hint that the `Deserialize` type is expecting a `u8` value. /// Hint that the `Deserialize` type is expecting a `u8` value.
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
@@ -885,6 +918,20 @@ pub trait Deserializer<'de>: Sized {
where where
V: Visitor<'de>; V: Visitor<'de>;
serde_if_integer128! {
/// Hint that the `Deserialize` type is expecting an `u128` value.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>
{
let _ = visitor;
Err(Error::custom("u128 is not supported"))
}
}
/// Hint that the `Deserialize` type is expecting a `f32` value. /// Hint that the `Deserialize` type is expecting a `f32` value.
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
@@ -1084,7 +1131,8 @@ pub trait Deserializer<'de>: Sized {
/// ///
/// impl<'de> Deserialize<'de> for Timestamp { /// impl<'de> Deserialize<'de> for Timestamp {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> /// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de> /// where
/// D: Deserializer<'de>,
/// { /// {
/// if deserializer.is_human_readable() { /// if deserializer.is_human_readable() {
/// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z". /// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z".
@@ -1135,7 +1183,8 @@ pub trait Deserializer<'de>: Sized {
/// } /// }
/// ///
/// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> /// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
/// where E: de::Error /// where
/// E: de::Error,
/// { /// {
/// if s.len() >= self.min { /// if s.len() >= self.min {
/// Ok(s.to_owned()) /// Ok(s.to_owned())
@@ -1229,6 +1278,20 @@ pub trait Visitor<'de>: Sized {
Err(Error::invalid_type(Unexpected::Signed(v), &self)) Err(Error::invalid_type(Unexpected::Signed(v), &self))
} }
serde_if_integer128! {
/// The input contains a `i128`.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default implementation fails with a type error.
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Other("i128"), &self))
}
}
/// The input contains a `u8`. /// The input contains a `u8`.
/// ///
/// The default implementation forwards to [`visit_u64`]. /// The default implementation forwards to [`visit_u64`].
@@ -1275,6 +1338,20 @@ pub trait Visitor<'de>: Sized {
Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
} }
serde_if_integer128! {
/// The input contains a `u128`.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default implementation fails with a type error.
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Other("u128"), &self))
}
}
/// The input contains an `f32`. /// The input contains an `f32`.
/// ///
/// The default implementation forwards to [`visit_f64`]. /// The default implementation forwards to [`visit_f64`].
@@ -1506,6 +1583,15 @@ pub trait Visitor<'de>: Sized {
let _ = data; let _ = data;
Err(Error::invalid_type(Unexpected::Enum, &self)) Err(Error::invalid_type(Unexpected::Enum, &self))
} }
// Used when deserializing a flattened Option field. Not public API.
#[doc(hidden)]
fn __private_visit_untagged_option<D>(self, _: D) -> Result<Self::Value, ()>
where
D: Deserializer<'de>,
{
Err(())
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1815,15 +1901,18 @@ pub trait VariantAccess<'de>: Sized {
/// } /// }
/// # /// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error> /// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de> /// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error> /// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error> /// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # } /// # }
/// ``` /// ```
@@ -1850,7 +1939,8 @@ pub trait VariantAccess<'de>: Sized {
/// # } /// # }
/// # /// #
/// fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error> /// fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
/// where T: DeserializeSeed<'de> /// where
/// T: DeserializeSeed<'de>,
/// { /// {
/// // What the data actually contained; suppose it is a unit variant. /// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant; /// let unexp = Unexpected::UnitVariant;
@@ -1858,11 +1948,13 @@ pub trait VariantAccess<'de>: Sized {
/// } /// }
/// # /// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error> /// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error> /// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # } /// # }
/// ``` /// ```
@@ -1903,13 +1995,17 @@ pub trait VariantAccess<'de>: Sized {
/// # } /// # }
/// # /// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error> /// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de> /// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// fn tuple_variant<V>(self, /// fn tuple_variant<V>(
/// _len: usize, /// self,
/// _visitor: V) -> Result<V::Value, Self::Error> /// _len: usize,
/// where V: Visitor<'de> /// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// { /// {
/// // What the data actually contained; suppose it is a unit variant. /// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant; /// let unexp = Unexpected::UnitVariant;
@@ -1917,7 +2013,8 @@ pub trait VariantAccess<'de>: Sized {
/// } /// }
/// # /// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error> /// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # } /// # }
/// ``` /// ```
@@ -1945,17 +2042,22 @@ pub trait VariantAccess<'de>: Sized {
/// # } /// # }
/// # /// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error> /// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de> /// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error> /// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() } /// # { unimplemented!() }
/// # /// #
/// fn struct_variant<V>(self, /// fn struct_variant<V>(
/// _fields: &'static [&'static str], /// self,
/// _visitor: V) -> Result<V::Value, Self::Error> /// _fields: &'static [&'static str],
/// where V: Visitor<'de> /// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// { /// {
/// // What the data actually contained; suppose it is a unit variant. /// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant; /// let unexp = Unexpected::UnitVariant;
+47 -50
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,
@@ -133,9 +136,9 @@ where
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct
struct enum identifier ignored_any map struct enum identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -186,9 +189,9 @@ macro_rules! primitive_deserializer {
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str
byte_buf option unit unit_struct newtype_struct seq tuple string bytes byte_buf option unit unit_struct newtype_struct seq
tuple_struct map struct enum identifier ignored_any tuple tuple_struct map struct enum identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -243,9 +246,9 @@ where
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -336,9 +339,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -405,9 +408,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -480,9 +483,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -559,9 +562,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any tuple_struct map struct identifier ignored_any
} }
} }
@@ -615,9 +618,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct identifier ignored_any enum tuple_struct map struct identifier ignored_any enum
} }
} }
@@ -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 {
@@ -688,9 +688,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -803,9 +803,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
@@ -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 {
@@ -920,9 +917,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct tuple_struct map struct bytes byte_buf option unit unit_struct newtype_struct tuple_struct map
enum identifier ignored_any struct enum identifier ignored_any
} }
} }
@@ -1062,9 +1059,9 @@ where
type Error = E; type Error = E;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct tuple_struct map struct bytes byte_buf option unit unit_struct newtype_struct tuple_struct map
enum identifier ignored_any struct enum identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -1210,9 +1207,9 @@ where
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
+3
View File
@@ -16,6 +16,9 @@ pub use lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy; pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::Vec;
mod string { mod string {
use lib::*; use lib::*;
+86
View File
@@ -0,0 +1,86 @@
/// Conditional compilation depending on whether Serde is built with support for
/// 128-bit integers.
///
/// Data formats that wish to support Rust compiler versions older than 1.26 may
/// place the i128 / u128 methods of their Serializer and Deserializer behind
/// this macro.
///
/// Data formats that require a minimum Rust compiler version of at least 1.26
/// do not need to bother with this macro and may assume support for 128-bit
/// integers.
///
/// ```rust
/// #[macro_use]
/// extern crate serde;
///
/// use serde::Serializer;
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
///
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
///
/// /* ... */
///
/// serde_if_integer128! {
/// fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
///
/// fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
/// }
/// #
/// # __serialize_unimplemented! {
/// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant seq
/// # tuple tuple_struct tuple_variant map struct struct_variant
/// # }
/// }
/// #
/// # fn main() {}
/// ```
///
/// When Serde is built with support for 128-bit integers, this macro expands
/// transparently into just the input tokens.
///
/// ```rust
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {
/// $($tt)*
/// };
/// }
/// ```
///
/// When built without support for 128-bit integers, this macro expands to
/// nothing.
///
/// ```rust
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {};
/// }
/// ```
#[cfg(integer128)]
#[macro_export]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {
$($tt)*
};
}
#[cfg(not(integer128))]
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {};
}
+42 -42
View File
@@ -79,21 +79,24 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 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.61")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and // Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue: // discussion of these features please refer to this issue:
// //
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))] #![cfg_attr(feature = "unstable", feature(specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Whitelisted clippy lints
#![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
@@ -127,24 +130,21 @@
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(all(feature = "unstable", feature = "std"))]
extern crate core;
/// A facade around all the types we need from the `std`, `core`, and `alloc` /// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every /// crates. This avoids elaborate import wrangling having to happen in every
/// module. /// module.
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, num, 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 +155,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 +206,9 @@ 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")]
#[cfg(feature = "unstable")] pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
pub use core::nonzero::{NonZero, Zeroable};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -219,13 +216,16 @@ mod lib {
#[macro_use] #[macro_use]
mod macros; mod macros;
pub mod ser; #[macro_use]
mod integer128;
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)]
+25 -11
View File
@@ -31,21 +31,23 @@
/// # type Error = value::Error; /// # type Error = value::Error;
/// # /// #
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error> /// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de> /// # where
/// # V: Visitor<'de>,
/// # { /// # {
/// # unimplemented!() /// # unimplemented!()
/// # } /// # }
/// # /// #
/// #[inline] /// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de> /// where
/// V: Visitor<'de>,
/// { /// {
/// self.deserialize_any(visitor) /// self.deserialize_any(visitor)
/// } /// }
/// # /// #
/// # forward_to_deserialize_any! { /// # forward_to_deserialize_any! {
/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes /// # i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// # byte_buf option unit unit_struct newtype_struct seq tuple /// # bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any /// # tuple_struct map struct enum identifier ignored_any
/// # } /// # }
/// # } /// # }
@@ -69,7 +71,8 @@
/// # type Error = value::Error; /// # type Error = value::Error;
/// # /// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de> /// where
/// V: Visitor<'de>,
/// { /// {
/// /* ... */ /// /* ... */
/// # let _ = visitor; /// # let _ = visitor;
@@ -77,8 +80,8 @@
/// } /// }
/// ///
/// forward_to_deserialize_any! { /// forward_to_deserialize_any! {
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes /// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// byte_buf option unit unit_struct newtype_struct seq tuple /// bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct map struct enum identifier ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// } /// }
@@ -105,16 +108,17 @@
/// # type Error = value::Error; /// # type Error = value::Error;
/// # /// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error> /// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q> /// # where
/// # W: Visitor<'q>,
/// # { /// # {
/// # unimplemented!() /// # unimplemented!()
/// # } /// # }
/// # /// #
/// forward_to_deserialize_any! { /// forward_to_deserialize_any! {
/// <W: Visitor<'q>> /// <W: Visitor<'q>>
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes /// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct /// bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// map struct enum identifier ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// # } /// # }
/// # /// #
@@ -170,6 +174,11 @@ macro_rules! forward_to_deserialize_any_helper {
(i64<$l:tt, $v:ident>) => { (i64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()} forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
}; };
(i128<$l:tt, $v:ident>) => {
serde_if_integer128! {
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
}
};
(u8<$l:tt, $v:ident>) => { (u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()} forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
}; };
@@ -182,6 +191,11 @@ macro_rules! forward_to_deserialize_any_helper {
(u64<$l:tt, $v:ident>) => { (u64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()} forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
}; };
(u128<$l:tt, $v:ident>) => {
serde_if_integer128! {
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
}
};
(f32<$l:tt, $v:ident>) => { (f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()} forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
}; };
+928 -97
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;
+321 -14
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>,
@@ -943,7 +947,8 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let key = self.key let key = self
.key
.take() .take()
.expect("serialize_value called before serialize_key"); .expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = try!(value.serialize(ContentSerializer::<E>::new()));
@@ -967,7 +972,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 +999,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 +1033,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(())
}
}
+88 -13
View File
@@ -44,6 +44,11 @@ primitive_impl!(f32, serialize_f32);
primitive_impl!(f64, serialize_f64); primitive_impl!(f64, serialize_f64);
primitive_impl!(char, serialize_char); primitive_impl!(char, serialize_char);
serde_if_integer128! {
primitive_impl!(i128, serialize_i128);
primitive_impl!(u128, serialize_u128);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
impl Serialize for str { impl Serialize for str {
@@ -320,8 +325,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,29 +349,96 @@ 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);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")] /// This impl requires the [`"rc"`] Cargo feature of Serde.
impl<T> Serialize for NonZero<T> ///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for RcWeak<T>
where where
T: Serialize + Zeroable + Clone, T: Serialize,
{ {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
self.clone().get().serialize(serializer) self.upgrade().serialize(serializer)
} }
} }
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for ArcWeak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.upgrade().serialize(serializer)
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => {
$(
#[cfg(num_nonzero)]
impl Serialize for num::$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,
@@ -464,7 +540,8 @@ impl Serialize for SystemTime {
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let duration_since_epoch = self.duration_since(UNIX_EPOCH) let duration_since_epoch = self
.duration_since(UNIX_EPOCH)
.expect("SystemTime must be later than UNIX_EPOCH"); .expect("SystemTime must be later than UNIX_EPOCH");
let mut state = try!(serializer.serialize_struct("SystemTime", 2)); let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())); try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
@@ -494,11 +571,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.
+179 -66
View File
@@ -48,8 +48,8 @@
//! //!
//! - **Primitive types**: //! - **Primitive types**:
//! - bool //! - bool
//! - i8, i16, i32, i64, isize //! - i8, i16, i32, i64, i128, isize
//! - u8, u16, u32, u64, usize //! - u8, u16, u32, u64, u128, usize
//! - f32, f64 //! - f32, f64
//! - char //! - char
//! - str //! - str
@@ -81,7 +81,6 @@
//! - LinkedList\<T\> //! - LinkedList\<T\>
//! - VecDeque\<T\> //! - VecDeque\<T\>
//! - Vec\<T\> //! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **FFI types**: //! - **FFI types**:
//! - CStr //! - CStr
//! - CString //! - CString
@@ -93,7 +92,7 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - NonZero\<T\> (unstable) //! - num::NonZero*
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -151,7 +150,8 @@ macro_rules! declare_error_trait {
/// ///
/// impl Serialize for Path { /// impl Serialize for Path {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match self.to_str() { /// match self.to_str() {
/// Some(s) => serializer.serialize_str(s), /// Some(s) => serializer.serialize_str(s),
@@ -222,7 +222,8 @@ pub trait Serialize {
/// // This is what #[derive(Serialize)] would generate. /// // This is what #[derive(Serialize)] would generate.
/// impl Serialize for Person { /// impl Serialize for Person {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut s = serializer.serialize_struct("Person", 3)?; /// let mut s = serializer.serialize_struct("Person", 3)?;
/// s.serialize_field("name", &self.name)?; /// s.serialize_field("name", &self.name)?;
@@ -244,7 +245,7 @@ pub trait Serialize {
/// A **data format** that can serialize any data structure supported by Serde. /// A **data format** that can serialize any data structure supported by Serde.
/// ///
/// The role of this trait is to define the serialization half of the Serde data /// The role of this trait is to define the serialization half of the Serde data
/// model, which is a way to categorize every Rust data structure into one of 27 /// model, which is a way to categorize every Rust data structure into one of 29
/// possible types. Each method of the `Serializer` trait corresponds to one of /// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model. /// the types of the data model.
/// ///
@@ -253,10 +254,10 @@ pub trait Serialize {
/// ///
/// The types that make up the Serde data model are: /// The types that make up the Serde data model are:
/// ///
/// - **12 primitive types** /// - **14 primitive types**
/// - bool /// - bool
/// - i8, i16, i32, i64 /// - i8, i16, i32, i64, i128
/// - u8, u16, u32, u64 /// - u8, u16, u32, u64, u128
/// - f32, f64 /// - f32, f64
/// - char /// - char
/// - **string** /// - **string**
@@ -376,7 +377,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for bool { /// impl Serialize for bool {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_bool(*self) /// serializer.serialize_bool(*self)
/// } /// }
@@ -402,7 +404,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i8 { /// impl Serialize for i8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i8(*self) /// serializer.serialize_i8(*self)
/// } /// }
@@ -428,7 +431,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i16 { /// impl Serialize for i16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i16(*self) /// serializer.serialize_i16(*self)
/// } /// }
@@ -454,7 +458,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i32 { /// impl Serialize for i32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i32(*self) /// serializer.serialize_i32(*self)
/// } /// }
@@ -476,7 +481,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for i64 { /// impl Serialize for i64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_i64(*self) /// serializer.serialize_i64(*self)
/// } /// }
@@ -486,6 +492,37 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>; fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize an `i128` value.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer;
/// #
/// # __private_serialize!();
/// #
/// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i128(*self)
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("i128 is not supported"))
}
}
/// Serialize a `u8` value. /// Serialize a `u8` value.
/// ///
/// If the format does not differentiate between `u8` and `u64`, a /// If the format does not differentiate between `u8` and `u64`, a
@@ -502,7 +539,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u8 { /// impl Serialize for u8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u8(*self) /// serializer.serialize_u8(*self)
/// } /// }
@@ -528,7 +566,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u16 { /// impl Serialize for u16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u16(*self) /// serializer.serialize_u16(*self)
/// } /// }
@@ -554,7 +593,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u32 { /// impl Serialize for u32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u32(*self) /// serializer.serialize_u32(*self)
/// } /// }
@@ -576,7 +616,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for u64 { /// impl Serialize for u64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_u64(*self) /// serializer.serialize_u64(*self)
/// } /// }
@@ -586,6 +627,37 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>; fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize a `u128` value.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer;
/// #
/// # __private_serialize!();
/// #
/// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u128(*self)
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("u128 is not supported"))
}
}
/// Serialize an `f32` value. /// Serialize an `f32` value.
/// ///
/// If the format does not differentiate between `f32` and `f64`, a /// If the format does not differentiate between `f32` and `f64`, a
@@ -602,7 +674,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for f32 { /// impl Serialize for f32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_f32(*self) /// serializer.serialize_f32(*self)
/// } /// }
@@ -624,7 +697,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for f64 { /// impl Serialize for f64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_f64(*self) /// serializer.serialize_f64(*self)
/// } /// }
@@ -649,7 +723,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for char { /// impl Serialize for char {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_char(*self) /// serializer.serialize_char(*self)
/// } /// }
@@ -671,7 +746,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for str { /// impl Serialize for str {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_str(self) /// serializer.serialize_str(self)
/// } /// }
@@ -736,10 +812,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None}; /// # use Option::{Some, None};
/// # /// #
/// impl<T> Serialize for Option<T> /// impl<T> Serialize for Option<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// Some(ref value) => serializer.serialize_some(value), /// Some(ref value) => serializer.serialize_some(value),
@@ -769,10 +847,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None}; /// # use Option::{Some, None};
/// # /// #
/// impl<T> Serialize for Option<T> /// impl<T> Serialize for Option<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// Some(ref value) => serializer.serialize_some(value), /// Some(ref value) => serializer.serialize_some(value),
@@ -801,7 +881,8 @@ pub trait Serializer: Sized {
/// # /// #
/// impl Serialize for () { /// impl Serialize for () {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_unit() /// serializer.serialize_unit()
/// } /// }
@@ -822,7 +903,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Nothing { /// impl Serialize for Nothing {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_unit_struct("Nothing") /// serializer.serialize_unit_struct("Nothing")
/// } /// }
@@ -846,7 +928,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::A => serializer.serialize_unit_variant("E", 0, "A"), /// E::A => serializer.serialize_unit_variant("E", 0, "A"),
@@ -875,7 +958,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Millimeters { /// impl Serialize for Millimeters {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.serialize_newtype_struct("Millimeters", &self.0) /// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// } /// }
@@ -905,7 +989,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s), /// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s),
@@ -955,10 +1040,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq}; /// use serde::ser::{Serialize, Serializer, SerializeSeq};
/// ///
/// impl<T> Serialize for Vec<T> /// impl<T> Serialize for Vec<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_seq(Some(self.len()))?; /// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self { /// for element in self {
@@ -987,12 +1074,14 @@ pub trait Serializer: Sized {
/// # struct Tuple3<A, B, C>(A, B, C); /// # struct Tuple3<A, B, C>(A, B, C);
/// # /// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C> /// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize, /// where
/// B: Serialize, /// A: Serialize,
/// C: Serialize /// B: Serialize,
/// C: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut tup = serializer.serialize_tuple(3)?; /// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?; /// tup.serialize_element(&self.0)?;
@@ -1011,7 +1100,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Vram { /// impl Serialize for Vram {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?; /// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?;
/// for element in &self.0[..] { /// for element in &self.0[..] {
@@ -1037,7 +1127,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?; /// ts.serialize_field(&self.0)?;
@@ -1071,7 +1162,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::T(ref a, ref b) => { /// E::T(ref a, ref b) => {
@@ -1129,11 +1221,13 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeMap}; /// use serde::ser::{Serialize, Serializer, SerializeMap};
/// ///
/// impl<K, V> Serialize for HashMap<K, V> /// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize, /// where
/// V: Serialize /// K: Serialize,
/// V: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut map = serializer.serialize_map(Some(self.len()))?; /// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self { /// for (k, v) in self {
@@ -1163,7 +1257,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?; /// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
/// rgb.serialize_field("r", &self.r)?; /// rgb.serialize_field("r", &self.r)?;
@@ -1196,7 +1291,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::S { ref r, ref g, ref b } => { /// E::S { ref r, ref g, ref b } => {
@@ -1233,7 +1329,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for SecretlyOneHigher { /// impl Serialize for SecretlyOneHigher {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_seq(self.data.iter().map(|x| x + 1)) /// serializer.collect_seq(self.data.iter().map(|x| x + 1))
/// } /// }
@@ -1271,7 +1368,8 @@ pub trait Serializer: Sized {
/// // Serializes as a map in which the values are all unit. /// // Serializes as a map in which the values are all unit.
/// impl Serialize for MapToUnit { /// impl Serialize for MapToUnit {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_map(self.keys.iter().map(|k| (k, ()))) /// serializer.collect_map(self.keys.iter().map(|k| (k, ())))
/// } /// }
@@ -1311,7 +1409,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for DateTime { /// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_str(&format_args!("{:?}{:?}", /// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(), /// self.naive_local(),
@@ -1351,7 +1450,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for DateTime { /// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// serializer.collect_str(&format_args!("{:?}{:?}", /// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(), /// self.naive_local(),
@@ -1392,7 +1492,8 @@ pub trait Serializer: Sized {
/// ///
/// impl Serialize for Timestamp { /// impl Serialize for Timestamp {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// if serializer.is_human_readable() { /// if serializer.is_human_readable() {
/// // Serialize to a human-readable string "2015-05-15T17:01:00Z". /// // Serialize to a human-readable string "2015-05-15T17:01:00Z".
@@ -1441,10 +1542,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq}; /// use serde::ser::{Serialize, Serializer, SerializeSeq};
/// ///
/// impl<T> Serialize for Vec<T> /// impl<T> Serialize for Vec<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_seq(Some(self.len()))?; /// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self { /// for element in self {
@@ -1484,12 +1587,14 @@ pub trait SerializeSeq {
/// # struct Tuple3<A, B, C>(A, B, C); /// # struct Tuple3<A, B, C>(A, B, C);
/// # /// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C> /// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize, /// where
/// B: Serialize, /// A: Serialize,
/// C: Serialize /// B: Serialize,
/// C: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut tup = serializer.serialize_tuple(3)?; /// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?; /// tup.serialize_element(&self.0)?;
@@ -1528,10 +1633,12 @@ pub trait SerializeSeq {
/// # } /// # }
/// # /// #
/// # impl<T> Serialize for Array<T> /// # impl<T> Serialize for Array<T>
/// where T: Serialize /// where
/// T: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut seq = serializer.serialize_tuple(16)?; /// let mut seq = serializer.serialize_tuple(16)?;
/// for element in self { /// for element in self {
@@ -1566,7 +1673,8 @@ pub trait SerializeTuple {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?; /// ts.serialize_field(&self.0)?;
@@ -1604,7 +1712,8 @@ pub trait SerializeTupleStruct {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::T(ref a, ref b) => { /// E::T(ref a, ref b) => {
@@ -1665,11 +1774,13 @@ pub trait SerializeTupleVariant {
/// use serde::ser::{Serialize, Serializer, SerializeMap}; /// use serde::ser::{Serialize, Serializer, SerializeMap};
/// ///
/// impl<K, V> Serialize for HashMap<K, V> /// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize, /// where
/// V: Serialize /// K: Serialize,
/// V: Serialize,
/// { /// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut map = serializer.serialize_map(Some(self.len()))?; /// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self { /// for (k, v) in self {
@@ -1753,7 +1864,8 @@ pub trait SerializeMap {
/// ///
/// impl Serialize for Rgb { /// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?; /// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
/// rgb.serialize_field("r", &self.r)?; /// rgb.serialize_field("r", &self.r)?;
@@ -1801,7 +1913,8 @@ pub trait SerializeStruct {
/// ///
/// impl Serialize for E { /// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer /// where
/// S: Serializer,
/// { /// {
/// match *self { /// match *self {
/// E::S { ref r, ref g, ref b } => { /// E::S { ref r, ref g, ref b } => {
+4 -5
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.32" # remember to update html_root_url version = "1.0.61" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -23,10 +23,9 @@ name = "serde_derive"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "0.2" proc-macro2 = "0.4"
quote = "0.4" quote = "0.6"
serde_derive_internals = { version = "=0.20.1", default-features = false, path = "../serde_derive_internals" } syn = { version = "0.14", features = ["visit"] }
syn = { version = "0.12", features = ["visit"] }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0", path = "../serde" } serde = { version = "1.0", path = "../serde" }
+150 -153
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,48 @@ 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 let predicates = cont
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>, .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 +99,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
@@ -125,9 +140,9 @@ 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.clone());
} }
} }
visit::visit_path(self, path); visit::visit_path(self, path);
@@ -139,21 +154,18 @@ 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
.params .type_params()
.iter() .map(|param| param.ident.clone())
.filter_map(|param| match *param {
syn::GenericParam::Type(ref param) => Some(param.ident),
_ => None,
})
.collect(); .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 +174,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.clone())
.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 +226,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,43 +235,42 @@ 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.clone(),
colon_token: None, colon_token: None,
bounds: Punctuated::new(), bounds: Punctuated::new(),
}; };
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.clone());
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.clone()));
}
syn::GenericParam::Const(_) => {}
}
param
}))
.collect(); .collect();
syn::Generics { syn::Generics {
@@ -287,36 +284,36 @@ 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.clone(),
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
args: cont.generics .generics
.params .params
.iter() .iter()
.map(|param| match *param { .map(|param| match *param {
syn::GenericParam::Type(ref param) => { syn::GenericParam::Type(ref param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None, qself: None,
path: param.ident.into(), path: param.ident.clone().into(),
})) }))
} }
syn::GenericParam::Lifetime(ref param) => { syn::GenericParam::Lifetime(ref param) => {
syn::GenericArgument::Lifetime(param.lifetime) syn::GenericArgument::Lifetime(param.lifetime.clone())
} }
syn::GenericParam::Const(_) => { syn::GenericParam::Const(_) => {
panic!("Serde does not support const generics yet"); panic!("Serde does not support const generics yet");
} }
}) })
.collect(), .collect(),
gt_token: Default::default(), gt_token: Default::default(),
}, },
), ),
}, }].into_iter()
].into_iter().collect(), .collect(),
}, },
}) })
} }
+705 -293
View File
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -6,15 +6,16 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use quote::{ToTokens, Tokens}; use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::token; use syn::token;
pub enum Fragment { pub enum Fragment {
/// Tokens that can be used as an expression. /// Tokens that can be used as an expression.
Expr(Tokens), Expr(TokenStream),
/// Tokens that can be used inside a block. The surrounding curly braces are /// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens. /// not part of these tokens.
Block(Tokens), Block(TokenStream),
} }
macro_rules! quote_expr { macro_rules! quote_expr {
@@ -33,7 +34,7 @@ macro_rules! quote_block {
/// Block fragments in curly braces. /// Block fragments in curly braces.
pub struct Expr(pub Fragment); pub struct Expr(pub Fragment);
impl ToTokens for Expr { impl ToTokens for Expr {
fn to_tokens(&self, out: &mut Tokens) { fn to_tokens(&self, out: &mut TokenStream) {
match self.0 { match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out), Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => { Fragment::Block(ref block) => {
@@ -46,7 +47,7 @@ impl ToTokens for Expr {
/// Interpolate a fragment as the statements of a block. /// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment); pub struct Stmts(pub Fragment);
impl ToTokens for Stmts { impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut Tokens) { fn to_tokens(&self, out: &mut TokenStream) {
match self.0 { match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out), Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out), Fragment::Block(ref block) => block.to_tokens(out),
@@ -58,7 +59,7 @@ impl ToTokens for Stmts {
/// involves putting a comma after expressions and curly braces around blocks. /// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment); pub struct Match(pub Fragment);
impl ToTokens for Match { impl ToTokens for Match {
fn to_tokens(&self, out: &mut Tokens) { fn to_tokens(&self, out: &mut TokenStream) {
match self.0 { match self.0 {
Fragment::Expr(ref expr) => { Fragment::Expr(ref expr) => {
expr.to_tokens(out); expr.to_tokens(out);
@@ -71,8 +72,8 @@ impl ToTokens for Match {
} }
} }
impl AsRef<Tokens> for Fragment { impl AsRef<TokenStream> for Fragment {
fn as_ref(&self) -> &Tokens { fn as_ref(&self) -> &TokenStream {
match *self { match *self {
Fragment::Expr(ref expr) => expr, Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block, Fragment::Block(ref block) => block,
@@ -6,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, Derive};
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> {
@@ -32,7 +32,7 @@ pub struct Variant<'a> {
} }
pub struct Field<'a> { pub struct Field<'a> {
pub ident: Option<syn::Ident>, pub member: syn::Member,
pub attrs: attr::Field, pub attrs: attr::Field,
pub ty: &'a syn::Type, pub ty: &'a syn::Type,
pub original: &'a syn::Field, pub original: &'a syn::Field,
@@ -47,8 +47,8 @@ pub enum Style {
} }
impl<'a> Container<'a> { impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> { pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive) -> Container<'a> {
let 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,25 +63,36 @@ 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());
}, },
} }
let item = Container { if has_flatten {
ident: item.ident, attrs.mark_has_flatten();
}
let mut item = Container {
ident: item.ident.clone(),
attrs: attrs, attrs: attrs,
data: data, data: data,
generics: &item.generics, generics: &item.generics,
}; };
check::check(cx, &item); check::check(cx, &mut item, derive);
item item
} }
} }
@@ -113,7 +124,7 @@ fn enum_from_ast<'a>(
let (style, fields) = let (style, fields) =
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default); struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant { Variant {
ident: variant.ident, ident: variant.ident.clone(),
attrs: attrs, attrs: attrs,
style: style, style: style,
fields: fields, fields: fields,
@@ -155,7 +166,10 @@ fn fields_from_ast<'a>(
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, field)| Field { .map(|(i, field)| Field {
ident: field.ident, member: match field.ident {
Some(ref ident) => syn::Member::Named(ident.clone()),
None => syn::Member::Unnamed(i.into()),
},
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default), attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty, ty: &field.ty,
original: field, original: field,
@@ -6,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,
@@ -104,6 +105,7 @@ impl Name {
/// Represents container (e.g. struct) attribute information /// Represents container (e.g. struct) attribute information
pub struct Container { pub struct Container {
name: Name, name: Name,
transparent: bool,
deny_unknown_fields: bool, deny_unknown_fields: bool,
default: Default, default: Default,
rename_all: RenameRule, rename_all: RenameRule,
@@ -114,6 +116,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 +168,7 @@ pub enum Identifier {
} }
impl Identifier { impl Identifier {
#[cfg(feature = "deserialize_in_place")]
pub fn is_some(self) -> bool { pub fn is_some(self) -> bool {
match self { match self {
Identifier::No => false, Identifier::No => false,
@@ -178,6 +182,7 @@ impl Container {
pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
let mut ser_name = Attr::none(cx, "rename"); let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename");
let mut transparent = BoolAttr::none(cx, "transparent");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields"); let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut default = Attr::none(cx, "default"); let mut default = Attr::none(cx, "default");
let mut rename_all = Attr::none(cx, "rename_all"); let mut rename_all = Attr::none(cx, "rename_all");
@@ -197,7 +202,7 @@ impl Container {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename" => { Meta(NameValue(ref m)) if m.ident == "rename" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
ser_name.set(s.value()); ser_name.set(s.value());
de_name.set(s.value()); de_name.set(s.value());
} }
@@ -213,7 +218,7 @@ impl Container {
// Parse `#[serde(rename_all = "foo")]` // Parse `#[serde(rename_all = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename_all" => { Meta(NameValue(ref m)) if m.ident == "rename_all" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match RenameRule::from_str(&s.value()) { match RenameRule::from_str(&s.value()) {
Ok(rename_rule) => rename_all.set(rename_rule), Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => cx.error(format!( Err(()) => cx.error(format!(
@@ -225,14 +230,22 @@ impl Container {
} }
} }
// Parse `#[serde(transparent)]`
Meta(Word(ref word)) if word == "transparent" => {
transparent.set_true();
}
// Parse `#[serde(deny_unknown_fields)]` // Parse `#[serde(deny_unknown_fields)]`
Meta(Word(word)) if word == "deny_unknown_fields" => { Meta(Word(ref word)) if word == "deny_unknown_fields" => {
deny_unknown_fields.set_true(); deny_unknown_fields.set_true();
} }
// Parse `#[serde(default)]` // Parse `#[serde(default)]`
Meta(Word(word)) if word == "default" => match item.data { Meta(Word(ref word)) if word == "default" => match item.data {
syn::Data::Struct(syn::DataStruct { 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 +256,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, &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(
@@ -259,7 +275,7 @@ impl Container {
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
Meta(NameValue(ref m)) if m.ident == "bound" => { Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
{ {
ser_bound.set(where_predicates.clone()); ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates); de_bound.set(where_predicates);
@@ -275,7 +291,7 @@ impl Container {
} }
// Parse `#[serde(untagged)]` // Parse `#[serde(untagged)]`
Meta(Word(word)) if word == "untagged" => match item.data { Meta(Word(ref word)) if word == "untagged" => match item.data {
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
untagged.set_true(); untagged.set_true();
} }
@@ -286,7 +302,7 @@ impl Container {
// Parse `#[serde(tag = "type")]` // Parse `#[serde(tag = "type")]`
Meta(NameValue(ref m)) if m.ident == "tag" => { Meta(NameValue(ref m)) if m.ident == "tag" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match item.data { match item.data {
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
internal_tag.set(s.value()); internal_tag.set(s.value());
@@ -300,7 +316,7 @@ impl Container {
// Parse `#[serde(content = "c")]` // Parse `#[serde(content = "c")]`
Meta(NameValue(ref m)) if m.ident == "content" => { Meta(NameValue(ref m)) if m.ident == "content" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match item.data { match item.data {
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
content.set(s.value()); content.set(s.value());
@@ -315,32 +331,36 @@ impl Container {
// Parse `#[serde(from = "Type")] // Parse `#[serde(from = "Type")]
Meta(NameValue(ref m)) if m.ident == "from" => { Meta(NameValue(ref m)) if m.ident == "from" => {
if let Ok(from_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) { if let Ok(from_ty) = parse_lit_into_ty(cx, &m.ident, &m.lit) {
type_from.set_opt(Some(from_ty)); type_from.set_opt(Some(from_ty));
} }
} }
// Parse `#[serde(into = "Type")] // Parse `#[serde(into = "Type")]
Meta(NameValue(ref m)) if m.ident == "into" => { Meta(NameValue(ref m)) if m.ident == "into" => {
if let Ok(into_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) { if let Ok(into_ty) = parse_lit_into_ty(cx, &m.ident, &m.lit) {
type_into.set_opt(Some(into_ty)); type_into.set_opt(Some(into_ty));
} }
} }
// Parse `#[serde(remote = "...")]` // Parse `#[serde(remote = "...")]`
Meta(NameValue(ref m)) if m.ident == "remote" => { Meta(NameValue(ref m)) if m.ident == "remote" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_path(cx, &m.ident, &m.lit) {
remote.set(path); if is_primitive_path(&path, "Self") {
remote.set(item.ident.clone().into());
} else {
remote.set(path);
}
} }
} }
// Parse `#[serde(field_identifier)]` // Parse `#[serde(field_identifier)]`
Meta(Word(word)) if word == "field_identifier" => { Meta(Word(ref word)) if word == "field_identifier" => {
field_identifier.set_true(); field_identifier.set_true();
} }
// Parse `#[serde(variant_identifier)]` // Parse `#[serde(variant_identifier)]`
Meta(Word(word)) if word == "variant_identifier" => { Meta(Word(ref word)) if word == "variant_identifier" => {
variant_identifier.set_true(); variant_identifier.set_true();
} }
@@ -363,6 +383,7 @@ impl Container {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()), deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
}, },
transparent: transparent.get(),
deny_unknown_fields: deny_unknown_fields.get(), deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None), default: default.get().unwrap_or(Default::None),
rename_all: rename_all.get().unwrap_or(RenameRule::None), rename_all: rename_all.get().unwrap_or(RenameRule::None),
@@ -373,6 +394,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,
} }
} }
@@ -384,6 +406,10 @@ impl Container {
&self.rename_all &self.rename_all
} }
pub fn transparent(&self) -> bool {
self.transparent
}
pub fn deny_unknown_fields(&self) -> bool { pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields self.deny_unknown_fields
} }
@@ -419,6 +445,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 +522,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 +539,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 +556,8 @@ impl Variant {
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut rename_all = Attr::none(cx, "rename_all"); let mut rename_all = Attr::none(cx, "rename_all");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let mut other = BoolAttr::none(cx, "other"); let mut other = BoolAttr::none(cx, "other");
let mut serialize_with = Attr::none(cx, "serialize_with"); let mut serialize_with = Attr::none(cx, "serialize_with");
let mut deserialize_with = Attr::none(cx, "deserialize_with"); let mut deserialize_with = Attr::none(cx, "deserialize_with");
@@ -532,7 +568,7 @@ impl Variant {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename" => { Meta(NameValue(ref m)) if m.ident == "rename" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
ser_name.set(s.value()); ser_name.set(s.value());
de_name.set(s.value()); de_name.set(s.value());
} }
@@ -548,7 +584,7 @@ impl Variant {
// Parse `#[serde(rename_all = "foo")]` // Parse `#[serde(rename_all = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename_all" => { Meta(NameValue(ref m)) if m.ident == "rename_all" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
match RenameRule::from_str(&s.value()) { match RenameRule::from_str(&s.value()) {
Ok(rename_rule) => rename_all.set(rename_rule), Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => cx.error(format!( Err(()) => cx.error(format!(
@@ -560,43 +596,73 @@ impl Variant {
} }
} }
// Parse `#[serde(skip)]`
Meta(Word(ref word)) if word == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
}
// Parse `#[serde(skip_deserializing)]` // Parse `#[serde(skip_deserializing)]`
Meta(Word(word)) if word == "skip_deserializing" => { Meta(Word(ref word)) if word == "skip_deserializing" => {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip_serializing)]` // Parse `#[serde(skip_serializing)]`
Meta(Word(word)) if word == "skip_serializing" => { Meta(Word(ref word)) if word == "skip_serializing" => {
skip_serializing.set_true(); skip_serializing.set_true();
} }
// Parse `#[serde(other)]` // Parse `#[serde(other)]`
Meta(Word(word)) if word == "other" => { Meta(Word(ref word)) if word == "other" => {
other.set_true(); other.set_true();
} }
// Parse `#[serde(bound = "D: Serialize")]`
Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
{
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
Meta(List(ref m)) if m.ident == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
// Parse `#[serde(with = "...")]` // Parse `#[serde(with = "...")]`
Meta(NameValue(ref m)) if m.ident == "with" => { Meta(NameValue(ref m)) if m.ident == "with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path.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, &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, &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
@@ -637,6 +703,8 @@ impl Variant {
ser_renamed: ser_renamed, ser_renamed: ser_renamed,
de_renamed: de_renamed, de_renamed: de_renamed,
rename_all: rename_all.get().unwrap_or(RenameRule::None), rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
skip_deserializing: skip_deserializing.get(), skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(), skip_serializing: skip_serializing.get(),
other: other.get(), other: other.get(),
@@ -663,6 +731,14 @@ impl Variant {
&self.rename_all &self.rename_all
} }
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn skip_deserializing(&self) -> bool { pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing self.skip_deserializing
} }
@@ -675,11 +751,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 +767,16 @@ 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,
transparent: bool,
} }
/// Represents the default to use for a field when deserializing. /// Represents the default to use for a field when deserializing.
@@ -708,7 +786,16 @@ 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 {
pub fn is_none(&self) -> bool {
match *self {
Default::None => true,
Default::Default | Default::Path(_) => false,
}
}
} }
impl Field { impl Field {
@@ -732,6 +819,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 +827,7 @@ impl Field {
}; };
let variant_borrow = attrs let variant_borrow = attrs
.map(|variant| &variant.borrow) .and_then(|variant| variant.borrow.as_ref())
.unwrap_or(&None)
.as_ref()
.map(|borrow| vec![Meta(borrow.clone())]); .map(|borrow| vec![Meta(borrow.clone())]);
for meta_items in field for meta_items in field
@@ -754,7 +840,7 @@ impl Field {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
Meta(NameValue(ref m)) if m.ident == "rename" => { Meta(NameValue(ref m)) if m.ident == "rename" => {
if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
ser_name.set(s.value()); ser_name.set(s.value());
de_name.set(s.value()); de_name.set(s.value());
} }
@@ -769,62 +855,68 @@ impl Field {
} }
// Parse `#[serde(default)]` // Parse `#[serde(default)]`
Meta(Word(word)) if word == "default" => { Meta(Word(ref word)) if word == "default" => {
default.set(Default::Default); default.set(Default::Default);
} }
// Parse `#[serde(default = "...")]` // Parse `#[serde(default = "...")]`
Meta(NameValue(ref m)) if m.ident == "default" => { Meta(NameValue(ref m)) if m.ident == "default" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
default.set(Default::Path(path)); default.set(Default::Path(path));
} }
} }
// Parse `#[serde(skip_serializing)]` // Parse `#[serde(skip_serializing)]`
Meta(Word(word)) if word == "skip_serializing" => { Meta(Word(ref word)) if word == "skip_serializing" => {
skip_serializing.set_true(); skip_serializing.set_true();
} }
// Parse `#[serde(skip_deserializing)]` // Parse `#[serde(skip_deserializing)]`
Meta(Word(word)) if word == "skip_deserializing" => { Meta(Word(ref word)) if word == "skip_deserializing" => {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip)]` // Parse `#[serde(skip)]`
Meta(Word(word)) if word == "skip" => { Meta(Word(ref word)) if word == "skip" => {
skip_serializing.set_true(); skip_serializing.set_true();
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip_serializing_if = "...")]` // Parse `#[serde(skip_serializing_if = "...")]`
Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => { Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
skip_serializing_if.set(path); skip_serializing_if.set(path);
} }
} }
// Parse `#[serde(serialize_with = "...")]` // Parse `#[serde(serialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "serialize_with" => { Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
serialize_with.set(path); serialize_with.set(path);
} }
} }
// Parse `#[serde(deserialize_with = "...")]` // Parse `#[serde(deserialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "deserialize_with" => { Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
// Parse `#[serde(with = "...")]` // Parse `#[serde(with = "...")]`
Meta(NameValue(ref m)) if m.ident == "with" => { Meta(NameValue(ref m)) if m.ident == "with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path.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);
} }
} }
@@ -832,7 +924,7 @@ impl Field {
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
Meta(NameValue(ref m)) if m.ident == "bound" => { Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) parse_lit_into_where(cx, &m.ident, &m.ident, &m.lit)
{ {
ser_bound.set(where_predicates.clone()); ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates); de_bound.set(where_predicates);
@@ -848,7 +940,7 @@ impl Field {
} }
// Parse `#[serde(borrow)]` // Parse `#[serde(borrow)]`
Meta(Word(word)) if word == "borrow" => { Meta(Word(ref word)) if word == "borrow" => {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
borrowed_lifetimes.set(borrowable); borrowed_lifetimes.set(borrowable);
} }
@@ -856,7 +948,7 @@ impl Field {
// Parse `#[serde(borrow = "'a + 'b")]` // Parse `#[serde(borrow = "'a + 'b")]`
Meta(NameValue(ref m)) if m.ident == "borrow" => { Meta(NameValue(ref m)) if m.ident == "borrow" => {
if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, m.ident.as_ref(), &m.lit) { if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, &m.ident, &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 +965,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, &m.lit) {
getter.set(path); getter.set(path);
} }
} }
// Parse `#[serde(flatten)]`
Meta(Word(ref 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 +1014,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 +1075,8 @@ 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(),
transparent: false,
} }
} }
@@ -984,7 +1101,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 +1109,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 +1129,21 @@ 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
}
pub fn transparent(&self) -> bool {
self.transparent
}
pub fn mark_transparent(&mut self) {
self.transparent = true;
}
} }
type SerAndDe<T> = (Option<T>, Option<T>); type SerAndDe<T> = (Option<T>, Option<T>);
@@ -1027,21 +1156,22 @@ fn get_ser_and_de<'a, T, F>(
) -> Result<SerAndDe<T>, ()> ) -> Result<SerAndDe<T>, ()>
where where
T: 'a, T: 'a,
F: Fn(&Ctxt, &str, &str, &'a syn::Lit) -> Result<T, ()>, F: Fn(&Ctxt, &Ident, &Ident, &'a syn::Lit) -> Result<T, ()>,
{ {
let mut ser_meta = Attr::none(cx, attr_name); let mut ser_meta = Attr::none(cx, attr_name);
let mut de_meta = Attr::none(cx, attr_name); let mut de_meta = Attr::none(cx, attr_name);
let attr_name = Ident::new(attr_name, Span::call_site());
for meta in metas { for meta in metas {
match *meta { match *meta {
Meta(NameValue(ref meta)) if meta.ident == "serialize" => { Meta(NameValue(ref meta)) if meta.ident == "serialize" => {
if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) { if let Ok(v) = f(cx, &attr_name, &meta.ident, &meta.lit) {
ser_meta.set(v); ser_meta.set(v);
} }
} }
Meta(NameValue(ref meta)) if meta.ident == "deserialize" => { Meta(NameValue(ref meta)) if meta.ident == "deserialize" => {
if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) { if let Ok(v) = f(cx, &attr_name, &meta.ident, &meta.lit) {
de_meta.set(v); de_meta.set(v);
} }
} }
@@ -1060,7 +1190,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)
} }
@@ -1087,8 +1220,8 @@ pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMeta
fn get_lit_str<'a>( fn get_lit_str<'a>(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
meta_item_name: &str, meta_item_name: &Ident,
lit: &'a syn::Lit, lit: &'a syn::Lit,
) -> Result<&'a syn::LitStr, ()> { ) -> Result<&'a syn::LitStr, ()> {
if let syn::Lit::Str(ref lit) = *lit { if let syn::Lit::Str(ref lit) = *lit {
@@ -1102,15 +1235,26 @@ fn get_lit_str<'a>(
} }
} }
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> { fn parse_lit_into_path(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
parse_lit_str(string).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: &Ident,
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(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
meta_item_name: &str, meta_item_name: &Ident,
lit: &syn::Lit, lit: &syn::Lit,
) -> Result<Vec<syn::WherePredicate>, ()> { ) -> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_lit_str(cx, attr_name, meta_item_name, lit)); let string = try!(get_lit_str(cx, attr_name, meta_item_name, lit));
@@ -1118,20 +1262,21 @@ 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())
.map_err(|err| cx.error(err)) .map_err(|err| cx.error(err))
} }
fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Type, ()> { fn parse_lit_into_ty(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn::Type, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
parse_lit_str(string).map_err(|_| { parse_lit_str(string).map_err(|_| {
cx.error(format!( cx.error(format!(
"failed to parse type: {} = {:?}", "failed to parse type: {} = {:?}",
attr_name, string.value() attr_name,
string.value()
)) ))
}) })
} }
@@ -1140,7 +1285,7 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::
// lifetimes separated by `+`. // lifetimes separated by `+`.
fn parse_lit_into_lifetimes( fn parse_lit_into_lifetimes(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &Ident,
lit: &syn::Lit, lit: &syn::Lit,
) -> Result<BTreeSet<syn::Lifetime>, ()> { ) -> Result<BTreeSet<syn::Lifetime>, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit)); let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
@@ -1161,17 +1306,28 @@ fn parse_lit_into_lifetimes(
if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) { if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
let mut set = BTreeSet::new(); let mut set = BTreeSet::new();
for lifetime in lifetimes { for lifetime in lifetimes {
if !set.insert(lifetime) { if !set.insert(lifetime.clone()) {
cx.error(format!("duplicate borrowed lifetime `{}`", lifetime)); cx.error(format!("duplicate borrowed lifetime `{}`", lifetime));
} }
} }
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 +1369,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 +1420,38 @@ 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 +1541,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,18 +6,21 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use ast::{Data, Container, Style}; use internals::ast::{Container, Data, Field, Style};
use attr::{Identifier, EnumTag}; use internals::attr::{EnumTag, Identifier};
use Ctxt; use internals::{Ctxt, Derive};
use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs /// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs. /// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) { pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_getter(cx, cont); check_getter(cx, cont);
check_flatten(cx, cont);
check_identifier(cx, cont); check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont); check_variant_skip_attrs(cx, cont);
check_internal_tag_field_name_conflict(cx, cont); check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont); check_adjacent_tag_conflict(cx, cont);
check_transparent(cx, cont, derive);
} }
/// Getters are only allowed inside structs (not enums) with the `remote` /// Getters are only allowed inside structs (not enums) with the `remote`
@@ -40,6 +43,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.
/// ///
@@ -121,17 +173,14 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
)); ));
} }
for (i, field) in variant.fields.iter().enumerate() { for field in &variant.fields {
let ident = field let member = member_message(&field.member);
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
if field.attrs.skip_serializing() { if field.attrs.skip_serializing() {
cx.error(format!( cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \ "variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]", a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident variant.ident, member
)); ));
} }
@@ -139,7 +188,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error(format!( cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \ "variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]", a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident variant.ident, member
)); ));
} }
} }
@@ -154,17 +203,14 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
)); ));
} }
for (i, field) in variant.fields.iter().enumerate() { for field in &variant.fields {
if field.attrs.skip_deserializing() { if field.attrs.skip_deserializing() {
let ident = field let member = member_message(&field.member);
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
cx.error(format!( cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \ "variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]", and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident variant.ident, member
)); ));
} }
} }
@@ -176,10 +222,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 +234,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 +253,8 @@ fn check_internal_tag_field_name_conflict(
return; return;
} }
} }
}, }
Style::Unit | Style::Newtype | Style::Tuple => {}, Style::Unit | Style::Newtype | Style::Tuple => {}
} }
} }
} }
@@ -223,7 +263,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,
}; };
@@ -235,3 +278,78 @@ fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
cx.error(message); cx.error(message);
} }
} }
/// Enums and unit structs cannot be transparent.
fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
if !cont.attrs.transparent() {
return;
}
if cont.attrs.type_from().is_some() {
cx.error("#[serde(transparent)] is not allowed with #[serde(from = \"...\")]");
}
if cont.attrs.type_into().is_some() {
cx.error("#[serde(transparent)] is not allowed with #[serde(into = \"...\")]");
}
let fields = match cont.data {
Data::Enum(_) => {
cx.error("#[serde(transparent)] is not allowed on an enum");
return;
}
Data::Struct(Style::Unit, _) => {
cx.error("#[serde(transparent)] is not allowed on a unit struct");
return;
}
Data::Struct(_, ref mut fields) => fields,
};
let mut transparent_field = None;
for field in fields {
if allow_transparent(field, derive) {
if transparent_field.is_some() {
cx.error(
"#[serde(transparent)] requires struct to have at most one transparent field",
);
return;
}
transparent_field = Some(field);
}
}
match transparent_field {
Some(transparent_field) => transparent_field.attrs.mark_transparent(),
None => match derive {
Derive::Serialize => {
cx.error("#[serde(transparent)] requires at least one field that is not skipped");
}
Derive::Deserialize => {
cx.error("#[serde(transparent)] requires at least one field that is neither skipped nor has a default");
}
},
}
}
fn member_message(member: &Member) -> String {
match *member {
Member::Named(ref ident) => format!("`{}`", ident),
Member::Unnamed(ref i) => i.index.to_string(),
}
}
fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ref ty) = *field.ty {
if let Some(seg) = ty.path.segments.last() {
if seg.into_value().ident == "PhantomData" {
return false;
}
}
}
match derive {
Derive::Serialize => !field.attrs.skip_serializing(),
Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(),
}
}
@@ -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)]
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub mod ast;
pub mod attr;
mod ctxt;
pub use self::ctxt::Ctxt;
mod case;
mod check;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
Deserialize,
}
+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.61")]
#![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 {
+140
View File
@@ -0,0 +1,140 @@
use proc_macro2::{Span, TokenStream};
use syn::Ident;
use internals::ast::{Container, Data, Field, Style};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
// never has its fields referenced and an enum annotated with remote derive
// never has its variants constructed.
//
// warning: field is never used: `i`
// --> src/main.rs:4:20
// |
// 4 | struct StructDef { i: i32 }
// | ^^^^^^
//
// warning: variant is never constructed: `V`
// --> src/main.rs:8:16
// |
// 8 | enum EnumDef { V }
// | ^
//
pub fn pretend_used(cont: &Container) -> TokenStream {
let pretend_fields = pretend_fields_used(cont);
let pretend_variants = pretend_variants_used(cont);
quote! {
#pretend_fields
#pretend_variants
}
}
// For structs with named fields, expands to:
//
// match None::<T> {
// Some(T { a: ref __v0, b: ref __v1 }) => {}
// _ => {}
// }
//
// For enums, expands to the following but only including struct variants:
//
// match None::<T> {
// Some(T::A { a: ref __v0 }) => {}
// Some(T::B { b: ref __v0 }) => {}
// _ => {}
// }
//
// The `ref` is important in case the user has written a Drop impl on their
// type. Rust does not allow destructuring a struct or enum that has a Drop
// impl.
fn pretend_fields_used(cont: &Container) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = &variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
Data::Struct(_, _) => {
return quote!();
}
};
quote! {
match _serde::export::None::<#type_ident #ty_generics> {
#(
_serde::export::Some(#patterns) => {}
)*
_ => {}
}
}
}
// Expands to one of these per enum variant:
//
// match None {
// Some((__v0, __v1,)) => {
// let _ = E::V { a: __v0, b: __v1 };
// }
// _ => {}
// }
//
fn pretend_variants_used(cont: &Container) -> TokenStream {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
};
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let turbofish = ty_generics.as_turbofish();
let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.collect::<Vec<_>>();
let pat = match variant.style {
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote!({ #(#members: #placeholders),* })
}
Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
Style::Unit => quote!(),
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
}
});
quote!(#(#cases)*)
}
fn struct_pattern(fields: &[Field]) -> TokenStream {
let members = fields.iter().map(|field| &field.member);
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#members: ref #placeholders),* })
}
+357 -136
View File
@@ -6,38 +6,39 @@
// 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 proc_macro2::{Span, TokenStream};
use syn::spanned::Spanned; use syn::spanned::Spanned;
use quote::Tokens; use syn::{self, Ident, Index, Member};
use proc_macro2::Span;
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, Derive};
use pretend;
use try;
use std::u32; pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, String> {
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = Ctxt::new(); let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input); let cont = Container::from_ast(&ctxt, input, Derive::Serialize);
precondition(&ctxt, &cont); precondition(&ctxt, &cont);
try!(ctxt.check()); try!(ctxt.check());
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 +48,8 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
#[automatically_derived] #[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause { impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
#body #body
} }
@@ -55,10 +57,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
} }
}; };
let try_replacement = try::replacement();
let generated = quote! { let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = { const #dummy_const: () = {
extern crate serde as _serde; extern crate serde as _serde;
#try_replacement
#impl_block #impl_block
}; };
}; };
@@ -98,14 +102,14 @@ 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() {
Some(remote) => remote.clone(), Some(remote) => remote.clone(),
None => cont.ident.into(), None => cont.ident.clone().into(),
}; };
let generics = build_generics(cont); let generics = build_generics(cont);
@@ -120,8 +124,8 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to /// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods. /// various Serializer methods.
fn type_name(&self) -> &str { fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.as_ref() self.this.segments.last().unwrap().value().ident.to_string()
} }
} }
@@ -133,6 +137,9 @@ fn build_generics(cont: &Container) -> syn::Generics {
let generics = let generics =
bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound); bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
let generics =
bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound);
match cont.attrs.ser_bound() { match cont.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates), Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => bound::with_bound( None => bound::with_bound(
@@ -145,31 +152,31 @@ fn build_generics(cont: &Container) -> syn::Generics {
} }
// Fields with a `skip_serializing` or `serialize_with` attribute, or which // Fields with a `skip_serializing` or `serialize_with` attribute, or which
// belong to a variant with a `serialize_with` attribute, are not serialized by // belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
// us so we do not generate a bound. Fields with a `bound` attribute specify // are not serialized by us so we do not generate a bound. Fields with a `bound`
// their own bound so we do not generate one. All other fields may need a `T: // attribute specify their own bound so we do not generate one. All other fields
// Serialize` bound where T is the type of the field. // may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none() !field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
&& variant.map_or(true, |variant| variant.serialize_with().is_none()) && variant.map_or(true, |variant| {
!variant.skip_serializing()
&& variant.serialize_with().is_none()
&& variant.ser_bound().is_none()
})
} }
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
if let Some(type_into) = cont.attrs.type_into() { if cont.attrs.transparent() {
serialize_transparent(cont, params)
} else if let Some(type_into) = cont.attrs.type_into() {
serialize_into(params, type_into) serialize_into(params, type_into)
} else { } else {
match cont.data { match cont.data {
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs), Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, ref fields) => { Data::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(params, fields, &cont.attrs) serialize_struct(params, fields, &cont.attrs)
} }
Data::Struct(Style::Tuple, ref fields) => { Data::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
serialize_tuple_struct(params, fields, &cont.attrs) serialize_tuple_struct(params, fields, &cont.attrs)
} }
Data::Struct(Style::Newtype, ref fields) => { Data::Struct(Style::Newtype, ref fields) => {
@@ -180,6 +187,26 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
} }
} }
fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
let fields = match cont.data {
Data::Struct(_, ref fields) => fields,
Data::Enum(_) => unreachable!(),
};
let self_var = &params.self_var;
let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
let member = &transparent_field.member;
let path = match transparent_field.attrs.serialize_with() {
Some(path) => quote!(#path),
None => quote!(_serde::Serialize::serialize),
};
quote_block! {
#path(&#self_var.#member, __serializer)
}
}
fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment { fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
let self_var = &params.self_var; let self_var = &params.self_var;
quote_block! { quote_block! {
@@ -204,15 +231,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 +255,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 +290,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();
@@ -265,8 +320,7 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
.map(|field| match field.attrs.skip_serializing_if() { .map(|field| match field.attrs.skip_serializing_if() {
None => quote!(1), None => quote!(1),
Some(path) => { Some(path) => {
let ident = field.ident.expect("struct has unnamed fields"); let field_expr = get_member(params, field, &field.member);
let field_expr = get_member(params, field, &Member::Named(ident));
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) })
@@ -279,8 +333,45 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
} }
} }
fn serialize_struct_as_map(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
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 field_expr = get_member(params, field, &field.member);
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 { fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
assert!(variants.len() as u64 <= u64::from(u32::MAX)); assert!(variants.len() as u64 <= u64::from(u32::max_value()));
let self_var = &params.self_var; let self_var = &params.self_var;
@@ -304,9 +395,9 @@ fn serialize_variant(
variant: &Variant, variant: &Variant,
variant_index: u32, variant_index: u32,
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Tokens { ) -> TokenStream {
let this = &params.this; let this = &params.this;
let variant_ident = variant.ident; let variant_ident = &variant.ident;
if variant.attrs.skip_serializing() { if variant.attrs.skip_serializing() {
let skipped_msg = format!( let skipped_msg = format!(
@@ -339,19 +430,16 @@ 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),*)
} }
} }
Style::Struct => { Style::Struct => {
let fields = variant let members = variant.fields.iter().map(|f| &f.member);
.fields
.iter()
.map(|f| f.ident.expect("struct variant has unnamed fields"));
quote! { quote! {
#this::#variant_ident { #(ref #fields),* } #this::#variant_ident { #(ref #members),* }
} }
} }
}; };
@@ -457,7 +545,7 @@ fn serialize_internally_tagged_variant(
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
let enum_ident_str = params.type_name(); let enum_ident_str = params.type_name();
let variant_ident_str = variant.ident.as_ref(); let variant_ident_str = variant.ident.to_string();
if let Some(path) = variant.attrs.serialize_with() { if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, variant); let ser = wrap_serialize_variant_with(params, path, variant);
@@ -548,9 +636,15 @@ fn serialize_adjacently_tagged_variant(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
} }
quote_expr! { return quote_block! {
_serde::Serialize::serialize(#field_expr, __serializer) let mut __struct = try!(_serde::Serializer::serialize_struct(
} __serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, #field_expr));
_serde::ser::SerializeStruct::end(__struct)
};
} }
Style::Tuple => { Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
@@ -573,20 +667,16 @@ fn serialize_adjacently_tagged_variant(
unreachable!() unreachable!()
} }
} }
Style::Newtype => vec![Ident::new("__field0", Span::def_site())], Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
Style::Tuple => (0..variant.fields.len()) Style::Tuple => (0..variant.fields.len())
.map(|i| Ident::new(&format!("__field{}", i), Span::def_site())) .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
.collect(),
Style::Struct => variant
.fields
.iter()
.map(|f| f.ident.expect("struct variant has unnamed fields"))
.collect(), .collect(),
Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
}; };
let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if let Style::Unit = variant.style { let wrapper_generics = if fields_ident.is_empty() {
params.generics.clone() params.generics.clone()
} else { } else {
bound::with_lifetime_bound(&params.generics, "'__a") bound::with_lifetime_bound(&params.generics, "'__a")
@@ -601,7 +691,8 @@ fn serialize_adjacently_tagged_variant(
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
let (#(#fields_ident,)*) = self.data; let (#(#fields_ident,)*) = self.data;
#inner #inner
@@ -679,8 +770,23 @@ fn serialize_tuple_variant(
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait); let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
let len = serialize_stmts.len(); let mut serialized_fields = fields
let let_mut = mut_if(len > 0); .iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|(i, field)| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context { match context {
TupleVariant::ExternallyTagged { TupleVariant::ExternallyTagged {
@@ -729,13 +835,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);
@@ -749,10 +857,10 @@ fn serialize_struct_variant<'a>(
let len = serialized_fields let len = serialized_fields
.map(|field| { .map(|field| {
let ident = field.ident.expect("struct has unnamed fields"); let member = &field.member;
match field.attrs.skip_serializing_if() { match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }), Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
None => quote!(1), None => quote!(1),
} }
}) })
@@ -805,24 +913,115 @@ fn serialize_struct_variant<'a>(
} }
} }
fn serialize_struct_variant_with_flatten<'a>(
context: StructVariant<'a>,
params: &Parameters,
fields: &[Field],
name: &str,
) -> Fragment {
let struct_trait = StructTrait::SerializeMap;
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
match context {
StructVariant::ExternallyTagged {
variant_index,
variant_name,
} => {
let this = &params.this;
let fields_ty = fields.iter().map(|f| &f.ty);
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote_block! {
struct __EnumFlatten #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let (#(#members,)*) = self.data;
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
_serde::Serializer::serialize_newtype_variant(
__serializer,
#name,
#variant_index,
#variant_name,
&__EnumFlatten {
data: (#(#members,)*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
})
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
try!(_serde::ser::SerializeMap::serialize_entry(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
}
}
fn serialize_tuple_struct_visitor( fn serialize_tuple_struct_visitor(
fields: &[Field], fields: &[Field],
params: &Parameters, params: &Parameters,
is_enum: bool, is_enum: bool,
tuple_trait: &TupleTrait, tuple_trait: &TupleTrait,
) -> Vec<Tokens> { ) -> Vec<TokenStream> {
fields fields
.iter() .iter()
.enumerate() .enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.map(|(i, field)| { .map(|(i, field)| {
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
let id = Ident::new(&format!("__field{}", i), Span::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 +1033,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));
@@ -853,16 +1052,17 @@ fn serialize_struct_visitor(
params: &Parameters, params: &Parameters,
is_enum: bool, is_enum: bool,
struct_trait: &StructTrait, struct_trait: &StructTrait,
) -> Vec<Tokens> { ) -> Vec<TokenStream> {
fields fields
.iter() .iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.map(|field| { .map(|field| {
let field_ident = field.ident.expect("struct has unnamed field"); let member = &field.member;
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
quote!(#field_ident) quote!(#member)
} else { } else {
get_member(params, field, &Member::Named(field_ident)) get_member(params, field, &member)
}; };
let key_expr = field.attrs.name().serialize_name(); let key_expr = field.attrs.name().serialize_name();
@@ -876,21 +1076,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,26 +1115,28 @@ 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: &TokenStream,
) -> Tokens { ) -> TokenStream {
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
} }
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 { ) -> TokenStream {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
let field_exprs: Vec<_> = variant let field_exprs: Vec<_> = variant
.fields .fields
.iter() .iter()
.enumerate() .map(|field| {
.map(|(i, field)| { let id = match field.member {
let id = field Member::Named(ref ident) => ident.clone(),
.ident Member::Unnamed(ref member) => {
.unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::def_site())); Ident::new(&format!("__field{}", member.index), Span::call_site())
}
};
quote!(#id) quote!(#id)
}) })
.collect(); .collect();
@@ -935,10 +1150,10 @@ 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: &[TokenStream],
) -> Tokens { ) -> TokenStream {
let this = &params.this; let this = &params.this;
let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
@@ -949,10 +1164,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 +1179,8 @@ fn wrap_serialize_with(
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where
__S: _serde::Serializer,
{ {
#serialize_with(#(self.values.#field_access, )* __s) #serialize_with(#(self.values.#field_access, )* __s)
} }
@@ -981,7 +1199,7 @@ fn wrap_serialize_with(
// _serde::ser::SerializeStruct::end(__serde_state) // _serde::ser::SerializeStruct::end(__serde_state)
// //
// where we want to omit the `mut` to avoid a warning. // where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> { fn mut_if(is_mut: bool) -> Option<TokenStream> {
if is_mut { if is_mut {
Some(quote!(mut)) Some(quote!(mut))
} else { } else {
@@ -989,14 +1207,12 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
} }
} }
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens { fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
let self_var = &params.self_var; let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) { match (params.is_remote, field.attrs.getter()) {
(false, None) => { (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,13 +1227,17 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
} }
enum StructTrait { enum StructTrait {
SerializeMap,
SerializeStruct, SerializeStruct,
SerializeStructVariant, SerializeStructVariant,
} }
impl StructTrait { impl StructTrait {
fn serialize_field(&self, span: Span) -> Tokens { fn serialize_field(&self, span: Span) -> TokenStream {
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 +1247,14 @@ impl StructTrait {
} }
} }
fn skip_field(&self, span: Span) -> Tokens { fn skip_field(&self, span: Span) -> Option<TokenStream> {
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))
} }
} }
} }
@@ -1046,7 +1267,7 @@ enum TupleTrait {
} }
impl TupleTrait { impl TupleTrait {
fn serialize_element(&self, span: Span) -> Tokens { fn serialize_element(&self, span: Span) -> TokenStream {
match *self { match *self {
TupleTrait::SerializeTuple => { TupleTrait::SerializeTuple => {
quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
+24
View File
@@ -0,0 +1,24 @@
use proc_macro2::{Punct, Spacing, TokenStream};
// None of our generated code requires the `From::from` error conversion
// performed by the standard library's `try!` macro. With this simplified macro
// we see a significant improvement in type checking and borrow checking time of
// the generated code and a slight improvement in binary size.
pub fn replacement() -> TokenStream {
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
let dollar = Punct::new('$', Spacing::Alone);
quote! {
#[allow(unused_macros)]
macro_rules! try {
(#dollar __expr:expr) => {
match #dollar __expr {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
}
}
}
+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.4"
syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls"] } syn = { version = "0.14", default-features = false, features = ["derive", "parsing", "clone-impls"] }
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -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/
+3 -3
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.61" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
@@ -12,10 +12,10 @@ readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies] [dependencies]
serde = { version = "1.0.16", path = "../serde" } serde = { version = "1.0.60", path = "../serde" }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0.16", path = "../serde", features = ["rc"] } serde = { version = "1.0", path = "../serde", features = ["rc"] }
serde_derive = { version = "1.0", path = "../serde_derive" } serde_derive = { version = "1.0", path = "../serde_derive" }
[badges] [badges]
File diff suppressed because it is too large Load Diff
+22 -19
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> {
@@ -127,8 +129,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error; type Error = Error;
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf unit seq map identifier ignored_any bytes byte_buf unit seq map identifier ignored_any
} }
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -597,7 +599,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
{ {
match self.variant.take() { match self.variant.take() {
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => seed.deserialize(BytesDeserializer { value: variant }) Some(Token::Bytes(variant)) => seed
.deserialize(BytesDeserializer { value: variant })
.map(Some), .map(Some),
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => unexpected!(other), Some(other) => unexpected!(other),
@@ -654,8 +657,8 @@ impl<'de> de::Deserializer<'de> for BytesDeserializer {
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct bytes byte_buf option unit unit_struct newtype_struct seq tuple
map struct enum identifier ignored_any tuple_struct map struct enum identifier ignored_any
} }
} }
+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.61")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))] #![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// 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.4"
rustc-serialize = "0.3.16" rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] } serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
+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
}
@@ -0,0 +1,20 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(transparent)]
struct S {
//~^^^ HELP: #[serde(transparent)] requires struct to have at most one transparent field
a: u8,
b: u8,
}
fn main() {}
@@ -0,0 +1,22 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(transparent)]
struct S {
//~^^^ HELP: #[serde(transparent)] requires at least one field that is neither skipped nor has a default
#[serde(skip)]
a: u8,
#[serde(default)]
b: u8,
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(transparent)]
struct S {
//~^^^ HELP: #[serde(transparent)] requires at least one field that is not skipped
#[serde(skip)]
a: u8,
}
fn main() {}
File diff suppressed because it is too large Load Diff
+70 -6
View File
@@ -12,20 +12,20 @@
extern crate serde_derive; extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::time::{Duration, UNIX_EPOCH};
use std::default::Default; use std::default::Default;
use std::ffi::{CString, OsString}; use std::ffi::{CString, OsString};
use std::rc::Rc; use std::net;
use std::sync::Arc;
use std::num::Wrapping; use std::num::Wrapping;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use std::ffi::CStr; use std::ffi::CStr;
extern crate serde; extern crate serde;
use serde::Deserialize; use serde::{Deserialize, Deserializer};
extern crate fnv; extern crate fnv;
use self::fnv::FnvHasher; use self::fnv::FnvHasher;
@@ -182,6 +182,27 @@ macro_rules! declare_error_tests {
} }
} }
#[derive(Debug)]
struct SkipPartialEq<T>(T);
impl<'de, T> Deserialize<'de> for SkipPartialEq<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(SkipPartialEq)
}
}
impl<T> PartialEq for SkipPartialEq<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) {
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
struct IgnoreBase { struct IgnoreBase {
@@ -238,6 +259,27 @@ declare_tests! {
0f32 => &[Token::F32(0.)], 0f32 => &[Token::F32(0.)],
0f64 => &[Token::F64(0.)], 0f64 => &[Token::F64(0.)],
} }
test_small_int_to_128 {
1i128 => &[Token::I8(1)],
1i128 => &[Token::I16(1)],
1i128 => &[Token::I32(1)],
1i128 => &[Token::I64(1)],
1i128 => &[Token::U8(1)],
1i128 => &[Token::U16(1)],
1i128 => &[Token::U32(1)],
1i128 => &[Token::U64(1)],
1u128 => &[Token::I8(1)],
1u128 => &[Token::I16(1)],
1u128 => &[Token::I32(1)],
1u128 => &[Token::I64(1)],
1u128 => &[Token::U8(1)],
1u128 => &[Token::U16(1)],
1u128 => &[Token::U32(1)],
1u128 => &[Token::U64(1)],
}
test_char { test_char {
'a' => &[Token::Char('a')], 'a' => &[Token::Char('a')],
'a' => &[Token::Str("a")], 'a' => &[Token::Str("a")],
@@ -788,11 +830,33 @@ declare_tests! {
Token::Bool(true), Token::Bool(true),
], ],
} }
test_rc_weak_some {
SkipPartialEq(RcWeak::<bool>::new()) => &[
Token::Some,
Token::Bool(true),
],
}
test_rc_weak_none {
SkipPartialEq(RcWeak::<bool>::new()) => &[
Token::None,
],
}
test_arc { test_arc {
Arc::new(true) => &[ Arc::new(true) => &[
Token::Bool(true), Token::Bool(true),
], ],
} }
test_arc_weak_some {
SkipPartialEq(ArcWeak::<bool>::new()) => &[
Token::Some,
Token::Bool(true),
],
}
test_arc_weak_none {
SkipPartialEq(ArcWeak::<bool>::new()) => &[
Token::None,
],
}
test_wrapping { test_wrapping {
Wrapping(1usize) => &[ Wrapping(1usize) => &[
Token::U32(1), Token::U32(1),
+188 -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,95 @@ 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>,
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum UntaggedNewtypeVariantWith {
Newtype(
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
X,
),
}
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct TransparentWith {
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
x: X,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+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,
} }
+43 -5
View File
@@ -10,13 +10,14 @@
extern crate serde_derive; extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::{Path, PathBuf};
use std::time::{Duration, UNIX_EPOCH};
use std::ffi::CString; use std::ffi::CString;
use std::rc::Rc; use std::mem;
use std::sync::Arc; use std::net;
use std::num::Wrapping; use std::num::Wrapping;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(unix)] #[cfg(unix)]
use std::str; use std::str;
@@ -398,11 +399,41 @@ declare_tests! {
Token::Bool(true), Token::Bool(true),
], ],
} }
test_rc_weak_some {
{
let rc = Rc::new(true);
mem::forget(rc.clone());
Rc::downgrade(&rc)
} => &[
Token::Some,
Token::Bool(true),
],
}
test_rc_weak_none {
RcWeak::<bool>::new() => &[
Token::None,
],
}
test_arc { test_arc {
Arc::new(true) => &[ Arc::new(true) => &[
Token::Bool(true), Token::Bool(true),
], ],
} }
test_arc_weak_some {
{
let arc = Arc::new(true);
mem::forget(arc.clone());
Arc::downgrade(&arc)
} => &[
Token::Some,
Token::Bool(true),
],
}
test_arc_weak_none {
ArcWeak::<bool>::new() => &[
Token::None,
],
}
test_wrapping { test_wrapping {
Wrapping(1usize) => &[ Wrapping(1usize) => &[
Token::U64(1), Token::U64(1),
@@ -555,3 +586,10 @@ fn test_enum_skipped() {
"the enum variant Enum::SkippedMap cannot be serialized", "the enum variant Enum::SkippedMap cannot be serialized",
); );
} }
#[test]
fn test_integer128() {
assert_ser_tokens_error(&1i128, &[], "i128 is not supported");
assert_ser_tokens_error(&1u128, &[], "u128 is not supported");
}
+1 -1
View File
@@ -10,8 +10,8 @@
extern crate serde_derive; extern crate serde_derive;
extern crate serde; extern crate serde;
use serde::Deserialize;
use serde::de::{value, IntoDeserializer}; use serde::de::{value, IntoDeserializer};
use serde::Deserialize;
#[test] #[test]
fn test_u32_to_enum() { fn test_u32_to_enum() {
+6
View File
@@ -87,4 +87,10 @@ else
channel build --no-default-features channel build --no-default-features
cd "$DIR/serde_test" cd "$DIR/serde_test"
channel build channel build
CHANNEL=1.15.0
cd "$DIR"
cargo clean
cd "$DIR/serde_derive"
channel build
fi fi