Compare commits

...

404 Commits

Author SHA1 Message Date
David Tolnay 60cbbacdb3 Release 1.0.72 2018-08-20 21:02:03 -04:00
David Tolnay befc7edc17 Merge pull request #1359 from Pratyush/master
Fix compilation under `rc` feature
2018-08-20 21:00:47 -04:00
Pratyush Mishra 3897ccb3f9 Fix compilation under rc feature 2018-08-20 14:35:48 -07:00
David Tolnay 11c5fd78ad Abbreviate and touch up some attribute parsing comments 2018-08-14 22:37:59 -07:00
David Tolnay cbfdba3826 Use rustfmt to wrap and format comments 2018-08-14 22:32:27 -07:00
David Tolnay 5985b7edaf Format with rustfmt 0.99.2 2018-08-14 19:59:20 -07:00
David Tolnay d28a0e66c8 Fix old reference to serde_codegen 2018-08-12 10:54:59 -07:00
David Tolnay 0ca4db1616 Move untagged borrow test case into codegen tests 2018-08-12 10:54:29 -07:00
David Tolnay 72b3438dfc Merge pull request #1338 from toidiu/ak-untagged-enum
test borrowing untagged enum
2018-08-12 10:49:15 -07:00
David Tolnay c7051ac748 Update links to a renamed manual chapter 2018-08-12 10:48:20 -07:00
David Tolnay a065db9838 Add AppVeyor badge to rest of crates 2018-08-07 00:15:12 -07:00
David Tolnay 24c4df7831 Release 1.0.71 2018-08-06 23:55:55 -07:00
David Tolnay a077ae039e Merge pull request #1349 from dtolnay/range
Share some code between the Range and RangeInclusive impls
2018-08-06 23:30:03 -07:00
David Tolnay 20b34d3b43 Share some code between the Range and RangeInclusive impls 2018-08-06 23:16:47 -07:00
David Tolnay b5451d1905 Merge pull request #1348 from dtolnay/range
Provide ops::Range impls whether or not std is used
2018-08-06 23:04:26 -07:00
David Tolnay e26960f7f8 Remove useless run-pass test
When originally added, this test used to contain a `#![plugin(clippy)]`.
This was removed at some point along the way, at which point this test
no longer tests anything. It prints:

    warning: unknown lint: `identity_op`
     --> src/main.rs:1:9
      |
    1 | #![deny(identity_op)]
      |         ^^^^^^^^^^^
      |
      = note: #[warn(unknown_lints)] on by default

which is swallowed and ignored by compiletest.

Nowadays Clippy handles warnings inside of macro expanded code
intelligently and this is something they would be responsible for
testing.
2018-08-06 22:57:46 -07:00
David Tolnay 228b5a4a63 Provide ops::Range impls whether or not std is used 2018-08-06 22:49:09 -07:00
David Tolnay 28db9d4989 Format with rustfmt 0.99.1 2018-08-06 22:40:28 -07:00
David Tolnay 5fff0d936d Merge pull request #1347 from c410-f3r/master
Implement Serialize and Deserialize for RangeInclusive
2018-08-06 22:36:12 -07:00
Caio 8eb195edf0 Fix tests 2018-08-05 17:38:41 -03:00
Caio 8b2e6baf78 Implement Serialize and Deserialize for RangeInclusive 2018-08-05 10:45:50 -03:00
toidiu 3ca0597a7e test borrowing untagged enum 2018-07-12 17:12:27 -04:00
David Tolnay 4e54aaf796 Format with rustfmt 0.8.2 2018-07-08 19:02:44 -07:00
David Tolnay 4cddcbe194 Release 1.0.70 2018-07-06 20:21:26 -07:00
David Tolnay 54b6798ef6 Merge pull request #1336 from dtolnay/collections
Update path to alloc::collections for nightly-2018-07-07
2018-07-06 20:19:59 -07:00
David Tolnay 229a9d90ba Update path to alloc::collections for nightly-2018-07-07 2018-07-06 20:04:23 -07:00
David Tolnay 3bcd568c86 Release 1.0.69 2018-06-30 23:40:28 -07:00
David Tolnay dc56077aac Local inner macros 2018-06-30 23:38:14 -07:00
David Tolnay 46bd36e17c Link to issue picker 2018-06-30 10:30:14 -07:00
David Tolnay 5dee9118c7 Factor out the getting help links 2018-06-30 10:29:36 -07:00
David Tolnay a916aa9420 Release 1.0.68 2018-06-28 09:31:12 -07:00
David Tolnay d9c63d0784 Merge pull request #1324 from jechase/suppress_2018_warning
Suppress 'extern crate' warning for rust 2018
2018-06-28 09:30:40 -07:00
Josh Chase 41dcb969e8 Shut clippy up 2018-06-28 11:12:27 -04:00
Josh Chase 6dbaea34ba Suppress 'extern crate' warning for rust 2018 2018-06-28 10:51:57 -04:00
David Tolnay ce17301b8b Release 1.0.67 2018-06-27 00:18:03 -07:00
David Tolnay b0e78c6be4 Format with rustfmt 0.8.2 2018-06-27 00:16:06 -07:00
David Tolnay 898f65fa46 Merge pull request #1323 from dtolnay/format-args
Implement Serialize for core::fmt::Arguments
2018-06-27 00:15:55 -07:00
David Tolnay 84e384196d Implement Serialize for core::fmt::Arguments 2018-06-26 23:58:16 -07:00
David Tolnay d827b101d9 Resolve default_trait_access lint 2018-06-26 23:58:02 -07:00
David Tolnay c45ab6b304 Ignore indexing_slicing pedantic lint 2018-06-26 23:56:39 -07:00
David Tolnay cc9d85b293 Work around unused_imports rustdoc bug 2018-06-26 23:54:32 -07:00
David Tolnay 02493d83be Ignore indexing_slicing pedantic lint 2018-06-26 23:39:26 -07:00
David Tolnay a1280c672a Switch no-std panic to #[panic_implementation] 2018-06-04 10:13:29 -07:00
David Tolnay a740f76772 Update no-std panic signature for nightly-2018-06-03 2018-06-03 23:15:16 -07:00
David Tolnay a887db398b Release 1.0.66 2018-06-03 11:45:20 -07:00
Oliver Schneider e1ae3c71f3 Merge pull request #1304 from dtolnay/ci
CI builders for all versions mentioned in the build script
2018-06-03 10:44:32 +02:00
David Tolnay d094209774 CI builders for all versions mentioned in the build script
This should prevent accidentally inserting something under one of these
cfgs that is available only on a newer rustc. For example if something
is changed in the Duration serialization, but that change works only on
a recent rustc, our test suite will not have caught it before.
2018-06-03 01:26:58 -07:00
David Tolnay 485a64aaf9 Visitor for types that parse from a string 2018-06-03 01:19:46 -07:00
David Tolnay 3e57cd5917 Merge pull request #1303 from dtolnay/duration
Support Duration in no-std mode on new compilers
2018-06-03 01:05:39 -07:00
David Tolnay b6c4cfec37 Support Duration in no-std mode on new compilers 2018-06-03 00:55:58 -07:00
David Tolnay 94853752a1 Stabilize some unstable tests in test suite 2018-06-03 00:31:20 -07:00
David Tolnay bd366f675e Merge pull request #1302 from dtolnay/never
Implement traits for `!`
2018-06-03 00:30:19 -07:00
David Tolnay 22b1af7eb3 Test never_type 2018-06-03 00:22:11 -07:00
David Tolnay fd6178cad6 IntoDeserializer for ! 2018-06-03 00:12:02 -07:00
David Tolnay 338fb67853 Implement traits for ! 2018-06-03 00:02:29 -07:00
David Tolnay 0a71fe329c Format the compile-test sources with rustfmt 0.8.2 2018-06-02 22:30:55 -07:00
David Tolnay a4acc83282 Place compile-fail expected errors on their own line 2018-06-02 22:28:05 -07:00
David Tolnay 57de28744c These match-expressions are implementing unwrap_or_else 2018-06-02 22:09:04 -07:00
David Tolnay 6d31ec521b Remove leftover import from compile_error change 2018-06-02 22:01:45 -07:00
David Tolnay 7ad3d17e59 Merge pull request #1297 from adamcrume/master
Use compile_error! instead of panicking
2018-06-02 22:00:24 -07:00
Adam Crume 05e931b9a5 Update tests and use quote! macro 2018-06-02 21:11:42 -07:00
David Tolnay 2db2b53bbf Release 1.0.65 2018-06-01 13:00:58 -07:00
David Tolnay d5ec3efe49 Merge pull request #1299 from dtolnay/flattenmap
Allow multiple flattened maps to see the same fields
2018-06-01 13:00:45 -07:00
David Tolnay 71fc318474 Merge pull request #1300 from dtolnay/refcell
Use try_borrow for serializing RefCell
2018-06-01 12:58:03 -07:00
David Tolnay 5ee2fc0562 Allow multiple flattened maps to see the same fields
Before this change, flattening anything after a flattened map was
nonsensical because the later flattened field would always observe no
input fields.

    #[derive(Deserialize)]
    struct S {
        #[serde(flatten)]
        map: Map<K, V>,
        #[serde(flatten)]
        other: Other, // always empty
    }

This change makes a flattened map not consume any of the input fields,
leaving them available to later flattened fields in the same struct. The
new behavior is useful when two flattened fields that both use
deserialize_map care about disjoint subsets of the fields in the input.

    #[derive(Deserialize)]
    struct S {
        // Looks at fields with a "player1_" prefix.
        #[serde(flatten, with = "prefix_player1")]
        player1: Player,
        // Looks at fields with a "player2_" prefix.
        #[serde(flatten, with = "prefix_player2")]
        player2: Player,
    }
2018-06-01 12:50:23 -07:00
David Tolnay ca53daf697 Fix RefCell serialize impl to work with no-std 2018-06-01 12:47:10 -07:00
Konrad Borowski c3b9ee314b Use try_borrow for serializing RefCell 2018-06-01 09:09:40 +02:00
Adam Crume 993710eb16 Use compile_error! instead of panicking
Fixes #1168
2018-05-31 19:57:23 -07:00
David Tolnay dbaf2893e3 Release 1.0.64 2018-05-30 00:17:45 -07:00
David Tolnay 34a7108b73 Second attempt at workaround for docs.rs compiler 2018-05-30 00:17:02 -07:00
David Tolnay db2bafd3f3 Revert "Work around docs.rs using an old 1.26-dev compiler"
This reverts commit c81bab18ad.
2018-05-30 00:13:20 -07:00
David Tolnay 1b6fbf1023 Release 1.0.63 2018-05-28 20:12:08 -07:00
David Tolnay c81bab18ad Work around docs.rs using an old 1.26-dev compiler 2018-05-28 19:58:27 -07:00
David Tolnay a39199e9f7 Reword Avro blurb
- Emphasize the association with Apache Hadoop,

- Rephrase "schematized data" because that term returns not many Google
  results, doesn't seem widely recognized.
2018-05-27 19:39:50 -07:00
David Tolnay b0ad1e56e8 Move Avro above deserialization-only formats 2018-05-27 19:31:05 -07:00
David Tolnay ab53448bc3 Merge pull request #1260 from flavray/master
Add Avro to the list of supported data formats
2018-05-27 19:29:19 -07:00
David Tolnay c50c9d8862 Simplify readme as rendered on crates.io 2018-05-27 19:18:30 -07:00
David Tolnay cc4f289758 Link from readme to new playground 2018-05-27 19:07:46 -07:00
David Tolnay a2a9041549 Fix warning about unresolved [u8] and [T] links 2018-05-27 14:35:55 -07:00
David Tolnay a65950acca Link to more complete explanation of the data model 2018-05-27 14:11:02 -07:00
David Tolnay 0fbf4d0c5d Link to example data format from trait rustdocs 2018-05-27 14:05:50 -07:00
David Tolnay 983bf8c090 Release 1.0.62 2018-05-26 18:59:03 -07:00
David Tolnay f2afa89ff1 Explain the pattern for optional Serde derives 2018-05-26 17:59:53 -07:00
David Tolnay 8b4f9c47c4 Build script rustc-cfg strings are not public API 2018-05-26 17:23:09 -07:00
David Tolnay 06d8a44f18 Move unimportant code out of build script main 2018-05-26 17:18:14 -07:00
David Tolnay fffdceca95 Link to "Understanding deserializer lifetimes" 2018-05-26 17:08:46 -07:00
David Tolnay 794b769e6b Merge pull request #1288 from dtolnay/copy
Implement Copy for value deserializers of primitive types
2018-05-26 16:05:12 -07:00
David Tolnay 927ec7d38e Implement Copy for value deserializers of primitive types 2018-05-26 15:56:57 -07:00
David Tolnay cd0b2d312c Merge pull request #1286 from dtolnay/into128
Implement IntoDeserializer for i128 and u128
2018-05-26 15:36:46 -07:00
David Tolnay ea118e11a0 Test the 128-bit IntoDeserializer impls 2018-05-26 15:21:37 -07:00
David Tolnay 0ff4882cab Implement IntoDeserializer for i128 and u128 2018-05-26 15:15:07 -07:00
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
Flavien Raynaud 38d4f0e06c Add Avro to the list of supported data formats 2018-05-16 16:22:25 +01: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
David Tolnay 23c6eb3b40 Release 1.0.32 2018-03-13 11:31:26 -07:00
David Tolnay b8c9a66d75 Release 1.0.31 2018-03-13 10:18:35 -07:00
David Tolnay 56b2e39dda Fix panic when a reference has unspecified lifetime
This will fail later in compilation anyway, but serde_derive needs to
not crash before then.

    #[derive(Deserialize)]
    struct A {
        field: &str,
    }

    error[E0106]: missing lifetime specifier
      --> src/main.rs
       |
       |     field: &str,
       |            ^ expected lifetime parameter
2018-03-13 09:56:38 -07:00
David Tolnay 5bc805329e Drop impl should only panic if not already panicking 2018-03-13 09:42:07 -07:00
David Tolnay 69dd3215f4 Release 1.0.30 2018-03-12 11:44:50 -07:00
David Tolnay a7a7a31809 Merge pull request #1175 from daboross/fix-borrowed-cow-bytes
Fix borrowed Cow<'_, [u8]> deserializing as str.
2018-03-12 11:44:14 -07:00
David Ross af9996aa9a Fix borrowed Cow<'_, [u8]> deserializing as str.
This changes the deserialize implementation for a borrowed Cow<[u8]>
to specifically request a byte slice, rather than a borrowed string.

The old behavior breaks any program which relies on data being
deserialized the same way as it was serialized and uses Cow<[u8]>.
In serde_json, it just wouldn't deserialize. In bincode, it
deserialized normally unless the bytes were invalid UTF8.

Fixes https://github.com/TyOverby/bincode/issues/231.
2018-03-12 11:26:11 -07:00
David Tolnay 0d4d47c398 Release 1.0.29 2018-03-09 00:24:08 -08:00
David Tolnay 30361ac6d0 Clean up workaround that required too many parentheses
The issue has been fixed in the compiler and these extra call site parentheses
are no longer required.
2018-03-09 00:22:27 -08:00
David Tolnay 3f75239bfb Release 1.0.28 2018-03-08 11:39:32 -08:00
David Tolnay 8dd5605a40 Merge pull request #1170 from H2CO3/disallow_internal_tag_conflict
Disallow variant field names to conflict with tag of internally-tagged enum
2018-03-08 09:34:27 -08:00
David Tolnay f288a41768 Test the new errors on conflicting enum tags 2018-03-08 09:31:25 -08:00
Árpád Goretity f4b78e202a add a check for conflicting adjacent tags as well 2018-03-08 09:57:05 +01:00
Árpád Goretity 0ddebe0317 More descriptive function name; add doc comment to function 2018-03-08 01:05:19 +01:00
Árpád Goretity 9fc526b788 be more explicit in match for future-proofing code via exhaustiveness check 2018-03-08 00:53:56 +01:00
Árpád Goretity a799ea171c Disallow variant field names to conflict with tag of internally-tagged enum 2018-03-08 00:43:35 +01:00
David Tolnay d6f07f2f47 Ignore redundant_field_names lint 2018-02-27 11:13:26 -08: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
David Tolnay 8bba8447ef Whitelist some new clippy lints 2018-02-05 10:27:04 -08:00
David Tolnay 9db784bccd Ignore decimal_literal_representation in test suite 2018-01-29 21:52:21 -08:00
David Tolnay 9317bc5afa Address clippy lints in serde_derive_internals 2018-01-26 00:22:38 -08:00
David Tolnay a185df1e77 Ignore decimal_literal_representation lint
The number 4096 is used to cap the size of collections that we preallocate.

    cmp::min(hint.unwrap_or(0), 4096)

I find this number more understandable than 0x1000.
2018-01-26 00:19:26 -08:00
David Tolnay 1bdf5ecec4 Ignore unused_parens warning on the proc macro workaround 2018-01-21 17:54:06 -08:00
David Tolnay 59017aa19b Follow clippy's replace_consts lint 2018-01-15 17:40:32 -08:00
David Tolnay 6b4625dcbb Ignore warning in no_std test 2018-01-13 14:43:34 -08:00
David Tolnay 6e01f220b1 Ignore clippy flagging our workaround 2018-01-13 14:28:12 -08:00
David Tolnay 64573319f9 Meaningful spans when invoking deserializer trait methods 2018-01-10 20:59:48 -08:00
David Tolnay 3d64df6e87 Meaningful span for attrs parsed from string literal 2018-01-10 19:59:49 -08:00
David Tolnay cc2558b0dc Meaningful spans when invoking serializer trait methods 2018-01-10 19:22:07 -08:00
David Tolnay 5c41661bce Merge pull request #1140 from serde-rs/hygiene
Hygiene fixes
2018-01-09 22:39:23 -08:00
David Tolnay dd6914a203 Build the test suite in CI using proc-macro2/nightly 2018-01-09 22:23:19 -08:00
David Tolnay 63623eb3b3 Hygiene fixes 2018-01-09 22:22:08 -08:00
David Tolnay ddc4b50d4d Use call_site in 'with' attribute 2018-01-09 20:34:29 -08:00
David Tolnay b313f947dc Use call_site as the span of unnamed member access 2018-01-09 20:28:23 -08:00
David Tolnay 16bc9fb99e Address clippy lints in serde_derive 2018-01-09 19:40:34 -08:00
David Tolnay 34eaab00f7 Address clippy lints in serde_derive_internals 2018-01-09 19:40:33 -08:00
David Tolnay 6024e717fb Merge pull request #1138 from serde-rs/syn
Update to syn 0.12
2018-01-09 19:23:19 -08:00
David Tolnay ef4dd6c0ec Update to syn 0.12 2018-01-09 19:05:08 -08:00
David Tolnay f7ed967db1 Merge pull request #1135 from mcgoo/appveyor-tls
get rustup-init with curl to avoid tls failures
2018-01-04 20:55:53 -08:00
mcgoo 613e46b0ee get rustup-init with curl to avoid tls failures 2018-01-04 22:04:16 -06:00
David Tolnay b2d2e96267 Merge pull request #1133 from martinlindhe/master
fix some typos
2018-01-03 07:44:40 -08:00
Martin Lindhe ae0373643c fix some typos 2018-01-03 15:16:45 +01:00
136 changed files with 9129 additions and 2816 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
---
+6 -1
View File
@@ -4,10 +4,15 @@ cache: cargo
# run builds for all the trains (and more)
rust:
- 1.13.0
- stable
- beta
- nightly
- 1.13.0
- 1.15.0
- 1.20.0
- 1.21.0
- 1.25.0
- 1.26.0
matrix:
include:
+11 -8
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
[travis]: https://travis-ci.org/serde-rs/serde
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[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.**
@@ -23,7 +25,7 @@ You may be looking for:
<details>
<summary>
Click to show Cargo.toml.
<a href="http://play.integer32.com/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a>
<a href="https://play.rust-lang.org/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a>
</summary>
```toml
@@ -77,12 +79,13 @@ fn main() {
## Getting help
Serde developers live in the #serde channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
good resource with generally faster response time but less specific knowledge
about Serde. If IRC is not your thing or you don't get a good response, we are
happy to respond to [GitHub issues](https://github.com/serde-rs/serde/issues/new)
as well.
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
## License
+1 -1
View File
@@ -5,7 +5,7 @@ environment:
install:
# Install rust, x86_64-pc-windows-msvc host
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -vV
+56
View File
@@ -0,0 +1,56 @@
<!-- Serde readme rendered on crates.io -->
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
---
You may be looking for:
- [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
- [Examples](https://serde.rs/examples.html)
- [API documentation](https://docs.serde.rs/serde/)
- [Release notes](https://github.com/serde-rs/serde/releases)
## Serde in action
```rust
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
```
## Getting help
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
-1
View File
@@ -1,2 +1 @@
error_on_line_overflow = false
same_line_attributes = false
+27 -15
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.27" # remember to update html_root_url
version = "1.0.72" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -9,8 +9,9 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
readme = "crates-io.md"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs"
[badges]
travis-ci = { repository = "serde-rs/serde" }
@@ -28,14 +29,30 @@ serde_derive = { version = "1.0", path = "../serde_derive" }
[features]
default = ["std"]
# Re-export the derive(Serialize, Deserialize) macros. This is specifically
# intended for library crates that provide optional Serde impls behind a Cargo
# cfg of their own. All other crates should depend on serde_derive directly.
# Re-export the derive(Serialize, Deserialize) macros. This is intended for
# library crates that provide optional Serde impls behind a Cargo cfg of their
# own.
#
# Mainly this is a workaround for limitations associated with
# rust-lang/cargo#1286 in which a library crate cannot use one "serde" cfg in
# Cargo to enable dependencies on both serde and serde_derive crates.
#
# The recommended way to provide optional Serde support that requires derive is
# as follows. In particular, please do not name your library's Serde feature
# anything other than "serde".
#
# [dependencies]
# serde = { version = "1.0", optional = true, features = ["derive"] }
#
# Within the library, these optional Serde derives would be written like this.
#
# #[cfg(feature = "serde")]
# #[macro_use]
# extern crate serde;
#
# #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
# struct ...
#
# Please refer to the long comment above the line `pub use serde_derive::*` in
# src/lib.rs before enabling this feature. If you think you need this feature
# and your use case does not precisely match the one described in the comment,
# please open an issue to let us know about your use case.
derive = ["serde_derive"]
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
@@ -61,8 +78,3 @@ alloc = ["unstable"]
# 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.
rc = []
# Get serde_derive picked up by the Integer 32 playground. Not public API.
#
# http://play.integer32.com/
playground = ["serde_derive"]
+84
View File
@@ -0,0 +1,84 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => 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");
}
// Duration available in core since Rust 1.25:
// https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
if minor >= 25 {
println!("cargo:rustc-cfg=core_duration");
}
// 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");
}
// Inclusive ranges methods stabilized in Rust 1.27:
// https://github.com/rust-lang/rust/pull/50758
if minor >= 27 {
println!("cargo:rustc-cfg=range_inclusive");
}
// 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");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
// Temporary workaround to support the old 1.26-dev compiler on docs.rs.
if version.contains("0eb87c9bf") {
return Some(25);
}
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
u32::from_str(next).ok()
}
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+199 -47
View File
@@ -9,42 +9,40 @@
use lib::*;
macro_rules! int_to_int {
($dst:ident, $n:ident) => (
if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
($dst:ident, $n:ident) => {
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
Some($n as $dst)
} else {
None
}
)
};
}
macro_rules! int_to_uint {
($dst:ident, $n:ident) => (
if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
($dst:ident, $n:ident) => {
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
)
};
}
macro_rules! uint_to {
($dst:ident, $n:ident) => (
if $n as u64 <= $dst::MAX as u64 {
($dst:ident, $n:ident) => {
if $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
)
};
}
pub trait FromPrimitive: Sized {
fn from_isize(n: isize) -> Option<Self>;
fn from_i8(n: i8) -> Option<Self>;
fn from_i16(n: i16) -> Option<Self>;
fn from_i32(n: i32) -> 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_u16(n: u16) -> Option<Self>;
fn from_u32(n: u32) -> Option<Self>;
@@ -52,54 +50,120 @@ pub trait FromPrimitive: Sized {
}
macro_rules! impl_from_primitive_for_int {
($t:ident) => (
($t:ident) => {
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
#[inline]
fn from_i8(n: i8) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_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 {
($t:ident) => (
($t:ident) => {
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
#[inline]
fn from_i8(n: i8) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_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 {
($t:ident) => (
($t:ident) => {
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
#[inline]
fn from_i8(n: i8) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_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);
@@ -114,3 +178,91 @@ impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
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)
}
}
}
+18 -7
View File
@@ -20,7 +20,9 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, IgnoredAny};
/// use serde::de::{
/// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
/// };
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
@@ -45,16 +47,22 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = T;
///
/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// write!(formatter, "a sequence in which we care about element {}", self.n)
/// write!(
/// formatter,
/// "a sequence in which we care about element {}",
/// self.n
/// )
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de>
/// where
/// A: SeqAccess<'de>,
/// {
/// // Skip over the first `n` elements.
/// for i in 0..self.n {
@@ -82,19 +90,22 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = T;
///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// deserializer.deserialize_seq(self)
/// }
/// }
///
/// # 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.
/// // The element at index 3 is required to be a string. Elements before and
+556 -244
View File
File diff suppressed because it is too large Load Diff
+312 -82
View File
@@ -24,8 +24,7 @@
//!
//! Additionally, Serde provides a procedural macro called [`serde_derive`] to
//! automatically generate [`Deserialize`] implementations for structs and enums
//! in your program. See the [codegen section of the manual] for how to use
//! this.
//! in your program. See the [derive section of the manual] for how to use this.
//!
//! In rare cases it may be necessary to implement [`Deserialize`] manually for
//! some type in your program. See the [Implementing `Deserialize`] section of
@@ -52,12 +51,12 @@
//!
//! - **Primitive types**:
//! - bool
//! - i8, i16, i32, i64, isize
//! - u8, u16, u32, u64, usize
//! - i8, i16, i32, i64, i128, isize
//! - u8, u16, u32, u64, u128, usize
//! - f32, f64
//! - char
//! - **Compound types**:
//! - [T; 0] through [T; 32]
//! - \[T; 0\] through \[T; 32\]
//! - tuples up to size 16
//! - **Common standard library types**:
//! - String
@@ -66,7 +65,7 @@
//! - PhantomData\<T\>
//! - **Wrapper types**:
//! - Box\<T\>
//! - Box\<[T]\>
//! - Box\<\[T\]\>
//! - Box\<str\>
//! - Rc\<T\>
//! - Arc\<T\>
@@ -84,10 +83,9 @@
//! - LinkedList\<T\>
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **Zero-copy types**:
//! - &str
//! - &[u8]
//! - &\[u8\]
//! - **FFI types**:
//! - CString
//! - Box\<CStr\>
@@ -98,7 +96,9 @@
//! - Path
//! - PathBuf
//! - Range\<T\>
//! - NonZero\<T\> (unstable)
//! - RangeInclusive\<T\>
//! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
@@ -116,7 +116,7 @@
//! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json
//! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml
//! [codegen section of the manual]: https://serde.rs/codegen.html
//! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats
use lib::*;
@@ -149,6 +149,13 @@ macro_rules! declare_error_trait {
///
/// Most deserializers should only need to provide the `Error::custom` method
/// and inherit the default behavior for the other methods.
///
/// # Example implementation
///
/// The [example data format] presented on the website shows an error
/// type appropriate for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Error: Sized $(+ $($supertrait)::+)* {
/// Raised when there is general error when deserializing a type.
///
@@ -171,7 +178,8 @@ macro_rules! declare_error_trait {
///
/// impl<'de> Deserialize<'de> for IpAddr {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// let s = try!(String::deserialize(deserializer));
/// s.parse().map_err(de::Error::custom)
@@ -195,6 +203,7 @@ macro_rules! declare_error_trait {
/// 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
/// expected type is the string.
#[cold]
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
}
@@ -212,6 +221,7 @@ macro_rules! declare_error_trait {
/// 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
/// expected value is a string.
#[cold]
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
}
@@ -225,12 +235,14 @@ macro_rules! declare_error_trait {
/// The `exp` argument provides information about what data was being
/// expected. For example `exp` might say that a tuple of size 6 was
/// expected.
#[cold]
fn invalid_length(len: usize, exp: &Expected) -> Self {
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
}
/// Raised when a `Deserialize` enum type received a variant with an
/// unrecognized name.
#[cold]
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() {
Error::custom(format_args!("unknown variant `{}`, there are no variants",
@@ -244,6 +256,7 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type received a field with an
/// unrecognized name.
#[cold]
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() {
Error::custom(format_args!("unknown field `{}`, there are no fields",
@@ -258,12 +271,14 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type expected to receive a required
/// field with a particular name but that field was not present in the
/// input.
#[cold]
fn missing_field(field: &'static str) -> Self {
Error::custom(format_args!("missing field `{}`", field))
}
/// Raised when a `Deserialize` struct type received more than one of the
/// same field.
#[cold]
fn duplicate_field(field: &'static str) -> Self {
Error::custom(format_args!("duplicate field `{}`", field))
}
@@ -298,7 +313,8 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// # }
/// #
/// 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))
/// }
@@ -422,7 +438,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # }
/// #
/// 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))
/// }
@@ -435,7 +452,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # use serde::de::{self, Unexpected};
/// #
/// # fn example<E>() -> Result<(), E>
/// # where E: de::Error
/// # where
/// # E: de::Error,
/// # {
/// # let v = true;
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
@@ -479,7 +497,7 @@ impl<'a> Display for Expected + 'a {
///
/// Additionally, Serde provides a procedural macro called `serde_derive` to
/// automatically generate `Deserialize` implementations for structs and enums
/// in your program. See the [codegen section of the manual][codegen] for how to
/// in your program. See the [derive section of the manual][derive] for how to
/// use this.
///
/// In rare cases it may be necessary to implement `Deserialize` manually for
@@ -492,8 +510,16 @@ impl<'a> Display for Expected + 'a {
/// provides an implementation of `Deserialize` for it.
///
/// [de]: https://docs.serde.rs/serde/de/index.html
/// [codegen]: https://serde.rs/codegen.html
/// [derive]: https://serde.rs/derive.html
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by `Self` when deserialized. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
pub trait Deserialize<'de>: Sized {
/// Deserialize this value from the given Serde deserializer.
///
@@ -513,7 +539,7 @@ pub trait Deserialize<'de>: Sized {
/// have been overwritten. Although whatever state that is will be
/// memory-safe.
///
/// This is generally useful when repeateadly deserializing values that
/// This is generally useful when repeatedly deserializing values that
/// are processed one at a time, where the value of `self` doesn't matter
/// when the next deserialization occurs.
///
@@ -549,19 +575,25 @@ pub trait Deserialize<'de>: Sized {
/// #
/// # trait Ignore {
/// 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>
/// where R: Read,
/// T: DeserializeOwned;
/// where
/// R: Read,
/// T: DeserializeOwned;
/// # }
/// ```
///
/// # Lifetime
///
/// The relationship between `Deserialize` and `DeserializeOwned` in trait
/// bounds is explained in more detail on the page [Understanding deserializer
/// lifetimes].
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
impl<T> DeserializeOwned for T
where
T: for<'de> Deserialize<'de>,
{
}
impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you
/// ever find yourself looking for a way to pass data into a `Deserialize` impl,
@@ -606,6 +638,14 @@ where
/// seed can be appeased by passing `std::marker::PhantomData` as a seed in the
/// case of stateless deserialization.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by `Self::Value` when deserialized. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example
///
/// Suppose we have JSON that looks like `[[1, 2], [3, 4, 5], [6]]` and we need
@@ -619,7 +659,7 @@ where
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess};
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
///
/// // A DeserializeSeed implementation that uses stateful deserialization to
/// // append array elements onto the end of an existing vector. The preexisting
@@ -629,7 +669,8 @@ where
/// struct ExtendVec<'a, T: 'a>(&'a mut Vec<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
/// // appends onto an existing vector but does not create any new data
@@ -637,14 +678,16 @@ where
/// type Value = ();
///
/// 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
/// // input.
/// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
///
/// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = ();
///
@@ -653,7 +696,8 @@ where
/// }
///
/// 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
/// // the existing vector.
@@ -672,7 +716,8 @@ where
/// struct FlattenedVecVisitor<T>(PhantomData<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
/// // contents of the inner arrays.
@@ -683,7 +728,8 @@ where
/// }
///
/// 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.
/// let mut vec = Vec::new();
@@ -699,7 +745,8 @@ where
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de>
/// # where
/// # D: Deserializer<'de>,
/// # {
/// let visitor = FlattenedVecVisitor(PhantomData);
/// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?;
@@ -737,10 +784,10 @@ where
/// A **data format** that can deserialize any data structure supported by
/// 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
/// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model.
/// 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
/// 29 possible types. Each method of the `Serializer` trait corresponds to one
/// of the types of the data model.
///
/// Implementations of `Deserialize` map themselves into this data model by
/// passing to the `Deserializer` a `Visitor` implementation that can receive
@@ -748,27 +795,27 @@ where
///
/// The types that make up the Serde data model are:
///
/// - **12 primitive types**
/// - **14 primitive types**
/// - bool
/// - i8, i16, i32, i64
/// - u8, u16, u32, u64
/// - i8, i16, i32, i64, i128
/// - u8, u16, u32, u64, u128
/// - f32, f64
/// - char
/// - **string**
/// - UTF-8 bytes with a length and no null terminator.
/// - When serializing, all strings are handled equally. When deserializing,
/// there are three flavors of strings: transient, owned, and borrowed.
/// - **byte array** - [u8]
/// - Similar to strings, during deserialization byte arrays can be transient,
/// owned, or borrowed.
/// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be
/// transient, owned, or borrowed.
/// - **option**
/// - Either none or some value.
/// - **unit**
/// - The type of `()` in Rust. It represents an anonymous value containing no
/// data.
/// - The type of `()` in Rust. It represents an anonymous value containing
/// no data.
/// - **unit_struct**
/// - For example `struct Unit` or `PhantomData<T>`. It represents a named value
/// containing no data.
/// - For example `struct Unit` or `PhantomData<T>`. It represents a named
/// value containing no data.
/// - **unit_variant**
/// - For example the `E::A` and `E::B` in `enum E { A, B }`.
/// - **newtype_struct**
@@ -776,14 +823,15 @@ where
/// - **newtype_variant**
/// - For example the `E::N` in `enum E { N(u8) }`.
/// - **seq**
/// - A variably sized heterogeneous sequence of values, for example `Vec<T>` or
/// `HashSet<T>`. When serializing, the length may or may not be known before
/// iterating through all the data. When deserializing, the length is determined
/// by looking at the serialized data.
/// - A variably sized heterogeneous sequence of values, for example `Vec<T>`
/// or `HashSet<T>`. When serializing, the length may or may not be known
/// before iterating through all the data. When deserializing, the length
/// is determined by looking at the serialized data.
/// - **tuple**
/// - A statically sized heterogeneous sequence of values for which the length
/// will be known at deserialization time without looking at the serialized
/// data, for example `(u8,)` or `(String, u64, Vec<T>)` or `[u64; 10]`.
/// - A statically sized heterogeneous sequence of values for which the
/// length will be known at deserialization time without looking at the
/// serialized data, for example `(u8,)` or `(String, u64, Vec<T>)` or
/// `[u64; 10]`.
/// - **tuple_struct**
/// - A named tuple, for example `struct Rgb(u8, u8, u8)`.
/// - **tuple_variant**
@@ -791,9 +839,9 @@ where
/// - **map**
/// - A heterogeneous key-value pairing, for example `BTreeMap<K, V>`.
/// - **struct**
/// - A heterogeneous key-value pairing in which the keys are strings and will be
/// known at deserialization time without looking at the serialized data, for
/// example `struct S { r: u8, g: u8, b: u8 }`.
/// - A heterogeneous key-value pairing in which the keys are strings and
/// will be known at deserialization time without looking at the serialized
/// data, for example `struct S { r: u8, g: u8, b: u8 }`.
/// - **struct_variant**
/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
///
@@ -808,7 +856,8 @@ where
/// type it sees in the input. JSON uses this approach when deserializing
/// `serde_json::Value` which is an enum that can represent any JSON
/// document. Without knowing what is in a JSON document, we can deserialize
/// it to `serde_json::Value` by going through `Deserializer::deserialize_any`.
/// it to `serde_json::Value` by going through
/// `Deserializer::deserialize_any`.
///
/// 2. The various `deserialize_*` methods. Non-self-describing formats like
/// Bincode need to be told what is in the input in order to deserialize it.
@@ -818,10 +867,28 @@ where
/// `Deserializer::deserialize_any`.
///
/// When implementing `Deserialize`, you should avoid relying on
/// `Deserializer::deserialize_any` unless you need to be told by the Deserializer
/// what type is in the input. Know that relying on `Deserializer::deserialize_any`
/// means your data type will be able to deserialize from self-describing
/// formats only, ruling out Bincode and many others.
/// `Deserializer::deserialize_any` unless you need to be told by the
/// Deserializer what type is in the input. Know that relying on
/// `Deserializer::deserialize_any` means your data type will be able to
/// deserialize from self-describing formats only, ruling out Bincode and many
/// others.
///
/// [Serde data model]: https://serde.rs/data-model.html
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed from the input when deserializing. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website contains example code for
/// a basic JSON `Deserializer`.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Deserializer<'de>: Sized {
/// The error type that can be returned if some error occurs during
/// deserialization.
@@ -865,6 +932,20 @@ pub trait Deserializer<'de>: Sized {
where
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.
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
@@ -885,6 +966,20 @@ pub trait Deserializer<'de>: Sized {
where
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.
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
@@ -1084,7 +1179,8 @@ pub trait Deserializer<'de>: Sized {
///
/// impl<'de> Deserialize<'de> for Timestamp {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// if deserializer.is_human_readable() {
/// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z".
@@ -1116,6 +1212,16 @@ pub trait Deserializer<'de>: Sized {
/// This trait represents a visitor that walks through a deserializer.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the requirement for lifetime of data
/// that may be borrowed by `Self::Value`. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example
///
/// ```rust
/// # use std::fmt;
/// #
@@ -1135,7 +1241,8 @@ pub trait Deserializer<'de>: Sized {
/// }
///
/// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
/// where E: de::Error
/// where
/// E: de::Error,
/// {
/// if s.len() >= self.min {
/// Ok(s.to_owned())
@@ -1229,6 +1336,20 @@ pub trait Visitor<'de>: Sized {
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 default implementation forwards to [`visit_u64`].
@@ -1275,6 +1396,20 @@ pub trait Visitor<'de>: Sized {
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 default implementation forwards to [`visit_f64`].
@@ -1506,6 +1641,15 @@ pub trait Visitor<'de>: Sized {
let _ = data;
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(())
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -1514,6 +1658,21 @@ pub trait Visitor<'de>: Sized {
///
/// This is a trait that a `Deserializer` passes to a `Visitor` implementation,
/// which deserializes each item in a sequence.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by deserialized sequence elements. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SeqAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SeqAccess<'de> {
/// The error type that can be returned if some error occurs during
/// deserialization.
@@ -1581,6 +1740,21 @@ where
/// Provides a `Visitor` access to each entry of a map in the input.
///
/// This is a trait that a `Deserializer` passes to a `Visitor` implementation.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by deserialized map entries. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `MapAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait MapAccess<'de> {
/// The error type that can be returned if some error occurs during
/// deserialization.
@@ -1758,6 +1932,21 @@ where
///
/// `EnumAccess` is created by the `Deserializer` and passed to the
/// `Visitor` in order to identify which variant of an enum to deserialize.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by the deserialized enum variant. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `EnumAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait EnumAccess<'de>: Sized {
/// The error type that can be returned if some error occurs during
/// deserialization.
@@ -1790,6 +1979,21 @@ pub trait EnumAccess<'de>: Sized {
/// `VariantAccess` is a visitor that is created by the `Deserializer` and
/// passed to the `Deserialize` to deserialize the content of a particular enum
/// variant.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by the deserialized enum variant. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `VariantAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait VariantAccess<'de>: Sized {
/// The error type that can be returned if some error occurs during
/// deserialization. Must match the error type of our `EnumAccess`.
@@ -1815,15 +2019,18 @@ pub trait VariantAccess<'de>: Sized {
/// }
/// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de>
/// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// # }
/// ```
@@ -1850,7 +2057,8 @@ pub trait VariantAccess<'de>: Sized {
/// # }
/// #
/// 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.
/// let unexp = Unexpected::UnitVariant;
@@ -1858,11 +2066,13 @@ pub trait VariantAccess<'de>: Sized {
/// }
/// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// # }
/// ```
@@ -1903,13 +2113,17 @@ pub trait VariantAccess<'de>: Sized {
/// # }
/// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de>
/// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// fn tuple_variant<V>(self,
/// _len: usize,
/// _visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// fn tuple_variant<V>(
/// self,
/// _len: usize,
/// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// {
/// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant;
@@ -1917,7 +2131,8 @@ pub trait VariantAccess<'de>: Sized {
/// }
/// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// # }
/// ```
@@ -1945,17 +2160,22 @@ pub trait VariantAccess<'de>: Sized {
/// # }
/// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de>
/// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// #
/// fn struct_variant<V>(self,
/// _fields: &'static [&'static str],
/// _visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// fn struct_variant<V>(
/// self,
/// _fields: &'static [&'static str],
/// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// {
/// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant;
@@ -1977,6 +2197,16 @@ pub trait VariantAccess<'de>: Sized {
/// Converts an existing value into a `Deserializer` from which other values can
/// be deserialized.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed from the resulting `Deserializer`. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example
///
/// ```rust
/// #[macro_use]
/// extern crate serde_derive;
+150 -58
View File
@@ -37,10 +37,26 @@
use lib::*;
use self::private::{First, Second};
use de::{self, Expected, IntoDeserializer, SeqAccess};
use private::de::size_hint;
use ser;
use self::private::{First, Second};
////////////////////////////////////////////////////////////////////////////////
// For structs that contain a PhantomData. We do not want the trait
// bound `E: Clone` inferred by derive(Clone).
macro_rules! impl_copy_clone {
($ty:ident $(<$lifetime:tt>)*) => {
impl<$($lifetime,)* E> Copy for $ty<$($lifetime,)* E> {}
impl<$($lifetime,)* E> Clone for $ty<$($lifetime,)* E> {
fn clone(&self) -> Self {
*self
}
}
};
}
////////////////////////////////////////////////////////////////////////////////
@@ -58,6 +74,7 @@ type ErrorImpl = ();
impl de::Error for Error {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -68,6 +85,7 @@ impl de::Error for Error {
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -78,6 +96,7 @@ impl de::Error for Error {
}
impl ser::Error for Error {
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -121,11 +140,13 @@ where
}
/// A deserializer holding a `()`.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct UnitDeserializer<E> {
marker: PhantomData<E>,
}
impl_copy_clone!(UnitDeserializer);
impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
where
E: de::Error,
@@ -133,9 +154,9 @@ where
type Error = E;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map
struct enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -155,16 +176,60 @@ where
////////////////////////////////////////////////////////////////////////////////
/// A deserializer that cannot be instantiated.
#[cfg(feature = "unstable")]
pub struct NeverDeserializer<E> {
never: !,
marker: PhantomData<E>,
}
#[cfg(feature = "unstable")]
impl<'de, E> IntoDeserializer<'de, E> for !
where
E: de::Error,
{
type Deserializer = NeverDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
#[cfg(feature = "unstable")]
impl<'de, E> de::Deserializer<'de> for NeverDeserializer<E>
where
E: de::Error,
{
type Error = E;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
self.never
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! primitive_deserializer {
($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => {
#[doc = "A deserializer holding"]
#[doc = $doc]
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct $name<E> {
value: $ty,
marker: PhantomData<E>
}
impl_copy_clone!($name);
impl<'de, E> IntoDeserializer<'de, E> for $ty
where
E: de::Error,
@@ -186,9 +251,9 @@ macro_rules! primitive_deserializer {
type Error = E;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str
string bytes byte_buf option unit unit_struct newtype_struct seq
tuple tuple_struct map struct enum identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -215,13 +280,20 @@ primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
serde_if_integer128! {
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
}
/// A deserializer holding a `u32`.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct U32Deserializer<E> {
value: u32,
marker: PhantomData<E>,
}
impl_copy_clone!(U32Deserializer);
impl<'de, E> IntoDeserializer<'de, E> for u32
where
E: de::Error,
@@ -243,9 +315,9 @@ where
type Error = E;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -288,12 +360,14 @@ where
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&str`.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct StrDeserializer<'a, E> {
value: &'a str,
marker: PhantomData<E>,
}
impl_copy_clone!(StrDeserializer<'de>);
impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str
where
E: de::Error,
@@ -336,9 +410,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
@@ -361,12 +435,14 @@ where
/// A deserializer holding a `&str` with a lifetime tied to another
/// deserializer.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct BorrowedStrDeserializer<'de, E> {
value: &'de str,
marker: PhantomData<E>,
}
impl_copy_clone!(BorrowedStrDeserializer<'de>);
impl<'de, E> BorrowedStrDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given string.
pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> {
@@ -405,9 +481,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
@@ -430,12 +506,22 @@ where
/// A deserializer holding a `String`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct StringDeserializer<E> {
value: String,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<E> Clone for StringDeserializer<E> {
fn clone(&self) -> Self {
StringDeserializer {
value: self.value.clone(),
marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> IntoDeserializer<'de, E> for String
where
@@ -480,9 +566,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
@@ -506,12 +592,22 @@ where
/// A deserializer holding a `Cow<str>`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, E> Clone for CowStrDeserializer<'a, E> {
fn clone(&self) -> Self {
CowStrDeserializer {
value: self.value.clone(),
marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
where
@@ -559,9 +655,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
@@ -585,12 +681,14 @@ where
/// A deserializer holding a `&[u8]` with a lifetime tied to another
/// deserializer.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct BorrowedBytesDeserializer<'de, E> {
value: &'de [u8],
marker: PhantomData<E>,
}
impl_copy_clone!(BorrowedBytesDeserializer<'de>);
impl<'de, E> BorrowedBytesDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given byte slice.
pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> {
@@ -615,9 +713,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any enum
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any enum
}
}
@@ -652,11 +750,8 @@ where
{
/// Check for remaining elements after passing a `SeqDeserializer` to
/// `Visitor::visit_seq`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0;
while self.iter.next().is_some() {
remaining += 1;
}
pub fn end(self) -> Result<(), E> {
let remaining = self.iter.count();
if remaining == 0 {
Ok(())
} else {
@@ -688,9 +783,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
@@ -803,9 +898,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
@@ -849,11 +944,8 @@ where
{
/// Check for remaining elements after passing a `MapDeserializer` to
/// `Visitor::visit_map`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0;
while self.iter.next().is_some() {
remaining += 1;
}
pub fn end(self) -> Result<(), E> {
let remaining = self.iter.count();
if remaining == 0 {
Ok(())
} else {
@@ -920,9 +1012,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct tuple_struct map struct
enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct tuple_struct map
struct enum identifier ignored_any
}
}
@@ -1062,9 +1154,9 @@ where
type Error = E;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct tuple_struct map struct
enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct tuple_struct map
struct enum identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -1210,9 +1302,9 @@ where
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
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;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::Vec;
mod string {
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)*) => {};
}
+63 -39
View File
@@ -52,6 +52,8 @@
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//! definition.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//! *(deserialization only)*
@@ -69,6 +71,7 @@
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
@@ -79,21 +82,31 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.27")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.72")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy",
allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist,
needless_pass_by_value, type_complexity, unreadable_literal,
zero_prefixed_literal))]
#![cfg_attr(
feature = "cargo-clippy",
allow(
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
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
@@ -104,6 +117,7 @@
// simplifies some macros
invalid_upcast_comparisons,
// things are often more readable this way
decimal_literal_representation,
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
@@ -111,37 +125,40 @@
stutter,
use_self,
// not practical
indexing_slicing,
many_single_char_names,
missing_docs_in_private_items,
similar_names,
// alternative is not stable
empty_enum,
use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
//
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "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`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
mod core {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))]
pub use core::*;
#[cfg(feature = "std")]
pub use std::*;
}
pub use self::core::{cmp, iter, mem, ops, slice, str};
pub use self::core::{isize, i16, i32, i64, i8};
pub use self::core::{usize, u16, u32, u64, u8};
pub use self::core::{cmp, iter, mem, num, slice, str};
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::clone::{self, Clone};
@@ -149,43 +166,44 @@ mod lib {
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::ops::Range;
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
#[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::borrow::{Cow, ToOwned};
#[cfg(feature = "std")]
pub use std::string::String;
pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::string::{String, ToString};
#[cfg(feature = "std")]
pub use std::vec::Vec;
pub use std::string::String;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::vec::Vec;
#[cfg(feature = "std")]
pub use std::boxed::Box;
pub use std::vec::Vec;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::boxed::Box;
#[cfg(feature = "std")]
pub use std::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;
pub use alloc::rc::{Rc, Weak as RcWeak};
#[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;
pub use std::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::sync::{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")))]
pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::{error, net};
@@ -203,12 +221,15 @@ mod lib {
#[cfg(feature = "std")]
pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(feature = "unstable")]
pub use core::nonzero::{NonZero, Zeroable};
#[cfg(any(core_duration, feature = "std"))]
pub use self::core::time::Duration;
#[cfg(range_inclusive)]
pub use self::core::ops::RangeInclusive;
}
////////////////////////////////////////////////////////////////////////////////
@@ -216,13 +237,16 @@ mod lib {
#[macro_use]
mod macros;
pub mod ser;
#[macro_use]
mod integer128;
pub mod de;
pub mod ser;
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
+27 -13
View File
@@ -31,21 +31,23 @@
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # {
/// # unimplemented!()
/// # }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// where
/// V: Visitor<'de>,
/// {
/// self.deserialize_any(visitor)
/// }
/// #
/// # forward_to_deserialize_any! {
/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// # byte_buf option unit unit_struct newtype_struct seq tuple
/// # i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// # bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any
/// # }
/// # }
@@ -69,7 +71,8 @@
/// # type Error = value::Error;
/// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// where
/// V: Visitor<'de>,
/// {
/// /* ... */
/// # let _ = visitor;
@@ -77,8 +80,8 @@
/// }
///
/// forward_to_deserialize_any! {
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple
/// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct map struct enum identifier ignored_any
/// }
/// }
@@ -105,16 +108,17 @@
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q>
/// # where
/// # W: Visitor<'q>,
/// # {
/// # unimplemented!()
/// # }
/// #
/// forward_to_deserialize_any! {
/// <W: Visitor<'q>>
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
/// map struct enum identifier ignored_any
/// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
/// bytes byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct map struct enum identifier ignored_any
/// }
/// # }
/// #
@@ -124,7 +128,7 @@
/// [`Deserializer`]: trait.Deserializer.html
/// [`Visitor`]: de/trait.Visitor.html
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
#[macro_export]
#[macro_export(local_inner_macros)]
macro_rules! forward_to_deserialize_any {
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
$(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})*
@@ -153,7 +157,7 @@ macro_rules! forward_to_deserialize_any_method {
}
#[doc(hidden)]
#[macro_export]
#[macro_export(local_inner_macros)]
macro_rules! forward_to_deserialize_any_helper {
(bool<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()}
@@ -170,6 +174,11 @@ macro_rules! forward_to_deserialize_any_helper {
(i64<$l:tt, $v:ident>) => {
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>) => {
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>) => {
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>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
};
+981 -104
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -32,7 +32,7 @@ macro_rules! __private_deserialize {
/// Used only by Serde doc tests. Not public API.
#[doc(hidden)]
#[macro_export]
#[macro_export(local_inner_macros)]
macro_rules! __serialize_unimplemented {
($($func:ident)*) => {
$(
@@ -52,7 +52,7 @@ macro_rules! __serialize_unimplemented_method {
}
#[doc(hidden)]
#[macro_export]
#[macro_export(local_inner_macros)]
macro_rules! __serialize_unimplemented_helper {
(bool) => {
__serialize_unimplemented_method!(serialize_bool(bool) -> Ok);
+1 -1
View File
@@ -8,5 +8,5 @@
mod macros;
pub mod ser;
pub mod de;
pub mod ser;
+321 -14
View File
@@ -11,7 +11,9 @@ use lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[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.
/// Not public API.
@@ -58,10 +60,11 @@ enum Unsupported {
ByteArray,
Optional,
Unit,
#[cfg(any(feature = "std", feature = "alloc"))]
UnitStruct,
Sequence,
Tuple,
TupleStruct,
#[cfg(not(any(feature = "std", feature = "alloc")))]
Enum,
}
@@ -76,10 +79,11 @@ impl Display for Unsupported {
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
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::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "alloc")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
@@ -459,7 +463,7 @@ mod content {
}
#[derive(Debug)]
enum Content {
pub enum Content {
Bool(bool),
U8(u8),
@@ -584,12 +588,12 @@ mod content {
}
}
struct ContentSerializer<E> {
pub struct ContentSerializer<E> {
error: PhantomData<E>,
}
impl<E> ContentSerializer<E> {
fn new() -> Self {
pub fn new() -> Self {
ContentSerializer { error: PhantomData }
}
}
@@ -804,7 +808,7 @@ mod content {
}
}
struct SerializeSeq<E> {
pub struct SerializeSeq<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
@@ -830,7 +834,7 @@ mod content {
}
}
struct SerializeTuple<E> {
pub struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
@@ -856,7 +860,7 @@ mod content {
}
}
struct SerializeTupleStruct<E> {
pub struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
@@ -883,7 +887,7 @@ mod content {
}
}
struct SerializeTupleVariant<E> {
pub struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: u32,
variant: &'static str,
@@ -917,7 +921,7 @@ mod content {
}
}
struct SerializeMap<E> {
pub struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
@@ -943,7 +947,8 @@ mod content {
where
T: Serialize,
{
let key = self.key
let key = self
.key
.take()
.expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
@@ -967,7 +972,7 @@ mod content {
}
}
struct SerializeStruct<E> {
pub struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
@@ -994,7 +999,7 @@ mod content {
}
}
struct SerializeStructVariant<E> {
pub struct SerializeStructVariant<E> {
name: &'static str,
variant_index: u32,
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(())
}
}
+133 -21
View File
@@ -8,10 +8,7 @@
use lib::*;
use ser::{Serialize, SerializeTuple, Serializer};
#[cfg(feature = "std")]
use ser::Error;
use ser::{Error, Serialize, SerializeTuple, Serializer};
////////////////////////////////////////////////////////////////////////////////
@@ -44,6 +41,11 @@ primitive_impl!(f32, serialize_f32);
primitive_impl!(f64, serialize_f64);
primitive_impl!(char, serialize_char);
serde_if_integer128! {
primitive_impl!(i128, serialize_i128);
primitive_impl!(u128, serialize_u128);
}
////////////////////////////////////////////////////////////////////////////////
impl Serialize for str {
@@ -67,6 +69,15 @@ impl Serialize for String {
}
}
impl<'a> Serialize for fmt::Arguments<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(self)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
@@ -216,8 +227,7 @@ seq_impl!(VecDeque<T>);
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<Idx> Serialize for ops::Range<Idx>
impl<Idx> Serialize for Range<Idx>
where
Idx: Serialize,
{
@@ -235,6 +245,25 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(range_inclusive)]
impl<Idx> Serialize for RangeInclusive<Idx>
where
Idx: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
try!(state.serialize_field("start", &self.start()));
try!(state.serialize_field("end", &self.end()));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
impl Serialize for () {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -245,6 +274,16 @@ impl Serialize for () {
}
}
#[cfg(feature = "unstable")]
impl Serialize for ! {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
*self
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
@@ -320,8 +359,12 @@ map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
////////////////////////////////////////////////////////////////////////////////
macro_rules! deref_impl {
($($desc:tt)+) => {
impl $($desc)+ {
(
$(#[doc = $doc:tt])*
<$($desc:tt)+
) => {
$(#[doc = $doc])*
impl <$($desc)+ {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -340,29 +383,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);
#[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")))]
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"))]
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T>
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for RcWeak<T>
where
T: Serialize + Zeroable + Clone,
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
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>
where
T: Serialize + Copy,
@@ -383,7 +493,10 @@ where
where
S: Serializer,
{
self.borrow().serialize(serializer)
match self.try_borrow() {
Ok(value) => value.serialize(serializer),
Err(_) => Err(S::Error::custom("already mutably borrowed")),
}
}
}
@@ -441,7 +554,7 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
#[cfg(any(core_duration, feature = "std"))]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -464,7 +577,8 @@ impl Serialize for SystemTime {
S: Serializer,
{
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");
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
@@ -494,11 +608,9 @@ macro_rules! serialize_display_bounded_length {
// write! only provides fmt::Formatter to Display implementations, which
// has methods write_str and write_char but no method to write arbitrary
// bytes. Therefore `written` must be valid UTF-8.
let written_str = unsafe {
str::from_utf8_unchecked(written)
};
let written_str = unsafe { str::from_utf8_unchecked(written) };
$serializer.serialize_str(written_str)
}}
}};
}
#[cfg(feature = "std")]
+4 -2
View File
@@ -10,8 +10,10 @@
use lib::*;
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
use ser::{
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
};
/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
+310 -108
View File
@@ -24,8 +24,7 @@
//!
//! Additionally, Serde provides a procedural macro called [`serde_derive`] to
//! automatically generate [`Serialize`] implementations for structs and enums
//! in your program. See the [codegen section of the manual] for how to use
//! this.
//! in your program. See the [derive section of the manual] for how to use this.
//!
//! In rare cases it may be necessary to implement [`Serialize`] manually for
//! some type in your program. See the [Implementing `Serialize`] section of the
@@ -48,15 +47,15 @@
//!
//! - **Primitive types**:
//! - bool
//! - i8, i16, i32, i64, isize
//! - u8, u16, u32, u64, usize
//! - i8, i16, i32, i64, i128, isize
//! - u8, u16, u32, u64, u128, usize
//! - f32, f64
//! - char
//! - str
//! - &T and &mut T
//! - **Compound types**:
//! - [T]
//! - [T; 0] through [T; 32]
//! - \[T\]
//! - \[T; 0\] through \[T; 32\]
//! - tuples up to size 16
//! - **Common standard library types**:
//! - String
@@ -81,7 +80,6 @@
//! - LinkedList\<T\>
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **FFI types**:
//! - CStr
//! - CString
@@ -93,7 +91,9 @@
//! - Path
//! - PathBuf
//! - Range\<T\>
//! - NonZero\<T\> (unstable)
//! - RangeInclusive\<T\>
//! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
@@ -111,7 +111,7 @@
//! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json
//! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml
//! [codegen section of the manual]: https://serde.rs/codegen.html
//! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats
use lib::*;
@@ -128,6 +128,13 @@ macro_rules! declare_error_trait {
/// Trait used by `Serialize` implementations to generically construct
/// errors belonging to the `Serializer` against which they are
/// currently running.
///
/// # Example implementation
///
/// The [example data format] presented on the website shows an error
/// type appropriate for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Error: Sized $(+ $($supertrait)::+)* {
/// Used when a [`Serialize`] implementation encounters any error
/// while serializing a type.
@@ -151,7 +158,8 @@ macro_rules! declare_error_trait {
///
/// impl Serialize for Path {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match self.to_str() {
/// Some(s) => serializer.serialize_str(s),
@@ -187,7 +195,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
///
/// Additionally, Serde provides a procedural macro called [`serde_derive`] to
/// automatically generate `Serialize` implementations for structs and enums in
/// your program. See the [codegen section of the manual] for how to use this.
/// your program. See the [derive section of the manual] for how to use this.
///
/// In rare cases it may be necessary to implement `Serialize` manually for some
/// type in your program. See the [Implementing `Serialize`] section of the
@@ -202,7 +210,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
/// [`serde_derive`]: https://crates.io/crates/serde_derive
/// [codegen section of the manual]: https://serde.rs/codegen.html
/// [derive section of the manual]: https://serde.rs/derive.html
/// [ser]: https://docs.serde.rs/serde/ser/index.html
pub trait Serialize {
/// Serialize this value into the given Serde serializer.
@@ -211,7 +219,7 @@ pub trait Serialize {
/// information about how to implement this method.
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct};
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
///
/// struct Person {
/// name: String,
@@ -222,7 +230,8 @@ pub trait Serialize {
/// // This is what #[derive(Serialize)] would generate.
/// impl Serialize for Person {
/// 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)?;
/// s.serialize_field("name", &self.name)?;
@@ -243,37 +252,37 @@ pub trait Serialize {
/// 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
/// model, which is a way to categorize every Rust data structure into one of 27
/// possible types. Each method of the `Serializer` trait corresponds to one of
/// the types of the data model.
/// 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 29 possible types. Each method of the `Serializer` trait corresponds to
/// one of the types of the data model.
///
/// Implementations of `Serialize` map themselves into this data model by
/// invoking exactly one of the `Serializer` methods.
///
/// The types that make up the Serde data model are:
///
/// - **12 primitive types**
/// - **14 primitive types**
/// - bool
/// - i8, i16, i32, i64
/// - u8, u16, u32, u64
/// - i8, i16, i32, i64, i128
/// - u8, u16, u32, u64, u128
/// - f32, f64
/// - char
/// - **string**
/// - UTF-8 bytes with a length and no null terminator.
/// - When serializing, all strings are handled equally. When deserializing,
/// there are three flavors of strings: transient, owned, and borrowed.
/// - **byte array** - [u8]
/// - Similar to strings, during deserialization byte arrays can be transient,
/// owned, or borrowed.
/// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be
/// transient, owned, or borrowed.
/// - **option**
/// - Either none or some value.
/// - **unit**
/// - The type of `()` in Rust. It represents an anonymous value containing no
/// data.
/// - The type of `()` in Rust. It represents an anonymous value containing
/// no data.
/// - **unit_struct**
/// - For example `struct Unit` or `PhantomData<T>`. It represents a named value
/// containing no data.
/// - For example `struct Unit` or `PhantomData<T>`. It represents a named
/// value containing no data.
/// - **unit_variant**
/// - For example the `E::A` and `E::B` in `enum E { A, B }`.
/// - **newtype_struct**
@@ -281,14 +290,15 @@ pub trait Serialize {
/// - **newtype_variant**
/// - For example the `E::N` in `enum E { N(u8) }`.
/// - **seq**
/// - A variably sized heterogeneous sequence of values, for example `Vec<T>` or
/// `HashSet<T>`. When serializing, the length may or may not be known before
/// iterating through all the data. When deserializing, the length is determined
/// by looking at the serialized data.
/// - A variably sized heterogeneous sequence of values, for example
/// `Vec<T>` or `HashSet<T>`. When serializing, the length may or may not
/// be known before iterating through all the data. When deserializing,
/// the length is determined by looking at the serialized data.
/// - **tuple**
/// - A statically sized heterogeneous sequence of values for which the length
/// will be known at deserialization time without looking at the serialized
/// data, for example `(u8,)` or `(String, u64, Vec<T>)` or `[u64; 10]`.
/// - A statically sized heterogeneous sequence of values for which the
/// length will be known at deserialization time without looking at the
/// serialized data, for example `(u8,)` or `(String, u64, Vec<T>)` or
/// `[u64; 10]`.
/// - **tuple_struct**
/// - A named tuple, for example `struct Rgb(u8, u8, u8)`.
/// - **tuple_variant**
@@ -296,9 +306,9 @@ pub trait Serialize {
/// - **map**
/// - A heterogeneous key-value pairing, for example `BTreeMap<K, V>`.
/// - **struct**
/// - A heterogeneous key-value pairing in which the keys are strings and will be
/// known at deserialization time without looking at the serialized data, for
/// example `struct S { r: u8, g: u8, b: u8 }`.
/// - A heterogeneous key-value pairing in which the keys are strings and
/// will be known at deserialization time without looking at the
/// serialized data, for example `struct S { r: u8, g: u8, b: u8 }`.
/// - **struct_variant**
/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
///
@@ -308,6 +318,15 @@ pub trait Serialize {
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as
/// output.
///
/// [Serde data model]: https://serde.rs/data-model.html
///
/// # Example implementation
///
/// The [example data format] presented on the website contains example code for
/// a basic JSON `Serializer`.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Serializer: Sized {
/// The output type produced by this `Serializer` during successful
/// serialization. Most serializers that produce text or binary output
@@ -376,7 +395,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for bool {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_bool(*self)
/// }
@@ -402,7 +422,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i8(*self)
/// }
@@ -428,7 +449,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i16(*self)
/// }
@@ -454,7 +476,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i32(*self)
/// }
@@ -476,7 +499,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i64(*self)
/// }
@@ -486,6 +510,37 @@ pub trait Serializer: Sized {
/// ```
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.
///
/// If the format does not differentiate between `u8` and `u64`, a
@@ -502,7 +557,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u8(*self)
/// }
@@ -528,7 +584,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u16(*self)
/// }
@@ -554,7 +611,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u32(*self)
/// }
@@ -576,7 +634,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u64(*self)
/// }
@@ -586,6 +645,37 @@ pub trait Serializer: Sized {
/// ```
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.
///
/// If the format does not differentiate between `f32` and `f64`, a
@@ -602,7 +692,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for f32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_f32(*self)
/// }
@@ -624,7 +715,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for f64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_f64(*self)
/// }
@@ -649,7 +741,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for char {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_char(*self)
/// }
@@ -671,7 +764,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for str {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_str(self)
/// }
@@ -736,10 +830,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None};
/// #
/// impl<T> Serialize for Option<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// Some(ref value) => serializer.serialize_some(value),
@@ -769,10 +865,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None};
/// #
/// impl<T> Serialize for Option<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// Some(ref value) => serializer.serialize_some(value),
@@ -801,7 +899,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for () {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_unit()
/// }
@@ -822,7 +921,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Nothing {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_unit_struct("Nothing")
/// }
@@ -846,7 +946,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::A => serializer.serialize_unit_variant("E", 0, "A"),
@@ -875,7 +976,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Millimeters {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// }
@@ -905,7 +1007,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s),
@@ -955,10 +1058,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
///
/// impl<T> Serialize for Vec<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// 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()))?;
/// for element in self {
@@ -987,12 +1092,14 @@ pub trait Serializer: Sized {
/// # struct Tuple3<A, B, C>(A, B, C);
/// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize,
/// B: Serialize,
/// C: Serialize
/// where
/// A: Serialize,
/// B: Serialize,
/// C: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?;
@@ -1004,14 +1111,15 @@ pub trait Serializer: Sized {
/// ```
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
///
/// const VRAM_SIZE: usize = 386;
/// struct Vram([u16; VRAM_SIZE]);
///
/// impl Serialize for Vram {
/// 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)?;
/// for element in &self.0[..] {
@@ -1031,13 +1139,14 @@ pub trait Serializer: Sized {
/// of data fields that will be serialized.
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct};
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
///
/// struct Rgb(u8, u8, u8);
///
/// impl Serialize for Rgb {
/// 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)?;
/// ts.serialize_field(&self.0)?;
@@ -1062,7 +1171,7 @@ pub trait Serializer: Sized {
/// and the `len` is the number of data fields that will be serialized.
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant};
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
///
/// enum E {
/// T(u8, u8),
@@ -1071,7 +1180,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::T(ref a, ref b) => {
@@ -1129,11 +1239,13 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeMap};
///
/// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize,
/// V: Serialize
/// where
/// K: Serialize,
/// V: Serialize,
/// {
/// 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()))?;
/// for (k, v) in self {
@@ -1153,7 +1265,7 @@ pub trait Serializer: Sized {
/// data fields that will be serialized.
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct};
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
///
/// struct Rgb {
/// r: u8,
@@ -1163,7 +1275,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Rgb {
/// 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)?;
/// rgb.serialize_field("r", &self.r)?;
@@ -1188,18 +1301,23 @@ pub trait Serializer: Sized {
/// and the `len` is the number of data fields that will be serialized.
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStructVariant};
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
///
/// enum E {
/// S { r: u8, g: u8, b: u8 }
/// S { r: u8, g: u8, b: u8 },
/// }
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::S { ref r, ref g, ref b } => {
/// E::S {
/// ref r,
/// ref g,
/// ref b,
/// } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?;
@@ -1233,7 +1351,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for SecretlyOneHigher {
/// 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))
/// }
@@ -1261,8 +1380,8 @@ pub trait Serializer: Sized {
/// method.
///
/// ```rust
/// use std::collections::BTreeSet;
/// use serde::{Serialize, Serializer};
/// use std::collections::BTreeSet;
///
/// struct MapToUnit {
/// keys: BTreeSet<i32>,
@@ -1271,7 +1390,8 @@ pub trait Serializer: Sized {
/// // Serializes as a map in which the values are all unit.
/// impl Serialize for MapToUnit {
/// 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, ())))
/// }
@@ -1311,7 +1431,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
@@ -1351,7 +1472,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
@@ -1392,7 +1514,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Timestamp {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// if serializer.is_human_readable() {
/// // Serialize to a human-readable string "2015-05-15T17:01:00Z".
@@ -1419,6 +1542,8 @@ pub trait Serializer: Sized {
/// Returned from `Serializer::serialize_seq`.
///
/// # Example use
///
/// ```rust
/// # use std::marker::PhantomData;
/// #
@@ -1441,10 +1566,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
///
/// impl<T> Serialize for Vec<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// 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()))?;
/// for element in self {
@@ -1454,6 +1581,13 @@ pub trait Serializer: Sized {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeSeq` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeSeq {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
@@ -1472,6 +1606,8 @@ pub trait SerializeSeq {
/// Returned from `Serializer::serialize_tuple`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
///
@@ -1484,12 +1620,14 @@ pub trait SerializeSeq {
/// # struct Tuple3<A, B, C>(A, B, C);
/// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize,
/// B: Serialize,
/// C: Serialize
/// where
/// A: Serialize,
/// B: Serialize,
/// C: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?;
@@ -1528,10 +1666,12 @@ pub trait SerializeSeq {
/// # }
/// #
/// # impl<T> Serialize for Array<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut seq = serializer.serialize_tuple(16)?;
/// for element in self {
@@ -1541,6 +1681,13 @@ pub trait SerializeSeq {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeTuple` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeTuple {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
@@ -1559,14 +1706,17 @@ pub trait SerializeTuple {
/// Returned from `Serializer::serialize_tuple_struct`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct};
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
///
/// struct Rgb(u8, u8, u8);
///
/// impl Serialize for Rgb {
/// 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)?;
/// ts.serialize_field(&self.0)?;
@@ -1576,6 +1726,13 @@ pub trait SerializeTuple {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeTupleStruct` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeTupleStruct {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
@@ -1594,8 +1751,10 @@ pub trait SerializeTupleStruct {
/// Returned from `Serializer::serialize_tuple_variant`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant};
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
///
/// enum E {
/// T(u8, u8),
@@ -1604,7 +1763,8 @@ pub trait SerializeTupleStruct {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::T(ref a, ref b) => {
@@ -1624,6 +1784,13 @@ pub trait SerializeTupleStruct {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeTupleVariant` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeTupleVariant {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
@@ -1642,6 +1809,8 @@ pub trait SerializeTupleVariant {
/// Returned from `Serializer::serialize_map`.
///
/// # Example use
///
/// ```rust
/// # use std::marker::PhantomData;
/// #
@@ -1665,11 +1834,13 @@ pub trait SerializeTupleVariant {
/// use serde::ser::{Serialize, Serializer, SerializeMap};
///
/// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize,
/// V: Serialize
/// where
/// K: Serialize,
/// V: Serialize,
/// {
/// 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()))?;
/// for (k, v) in self {
@@ -1679,6 +1850,13 @@ pub trait SerializeTupleVariant {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeMap` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeMap {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
@@ -1742,8 +1920,10 @@ pub trait SerializeMap {
/// Returned from `Serializer::serialize_struct`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct};
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
///
/// struct Rgb {
/// r: u8,
@@ -1753,7 +1933,8 @@ pub trait SerializeMap {
///
/// impl Serialize for Rgb {
/// 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)?;
/// rgb.serialize_field("r", &self.r)?;
@@ -1763,6 +1944,13 @@ pub trait SerializeMap {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeStruct` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeStruct {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
@@ -1792,19 +1980,26 @@ pub trait SerializeStruct {
/// Returned from `Serializer::serialize_struct_variant`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStructVariant};
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
///
/// enum E {
/// S { r: u8, g: u8, b: u8 }
/// S { r: u8, g: u8, b: u8 },
/// }
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::S { ref r, ref g, ref b } => {
/// E::S {
/// ref r,
/// ref g,
/// ref b,
/// } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?;
@@ -1815,6 +2010,13 @@ pub trait SerializeStruct {
/// }
/// }
/// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeStructVariant` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeStructVariant {
/// Must match the `Ok` type of our `Serializer`.
type Ok;
+7 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.27" # remember to update html_root_url
version = "1.0.72" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -8,11 +8,12 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization", "no_std"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[features]
default = []
@@ -23,9 +24,9 @@ name = "serde_derive"
proc-macro = true
[dependencies]
quote = "0.3.8"
serde_derive_internals = { version = "=0.19.0", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] }
proc-macro2 = "0.4"
quote = "0.6"
syn = { version = "0.14", features = ["visit"] }
[dev-dependencies]
serde = { version = "1.0", path = "../serde" }
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+191 -133
View File
@@ -8,30 +8,31 @@
use std::collections::HashSet;
use syn::{self, visit};
use syn;
use syn::punctuated::{Pair, Punctuated};
use syn::visit::{self, Visit};
use internals::ast::{Body, Container};
use internals::ast::{Container, Data};
use internals::attr;
macro_rules! path {
($($path:tt)+) => {
syn::parse_path(quote!($($path)+).as_str()).unwrap()
};
}
use proc_macro2::Span;
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
ty_params: generics
.ty_params
params: generics
.params
.iter()
.map(|ty_param| syn::TyParam {
default: None,
..ty_param.clone()
})
.collect(),
.map(|param| match *param {
syn::GenericParam::Type(ref param) => syn::GenericParam::Type(syn::TypeParam {
eq_token: None,
default: None,
..param.clone()
}),
_ => param.clone(),
}).collect(),
..generics.clone()
}
}
@@ -42,34 +43,55 @@ pub fn with_where_predicates(
) -> syn::Generics {
let mut generics = generics.clone();
generics
.where_clause
.make_where_clause()
.predicates
.extend_from_slice(predicates);
.extend(predicates.into_iter().cloned());
generics
}
pub fn with_where_predicates_from_fields<F>(
pub fn with_where_predicates_from_fields(
cont: &Container,
generics: &syn::Generics,
from_field: F,
) -> syn::Generics
where
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
let predicates = cont.body
from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let predicates = cont
.data
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.where_clause.predicates.extend(predicates);
generics.make_where_clause().predicates.extend(predicates);
generics
}
pub fn with_where_predicates_from_variants(
cont: &Container,
generics: &syn::Generics,
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return generics.clone();
}
};
let predicates = variants
.iter()
.flat_map(|variant| from_variant(&variant.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
generics
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
// For example, the following struct needs the bound `A: Serialize, B:
// Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
@@ -77,40 +99,53 @@ where
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(
pub fn with_bound(
cont: &Container,
generics: &syn::Generics,
filter: F,
filter: fn(&attr::Field, Option<&attr::Variant>) -> bool,
bound: &syn::Path,
) -> syn::Generics
where
F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
{
struct FindTyParams {
) -> syn::Generics {
struct FindTyParams<'ast> {
// Set of all generic type parameters on the current struct (A, B, C in
// 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
// returns true (A and B in the example). Filled in as the visitor sees
// 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 visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
impl<'ast> Visit<'ast> for FindTyParams<'ast> {
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 seg.ident == "PhantomData" {
if seg.into_value().ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
if path.leading_colon.is_none() && path.segments.len() == 1 {
let id = &path.segments[0].ident;
if self.all_type_params.contains(id) {
self.relevant_type_params.insert(id.clone());
}
}
visit::walk_path(self, path);
visit::visit_path(self, path);
}
// Type parameter should not be considered used by a macro path.
@@ -119,61 +154,68 @@ where
// mac: T!(),
// marker: PhantomData<T>,
// }
fn visit_mac(&mut self, _mac: &syn::Mac) {}
fn visit_macro(&mut self, _mac: &'ast syn::Macro) {}
}
let all_ty_params: HashSet<_> = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
let all_type_params = generics
.type_params()
.map(|param| param.ident.clone())
.collect();
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
all_type_params: all_type_params,
relevant_type_params: HashSet::new(),
associated_type_usage: Vec::new(),
};
match cont.body {
Body::Enum(ref variants) => for variant in variants.iter() {
match cont.data {
Data::Enum(ref variants) => for variant in variants.iter() {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
visit::walk_ty(&mut visitor, field.ty);
visitor.visit_field(field.original);
}
},
Body::Struct(_, ref fields) => {
Data::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visit::walk_ty(&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
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| {
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
.type_params()
.map(|param| param.ident.clone())
.filter(|id| relevant_type_params.contains(id))
.map(|id| syn::TypePath {
qself: None,
path: id.into(),
}).chain(associated_type_usage.into_iter().cloned())
.map(|bounded_ty| {
syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
bounded_ty: syn::Type::Path(bounded_ty),
colon_token: <Token![:]>::default(),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: bound.clone(),
})].into_iter()
.collect(),
})
});
let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
generics
.make_where_clause()
.predicates
.extend(new_predicates);
generics
}
@@ -184,75 +226,91 @@ pub fn with_self_bound(
) -> syn::Generics {
let mut generics = generics.clone();
generics
.where_clause
.make_where_clause()
.predicates
.push(syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
));
.push(syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
colon_token: <Token![:]>::default(),
// the bound e.g. Default
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: bound.clone(),
})].into_iter()
.collect(),
}));
generics
}
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let mut generics = generics.clone();
for lifetime_def in &mut generics.lifetimes {
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
}
for ty_param in &mut generics.ty_params {
ty_param
.bounds
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
}
generics.lifetimes.push(syn::LifetimeDef {
let bound = syn::Lifetime::new(lifetime, Span::call_site());
let def = syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
});
lifetime: bound.clone(),
colon_token: None,
bounds: Punctuated::new(),
};
generics
let params = Some(syn::GenericParam::Lifetime(def))
.into_iter()
.chain(generics.params.iter().cloned().map(|mut param| {
match param {
syn::GenericParam::Lifetime(ref mut param) => {
param.bounds.push(bound.clone());
}
syn::GenericParam::Type(ref mut param) => {
param
.bounds
.push(syn::TypeParamBound::Lifetime(bound.clone()));
}
syn::GenericParam::Const(_) => {}
}
param
})).collect();
syn::Generics {
params: params,
..generics.clone()
}
}
fn type_of_item(cont: &Container) -> syn::Ty {
syn::Ty::Path(
None,
syn::Path {
global: false,
segments: vec![
syn::PathSegment {
ident: cont.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(
syn::AngleBracketedParameterData {
lifetimes: cont.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
types: cont.generics
.ty_params
.iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(),
bindings: Vec::new(),
},
),
},
],
fn type_of_item(cont: &Container) -> syn::Type {
syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: vec![syn::PathSegment {
ident: cont.ident.clone(),
arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: <Token![<]>::default(),
args: cont
.generics
.params
.iter()
.map(|param| match *param {
syn::GenericParam::Type(ref param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None,
path: param.ident.clone().into(),
}))
}
syn::GenericParam::Lifetime(ref param) => {
syn::GenericArgument::Lifetime(param.lifetime.clone())
}
syn::GenericParam::Const(_) => {
panic!("Serde does not support const generics yet");
}
}).collect(),
gt_token: <Token![>]>::default(),
},
),
}].into_iter()
.collect(),
},
)
})
}
+832 -358
View File
File diff suppressed because it is too large Load Diff
+13 -15
View File
@@ -6,14 +6,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{ToTokens, Tokens};
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::token;
pub enum Fragment {
/// 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
/// not part of these tokens.
Block(Tokens),
Block(TokenStream),
}
macro_rules! quote_expr {
@@ -32,13 +34,11 @@ macro_rules! quote_block {
/// Block fragments in curly braces.
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut Tokens) {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
@@ -47,7 +47,7 @@ impl ToTokens for Expr {
/// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut Tokens) {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out),
@@ -59,23 +59,21 @@ impl ToTokens for Stmts {
/// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut Tokens) {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => {
expr.to_tokens(out);
out.append(",");
<Token![,]>::default().to_tokens(out);
}
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
}
impl AsRef<Tokens> for Fragment {
fn as_ref(&self) -> &Tokens {
impl AsRef<TokenStream> for Fragment {
fn as_ref(&self) -> &TokenStream {
match *self {
Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block,
@@ -6,19 +6,20 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use internals::attr;
use internals::check;
use internals::{Ctxt, Derive};
use syn;
use attr;
use check;
use Ctxt;
use syn::punctuated::Punctuated;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
pub body: Body<'a>,
pub data: Data<'a>,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
pub enum Data<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
@@ -31,9 +32,10 @@ pub struct Variant<'a> {
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub member: syn::Member,
pub attrs: attr::Field,
pub ty: &'a syn::Ty,
pub ty: &'a syn::Type,
pub original: &'a syn::Field,
}
#[derive(Copy, Clone)]
@@ -45,49 +47,63 @@ pub enum Style {
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
let attrs = attr::Container::from_ast(cx, item);
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive) -> Container<'a> {
let mut attrs = attr::Container::from_ast(cx, item);
let mut body = match item.body {
syn::Body::Enum(ref variants) => {
Body::Enum(enum_from_ast(cx, variants, &attrs.default()))
let mut data = match item.data {
syn::Data::Enum(ref data) => {
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
}
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data, None, &attrs.default());
Body::Struct(style, fields)
syn::Data::Struct(ref data) => {
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
Data::Struct(style, fields)
}
syn::Data::Union(_) => {
panic!("Serde does not support derive for unions");
}
};
match body {
Body::Enum(ref mut variants) => for ref mut variant in variants {
let mut has_flatten = false;
match data {
Data::Enum(ref mut variants) => for variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut 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());
}
},
Body::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());
},
}
let item = Container {
if has_flatten {
attrs.mark_has_flatten();
}
let mut item = Container {
ident: item.ident.clone(),
attrs: attrs,
body: body,
data: data,
generics: &item.generics,
};
check::check(cx, &item);
check::check(cx, &mut item, derive);
item
}
}
impl<'a> Body<'a> {
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Data::Enum(ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
Data::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
@@ -98,7 +114,7 @@ impl<'a> Body<'a> {
fn enum_from_ast<'a>(
cx: &Ctxt,
variants: &'a [syn::Variant],
variants: &'a Punctuated<syn::Variant, Token![,]>,
container_default: &attr::Default,
) -> Vec<Variant<'a>> {
variants
@@ -106,43 +122,42 @@ fn enum_from_ast<'a>(
.map(|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) =
struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
}
})
.collect()
}).collect()
}
fn struct_from_ast<'a>(
cx: &Ctxt,
data: &'a syn::VariantData,
fields: &'a syn::Fields,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => (
match *fields {
syn::Fields::Named(ref fields) => (
Style::Struct,
fields_from_ast(cx, fields, attrs, container_default),
fields_from_ast(cx, &fields.named, attrs, container_default),
),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => (
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, fields, attrs, container_default),
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::VariantData::Tuple(ref fields) => (
syn::Fields::Unnamed(ref fields) => (
Style::Tuple,
fields_from_ast(cx, fields, attrs, container_default),
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
syn::Fields::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(
cx: &Ctxt,
fields: &'a [syn::Field],
fields: &'a Punctuated<syn::Field, Token![,]>,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> Vec<Field<'a>> {
@@ -150,9 +165,12 @@ fn fields_from_ast<'a>(
.iter()
.enumerate()
.map(|(i, field)| Field {
ident: field.ident.clone(),
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),
ty: &field.ty,
})
.collect()
original: field,
}).collect()
}
File diff suppressed because it is too large Load Diff
@@ -7,14 +7,14 @@
// 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
#[allow(unused_imports)]
#[allow(deprecated, unused_imports)]
use std::ascii::AsciiExt;
use std::str::FromStr;
use self::RenameRule::*;
#[derive(Debug, PartialEq)]
#[derive(PartialEq)]
pub enum RenameRule {
/// Don't apply a default rename rule.
None,
@@ -22,13 +22,16 @@ pub enum RenameRule {
LowerCase,
/// Rename direct children to "UPPERCASE" style.
UPPERCASE,
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
/// Rename direct children to "PascalCase" style, as typically used for
/// enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
CamelCase,
/// Rename direct children to "snake_case" style, as commonly used for fields.
/// Rename direct children to "snake_case" style, as commonly used for
/// fields.
SnakeCase,
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly
/// used for constants.
ScreamingSnakeCase,
/// Rename direct children to "kebab-case" style.
KebabCase,
@@ -113,14 +116,7 @@ impl FromStr for RenameRule {
fn rename_variants() {
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",
@@ -154,13 +150,7 @@ fn rename_variants() {
fn rename_fields() {
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",
+355
View File
@@ -0,0 +1,355 @@
// 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.
use internals::ast::{Container, Data, Field, Style};
use internals::attr::{EnumTag, Identifier};
use internals::{Ctxt, Derive};
use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_getter(cx, cont);
check_flatten(cx, cont);
check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont);
check_internal_tag_field_name_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`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(_) => {
if cont.data.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Data::Struct(_, _) => {
if cont.data.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
);
}
}
}
}
/// 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
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (
variant.style,
cont.attrs.identifier(),
variant.attrs.other(),
) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true) => {
if i < variants.len() - 1 {
cx.error("#[serde(other)] must be the last variant");
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true) => {
cx.error("#[serde(other)] must be on a unit variant");
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false) => {
if i < variants.len() - 1 {
cx.error(format!("`{}` must be the last variant", variant.ident));
}
}
(_, Identifier::Field, false) => {
cx.error("field_identifier may only contain unit variants");
}
(_, Identifier::Variant, false) => {
cx.error("variant_identifier may only contain unit variants");
}
}
}
}
/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return;
}
};
for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
variant.ident
));
}
for field in &variant.fields {
let member = member_message(&field.member);
if field.attrs.skip_serializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
variant.ident, member
));
}
if field.attrs.skip_serializing_if().is_some() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, member
));
}
}
}
if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
variant.ident
));
}
for field in &variant.fields {
if field.attrs.skip_deserializing() {
let member = member_message(&field.member);
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, member
));
}
}
}
}
}
/// The tag of an internally-tagged struct variant must not be
/// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => return,
};
let tag = match *cont.attrs.tag() {
EnumTag::Internal { ref tag } => tag.as_str(),
EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
};
let diagnose_conflict = || {
let message = format!("variant field name `{}` conflicts with internal tag", tag);
cx.error(message);
};
for variant in variants {
match variant.style {
Style::Struct => {
for field in &variant.fields {
let check_ser = !field.attrs.skip_serializing();
let check_de = !field.attrs.skip_deserializing();
let name = field.attrs.name();
let ser_name = name.serialize_name();
let de_name = name.deserialize_name();
if check_ser && ser_name == tag || check_de && de_name == tag {
diagnose_conflict();
return;
}
}
}
Style::Unit | Style::Newtype | Style::Tuple => {}
}
}
}
/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
let (type_tag, content_tag) = match *cont.attrs.tag() {
EnumTag::Adjacent {
ref tag,
ref content,
} => (tag, content),
EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
};
if type_tag == content_tag {
let message = format!(
"enum tags `{}` for type and content conflict with each other",
type_tag
);
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,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Display;
use std::cell::RefCell;
use std::fmt::Display;
use std::thread;
#[derive(Default)]
pub struct Ctxt {
@@ -48,7 +49,7 @@ impl Ctxt {
impl Drop for Ctxt {
fn drop(&mut self) {
if self.errors.borrow().is_some() {
if !thread::panicking() && self.errors.borrow().is_some() {
panic!("forgot to check for errors");
}
}
@@ -6,17 +6,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.19.0")]
extern crate syn;
#[macro_use]
extern crate synom;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
pub use self::ctxt::Ctxt;
mod case;
mod check;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
Deserialize,
}
+54 -16
View File
@@ -22,43 +22,81 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.27")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.72")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
enum_variant_names,
redundant_field_names,
too_many_arguments,
used_underscore_binding,
cyclomatic_complexity,
needless_pass_by_value
)
)]
// 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,
indexing_slicing,
)
)]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
#![recursion_limit = "512"]
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate serde_derive_internals as internals;
extern crate proc_macro;
extern crate proc_macro2;
mod internals;
use proc_macro::TokenStream;
use syn::DeriveInput;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod ser;
mod de;
mod pretend;
mod ser;
mod try;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match ser::expand_derive_serialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
let input: DeriveInput = syn::parse(input).unwrap();
ser::expand_derive_serialize(&input)
.unwrap_or_else(compile_error)
.into()
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match de::expand_derive_deserialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
let input: DeriveInput = syn::parse(input).unwrap();
de::expand_derive_deserialize(&input)
.unwrap_or_else(compile_error)
.into()
}
fn compile_error(message: String) -> proc_macro2::TokenStream {
quote! {
compile_error!(#message);
}
}
+139
View File
@@ -0,0 +1,139 @@
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),* })
}
+447 -170
View File
@@ -6,35 +6,39 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn::{self, Ident};
use quote::Tokens;
use proc_macro2::{Span, TokenStream};
use syn::spanned::Spanned;
use syn::{self, Ident, Index, Member};
use bound;
use fragment::{Fragment, Match, Stmts};
use internals::ast::{Body, Container, Field, Style, Variant};
use internals::{attr, Ctxt};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, Ctxt, Derive};
use pretend;
use try;
use std::u32;
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, String> {
let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input);
let cont = Container::from_ast(&ctxt, input, Derive::Serialize);
precondition(&ctxt, &cont);
try!(ctxt.check());
let ident = &cont.ident;
let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::call_site());
let body = Stmts(serialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
let used = pretend::pretend_used(&cont);
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
#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
}
}
@@ -44,7 +48,8 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
#[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
#body
}
@@ -52,10 +57,15 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
}
};
let try_replacement = try::replacement();
let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
#[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)]
extern crate serde as _serde;
#try_replacement
#impl_block
};
};
@@ -95,9 +105,9 @@ impl Parameters {
fn new(cont: &Container) -> Self {
let is_remote = cont.attrs.remote().is_some();
let self_var = if is_remote {
Ident::new("__self")
Ident::new("__self", Span::call_site())
} else {
Ident::new("self")
Ident::new("self", Span::call_site())
};
let this = match cont.attrs.remote() {
@@ -117,8 +127,8 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> &str {
self.this.segments.last().unwrap().ident.as_ref()
fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.to_string()
}
}
@@ -130,58 +140,83 @@ fn build_generics(cont: &Container) -> syn::Generics {
let generics =
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() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => bound::with_bound(
cont,
&generics,
needs_serialize_bound,
&path!(_serde::Serialize),
&parse_quote!(_serde::Serialize),
),
}
}
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
// belong to a variant with a `serialize_with` attribute, are not serialized by
// us so we do not generate a bound. Fields with a `bound` attribute specify
// their own bound so we do not generate one. All other fields may need a `T:
// Serialize` bound where T is the type of the field.
// belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
// are not serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// 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 {
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
&& variant.map_or(true, |variant| variant.serialize_with().is_none())
!field.skip_serializing()
&& field.serialize_with().is_none()
&& field.ser_bound().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 {
if let Some(into_type) = cont.attrs.into_type() {
serialize_into(params, into_type)
if cont.attrs.transparent() {
serialize_transparent(cont, params)
} else if let Some(type_into) = cont.attrs.type_into() {
serialize_into(params, type_into)
} else {
match cont.body {
Body::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
match cont.data {
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, ref fields) => {
serialize_struct(params, fields, &cont.attrs)
}
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
Data::Struct(Style::Tuple, ref fields) => {
serialize_tuple_struct(params, fields, &cont.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
Data::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(params, &fields[0], &cont.attrs)
}
Body::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
}
}
}
fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> 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 {
let self_var = &params.self_var;
quote_block! {
_serde::Serialize::serialize(
&_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)),
&_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
__serializer)
}
}
@@ -201,13 +236,22 @@ fn serialize_newtype_struct(
) -> Fragment {
let type_name = cattrs.name().serialize_name();
let mut field_expr = get_field(params, field, 0);
let mut field_expr = get_member(
params,
field,
&Member::Unnamed(Index {
index: 0,
span: Span::call_site(),
}),
);
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 = field.original.span();
let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
quote_expr! {
_serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr)
#func(__serializer, #type_name, #field_expr)
}
}
@@ -216,16 +260,31 @@ fn serialize_tuple_struct(
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
let serialize_stmts = serialize_tuple_struct_visitor(
fields,
params,
false,
quote!(_serde::ser::SerializeTupleStruct::serialize_field),
);
let serialize_stmts =
serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct);
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! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
@@ -235,15 +294,22 @@ fn serialize_tuple_struct(
}
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
assert!(fields.len() as u64 <= u32::MAX as u64);
assert!(fields.len() as u64 <= u64::from(u32::max_value()));
let serialize_fields = serialize_struct_visitor(
fields,
params,
false,
quote!(_serde::ser::SerializeStruct::serialize_field),
quote!(_serde::ser::SerializeStruct::skip_field),
);
if cattrs.has_flatten() {
serialize_struct_as_map(params, fields, cattrs)
} else {
serialize_struct_as_struct(params, fields, cattrs)
}
}
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();
@@ -258,12 +324,10 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
.map(|field| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = get_field(params, field, ident);
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));
}).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
@@ -272,8 +336,44 @@ 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 {
assert!(variants.len() as u64 <= u32::MAX as u64);
assert!(variants.len() as u64 <= u64::from(u32::max_value()));
let self_var = &params.self_var;
@@ -282,8 +382,7 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(params, variant, variant_index as u32, cattrs)
})
.collect();
}).collect();
quote_expr! {
match *#self_var {
@@ -297,9 +396,9 @@ fn serialize_variant(
variant: &Variant,
variant_index: u32,
cattrs: &attr::Container,
) -> Tokens {
) -> TokenStream {
let this = &params.this;
let variant_ident = variant.ident.clone();
let variant_ident = &variant.ident;
if variant.attrs.skip_serializing() {
let skipped_msg = format!(
@@ -332,19 +431,16 @@ fn serialize_variant(
}
}
Style::Tuple => {
let field_names =
(0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i)));
let field_names = (0..variant.fields.len())
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
quote! {
#this::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let fields = variant
.fields
.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
let members = variant.fields.iter().map(|f| &f.member);
quote! {
#this::#variant_ident { #(ref #fields),* }
#this::#variant_ident { #(ref #members),* }
}
}
};
@@ -379,7 +475,7 @@ fn serialize_externally_tagged_variant(
let variant_name = variant.attrs.name().serialize_name();
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);
return quote_expr! {
_serde::Serializer::serialize_newtype_variant(
__serializer,
@@ -406,7 +502,7 @@ fn serialize_externally_tagged_variant(
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
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);
}
quote_expr! {
@@ -450,10 +546,10 @@ fn serialize_internally_tagged_variant(
let variant_name = variant.attrs.name().serialize_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() {
let ser = wrap_serialize_variant_with(params, path, &variant);
let ser = wrap_serialize_variant_with(params, path, variant);
return quote_expr! {
_serde::private::ser::serialize_tagged_newtype(
__serializer,
@@ -480,7 +576,7 @@ fn serialize_internally_tagged_variant(
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
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);
}
quote_expr! {
@@ -519,7 +615,7 @@ fn serialize_adjacently_tagged_variant(
let variant_name = variant.attrs.name().serialize_name();
let inner = Stmts(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);
quote_expr! {
_serde::Serialize::serialize(#ser, __serializer)
}
@@ -538,12 +634,18 @@ fn serialize_adjacently_tagged_variant(
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
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);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
return quote_block! {
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 => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
@@ -558,7 +660,7 @@ fn serialize_adjacently_tagged_variant(
});
let fields_ty = variant.fields.iter().map(|f| &f.ty);
let ref fields_ident: Vec<_> = match variant.style {
let fields_ident: &Vec<_> = &match variant.style {
Style::Unit => {
if variant.attrs.serialize_with().is_some() {
vec![]
@@ -566,20 +668,16 @@ fn serialize_adjacently_tagged_variant(
unreachable!()
}
}
Style::Newtype => vec![Ident::new("__field0")],
Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
Style::Tuple => (0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)))
.collect(),
Style::Struct => variant
.fields
.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"))
.map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
.collect(),
Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
};
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()
} else {
bound::with_lifetime_bound(&params.generics, "'__a")
@@ -594,7 +692,8 @@ fn serialize_adjacently_tagged_variant(
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>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
let (#(#fields_ident,)*) = self.data;
#inner
@@ -620,7 +719,7 @@ fn serialize_untagged_variant(
cattrs: &attr::Container,
) -> Fragment {
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);
return quote_expr! {
_serde::Serialize::serialize(#ser, __serializer)
};
@@ -636,7 +735,7 @@ fn serialize_untagged_variant(
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
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);
}
quote_expr! {
@@ -665,17 +764,29 @@ fn serialize_tuple_variant(
params: &Parameters,
fields: &[Field],
) -> Fragment {
let method = match context {
TupleVariant::ExternallyTagged { .. } => {
quote!(_serde::ser::SerializeTupleVariant::serialize_field)
}
TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
let tuple_trait = match context {
TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
TupleVariant::Untagged => TupleTrait::SerializeTuple,
};
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, method);
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
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 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 {
TupleVariant::ExternallyTagged {
@@ -724,18 +835,18 @@ fn serialize_struct_variant<'a>(
fields: &[Field],
name: &str,
) -> Fragment {
let (method, skip_method) = match context {
StructVariant::ExternallyTagged { .. } => (
quote!(_serde::ser::SerializeStructVariant::serialize_field),
quote!(_serde::ser::SerializeStructVariant::skip_field),
),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => (
quote!(_serde::ser::SerializeStruct::serialize_field),
quote!(_serde::ser::SerializeStruct::skip_field),
),
if fields.iter().any(|field| field.attrs.flatten()) {
return serialize_struct_variant_with_flatten(context, params, fields, name);
}
let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
(StructTrait::SerializeStruct)
}
};
let serialize_fields = serialize_struct_visitor(fields, params, true, method, skip_method);
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
let mut serialized_fields = fields
.iter()
@@ -746,14 +857,13 @@ fn serialize_struct_variant<'a>(
let len = serialized_fields
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
let member = &field.member;
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),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
}).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context {
StructVariant::ExternallyTagged {
@@ -802,21 +912,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(
fields: &[Field],
params: &Parameters,
is_enum: bool,
func: Tokens,
) -> Vec<Tokens> {
tuple_trait: &TupleTrait,
) -> Vec<TokenStream> {
fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(format!("__field{}", i));
let id = Ident::new(&format!("__field{}", i), Span::call_site());
quote!(#id)
} else {
get_field(params, field, i)
get_member(
params,
field,
&Member::Unnamed(Index {
index: i as u32,
span: Span::call_site(),
}),
)
};
let skip = field
@@ -825,9 +1029,11 @@ fn serialize_tuple_struct_visitor(
.map(|path| quote!(#path(#field_expr)));
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 = field.original.span();
let func = tuple_trait.serialize_element(span);
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
};
@@ -836,26 +1042,25 @@ fn serialize_tuple_struct_visitor(
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}).collect()
}
fn serialize_struct_visitor(
fields: &[Field],
params: &Parameters,
is_enum: bool,
func: Tokens,
skip_func: Tokens,
) -> Vec<Tokens> {
struct_trait: &StructTrait,
) -> Vec<TokenStream> {
fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let field_ident = field.ident.clone().expect("struct has unnamed field");
let member = &field.member;
let mut field_expr = if is_enum {
quote!(#field_ident)
quote!(#member)
} else {
get_field(params, field, field_ident)
get_member(params, field, &member)
};
let key_expr = field.attrs.name().serialize_name();
@@ -866,21 +1071,37 @@ fn serialize_struct_visitor(
.map(|path| quote!(#path(#field_expr)));
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 ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
let span = field.original.span();
let ser = if field.attrs.flatten() {
quote! {
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 {
None => ser,
Some(skip) => {
quote! {
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
if let Some(skip_func) = struct_trait.skip_field(span) {
quote! {
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
}
}
} else {
quote! {
if !#skip {
#ser
}
}
}
}
@@ -891,31 +1112,31 @@ fn serialize_struct_visitor(
fn wrap_serialize_field_with(
params: &Parameters,
field_ty: &syn::Ty,
serialize_with: &syn::Path,
field_expr: Tokens,
) -> Tokens {
field_ty: &syn::Type,
serialize_with: &syn::ExprPath,
field_expr: &TokenStream,
) -> TokenStream {
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
}
fn wrap_serialize_variant_with(
params: &Parameters,
serialize_with: &syn::Path,
serialize_with: &syn::ExprPath,
variant: &Variant,
) -> Tokens {
) -> TokenStream {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
let field_exprs: Vec<_> = variant
.fields
.iter()
.enumerate()
.map(|(i, field)| {
let id = field
.ident
.as_ref()
.map_or_else(|| Ident::new(format!("__field{}", i)), |id| id.clone());
.map(|field| {
let id = match field.member {
Member::Named(ref ident) => ident.clone(),
Member::Unnamed(ref member) => {
Ident::new(&format!("__field{}", member.index), Span::call_site())
}
};
quote!(#id)
})
.collect();
}).collect();
wrap_serialize_with(
params,
serialize_with,
@@ -926,21 +1147,26 @@ fn wrap_serialize_variant_with(
fn wrap_serialize_with(
params: &Parameters,
serialize_with: &syn::Path,
field_tys: &[&syn::Ty],
field_exprs: &[Tokens],
) -> Tokens {
serialize_with: &syn::ExprPath,
field_tys: &[&syn::Type],
field_exprs: &[TokenStream],
) -> TokenStream {
let this = &params.this;
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if field_exprs.len() == 0 {
let wrapper_generics = if field_exprs.is_empty() {
params.generics.clone()
} else {
bound::with_lifetime_bound(&params.generics, "'__a")
};
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
let field_access = (0..field_exprs.len()).map(|n| Ident::new(format!("{}", n)));
let field_access = (0..field_exprs.len()).map(|n| {
Member::Unnamed(Index {
index: n as u32,
span: Span::call_site(),
})
});
quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause {
@@ -950,7 +1176,8 @@ fn wrap_serialize_with(
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>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
#serialize_with(#(self.values.#field_access, )* __s)
}
@@ -969,7 +1196,7 @@ fn wrap_serialize_with(
// _serde::ser::SerializeStruct::end(__serde_state)
//
// 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 {
Some(quote!(mut))
} else {
@@ -977,20 +1204,14 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
}
}
fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
where
I: Into<Ident>,
{
fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => {
let ident = ident.into();
quote!(&#self_var.#ident)
}
(false, None) => quote!(&#self_var.#member),
(true, None) => {
let inner = quote!(&#self_var.#member);
let ty = field.ty;
let ident = ident.into();
quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident))
quote!(_serde::private::ser::constrain::<#ty>(#inner))
}
(true, Some(getter)) => {
let ty = field.ty;
@@ -1001,3 +1222,59 @@ where
}
}
}
enum StructTrait {
SerializeMap,
SerializeStruct,
SerializeStructVariant,
}
impl StructTrait {
fn serialize_field(&self, span: Span) -> TokenStream {
match *self {
StructTrait::SerializeMap => {
quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
}
StructTrait::SerializeStruct => {
quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
}
StructTrait::SerializeStructVariant => {
quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
}
}
}
fn skip_field(&self, span: Span) -> Option<TokenStream> {
match *self {
StructTrait::SerializeMap => None,
StructTrait::SerializeStruct => {
Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field))
}
StructTrait::SerializeStructVariant => {
Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field))
}
}
}
}
enum TupleTrait {
SerializeTuple,
SerializeTupleStruct,
SerializeTupleVariant,
}
impl TupleTrait {
fn serialize_element(&self, span: Span) -> TokenStream {
match *self {
TupleTrait::SerializeTuple => {
quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
}
TupleTrait::SerializeTupleStruct => {
quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
}
TupleTrait::SerializeTupleVariant => {
quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
}
}
}
}
+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);
}
}
}
}
}
}
+9 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive_internals"
version = "0.19.0" # 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>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
@@ -8,12 +8,16 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
readme = "crates-io.md"
include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[lib]
path = "lib.rs"
[dependencies]
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
synom = "0.11"
proc-macro2 = "0.4"
syn = { version = "0.14", default-features = false, features = ["derive", "parsing", "clone-impls"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+28
View File
@@ -0,0 +1,28 @@
// 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.
#![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,
redundant_field_names
)
)]
#[macro_use]
extern crate syn;
extern crate proc_macro2;
#[path = "src/mod.rs"]
mod internals;
pub use internals::*;
+1
View File
@@ -0,0 +1 @@
../serde_derive/src/internals/
-171
View File
@@ -1,171 +0,0 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Body, Container, Style};
use attr::Identifier;
use Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
check_getter(cx, cont);
check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.body {
Body::Enum(_) => {
if cont.body.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Body::Struct(_, _) => {
if cont.body.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
);
}
}
}
}
/// 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.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.body {
Body::Enum(ref variants) => variants,
Body::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (
variant.style,
cont.attrs.identifier(),
variant.attrs.other(),
) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true) => {
if i < variants.len() - 1 {
cx.error("#[serde(other)] must be the last variant");
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true) => {
cx.error("#[serde(other)] must be on a unit variant");
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false) => {
if i < variants.len() - 1 {
cx.error(format!("`{}` must be the last variant", variant.ident));
}
}
(_, Identifier::Field, false) => {
cx.error("field_identifier may only contain unit variants");
}
(_, Identifier::Variant, false) => {
cx.error("variant_identifier may only contain unit variants");
}
}
}
}
/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match cont.body {
Body::Enum(ref variants) => variants,
Body::Struct(_, _) => {
return;
}
};
for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
variant.ident
));
}
for (i, field) in variant.fields.iter().enumerate() {
let ident = field
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
if field.attrs.skip_serializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident
));
}
if field.attrs.skip_serializing_if().is_some() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident
));
}
}
}
if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
variant.ident
));
}
for (i, field) in variant.fields.iter().enumerate() {
if field.attrs.skip_deserializing() {
let ident = field
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident
));
}
}
}
}
}
+6 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.27" # remember to update html_root_url
version = "1.0.72" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
@@ -8,15 +8,16 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
serde = { version = "1.0.16", path = "../serde" }
serde = { version = "1.0.60", path = "../serde" }
[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" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+2 -1
View File
@@ -95,7 +95,8 @@ where
}
}
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`.
/// Asserts that `value` serializes to the given `tokens`, and then yields
/// `error`.
///
/// ```rust
/// # #[macro_use]
File diff suppressed because it is too large Load Diff
+24 -20
View File
@@ -6,9 +6,11 @@
// option. This file may not be copied, modified, or distributed
// 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::{
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use error::Error;
use token::Token;
@@ -22,28 +24,28 @@ macro_rules! assert_next_token {
($de:expr, $expected:expr) => {
match $de.next_token_opt() {
Some(token) if token == $expected => {}
Some(other) => {
panic!("expected Token::{} but deserialization wants Token::{}",
other, $expected)
}
None => {
panic!("end of tokens but deserialization wants Token::{}",
$expected)
}
Some(other) => panic!(
"expected Token::{} but deserialization wants Token::{}",
other, $expected
),
None => panic!(
"end of tokens but deserialization wants Token::{}",
$expected
),
}
}
};
}
macro_rules! unexpected {
($token:expr) => {
panic!("deserialization did not expect this token: {}", $token)
}
};
}
macro_rules! end_of_tokens {
() => {
panic!("ran out of tokens to deserialize")
}
};
}
impl<'de> Deserializer<'de> {
@@ -127,8 +129,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf unit seq map identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf unit seq map identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -251,7 +253,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
Token::UnitVariant { name: n, .. }
| Token::NewtypeVariant { name: n, .. }
| Token::TupleVariant { name: n, .. }
| Token::StructVariant { name: n, .. } if name == n =>
| Token::StructVariant { name: n, .. }
if name == n =>
{
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
@@ -597,7 +600,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
{
match self.variant.take() {
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),
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => unexpected!(other),
@@ -654,8 +658,8 @@ impl<'de> de::Deserializer<'de> for BytesDeserializer {
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
+34 -17
View File
@@ -53,7 +53,7 @@
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
//! #
//! # // Dumb immitation of LinkedHashMap.
//! # // Dumb imitation of LinkedHashMap.
//! # #[derive(PartialEq, Debug)]
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
//! #
@@ -68,11 +68,13 @@
//! # }
//! #
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
//! # where K: Serialize,
//! # V: Serialize
//! # where
//! # K: Serialize,
//! # V: Serialize,
//! # {
//! # 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()))?;
//! # for &(ref k, ref v) in &self.0 {
@@ -85,8 +87,9 @@
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
//! #
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
//! # where K: Deserialize<'de>,
//! # V: Deserialize<'de>
//! # where
//! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # {
//! # type Value = LinkedHashMap<K, V>;
//! #
@@ -95,7 +98,8 @@
//! # }
//! #
//! # 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();
//! # while let Some((key, value)) = access.next_entry()? {
@@ -106,11 +110,13 @@
//! # }
//! #
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
//! # where K: Deserialize<'de>,
//! # V: Deserialize<'de>
//! # where
//! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # {
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//! # where D: Deserializer<'de>
//! # where
//! # D: Deserializer<'de>,
//! # {
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
//! # }
@@ -155,28 +161,39 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.27")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.72")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy",
allow(missing_docs_in_private_items, stutter, use_debug, use_self))]
#![cfg_attr(
feature = "cargo-clippy",
allow(
empty_line_after_outer_attr,
missing_docs_in_private_items,
redundant_field_names,
stutter,
use_debug,
use_self
)
)]
#[macro_use]
extern crate serde;
mod ser;
mod de;
mod error;
mod ser;
mod assert;
mod configure;
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 assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
assert_ser_tokens_error, assert_tokens};
pub use configure::{Compact, Configure, Readable};
+5 -4
View File
@@ -11,7 +11,8 @@ use serde::{ser, Serialize};
use error::Error;
use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of tokens.
/// A `Serializer` that ensures that a value serializes to a given list of
/// tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
tokens: &'a [Token],
@@ -45,7 +46,7 @@ macro_rules! assert_next_token {
($ser:expr, $expected:ident($v:expr)) => {
assert_next_token!(
$ser,
format_args!("{}({:?})", stringify!($expected), $v),
format_args!(concat!(stringify!($expected), "({:?})"), $v),
Token::$expected(v),
v == $v
);
@@ -56,13 +57,13 @@ macro_rules! assert_next_token {
use std::fmt::Write;
let mut buffer = String::new();
$(
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
)*
buffer
};
assert_next_token!(
$ser,
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
Token::$expected { $($k),* },
($($k,)*) == compare
);
+1
View File
@@ -9,6 +9,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies]
fnv = "1.0"
proc-macro2 = "0.4"
rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
+8 -14
View File
@@ -6,11 +6,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(lang_items, start, compiler_builtins_lib)]
#![feature(lang_items, start, panic_implementation)]
#![no_std]
extern crate libc;
extern crate compiler_builtins;
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
@@ -19,19 +18,12 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
#[lang = "eh_personality"]
#[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"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32) -> ! {
#[panic_implementation]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort()
libc::abort();
}
}
@@ -50,7 +42,9 @@ struct Newtype(u8);
struct Tuple(u8, u8);
#[derive(Serialize, Deserialize)]
struct Struct { f: u8 }
struct Struct {
f: u8,
}
#[derive(Serialize, Deserialize)]
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())
}
}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
struct Test<'a> {
#[serde(borrow = "zzz")] //~^^ HELP: failed to parse borrowed lifetimes: "zzz"
#[serde(borrow = "zzz")]
//~^^^ ERROR: failed to parse borrowed lifetimes: "zzz"
s: &'a str,
}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
struct Test<'a> {
#[serde(borrow = "'a + 'a")] //~^^ HELP: duplicate borrowed lifetime `'a`
#[serde(borrow = "'a + 'a")]
//~^^^ ERROR: duplicate borrowed lifetime `'a`
s: &'a str,
}
@@ -12,10 +12,11 @@ extern crate serde_derive;
#[derive(Deserialize)]
struct Str<'a>(&'a str);
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
enum Test<'a> {
#[serde(borrow)] //~^^ HELP: duplicate serde attribute `borrow`
S(#[serde(borrow)] Str<'a>)
#[serde(borrow)]
//~^^^ ERROR: duplicate serde attribute `borrow`
S(#[serde(borrow)] Str<'a>),
}
fn main() {}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
struct Test<'a> {
#[serde(borrow = "")] //~^^ HELP: at least one lifetime must be borrowed
#[serde(borrow = "")]
//~^^^ ERROR: at least one lifetime must be borrowed
s: &'a str,
}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
struct Test {
#[serde(borrow)] //~^^ HELP: field `s` has no lifetimes to borrow
#[serde(borrow)]
//~^^^ ERROR: field `s` has no lifetimes to borrow
s: String,
}
@@ -12,10 +12,11 @@ extern crate serde_derive;
#[derive(Deserialize)]
struct Str<'a>(&'a str);
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
enum Test<'a> {
#[serde(borrow)] //~^^ HELP: #[serde(borrow)] may only be used on newtype variants
S { s: Str<'a> }
#[serde(borrow)]
//~^^^ ERROR: #[serde(borrow)] may only be used on newtype variants
S { s: Str<'a> },
}
fn main() {}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
struct Test<'a> {
#[serde(borrow = "'b")] //~^^ HELP: field `s` does not have lifetime 'b
#[serde(borrow = "'b")]
//~^^^ ERROR: field `s` does not have lifetime 'b
s: &'a str,
}
@@ -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)]
#[serde(tag = "conflict", content = "conflict")]
//~^^ ERROR: enum tags `conflict` for type and content conflict with each other
enum E {
A,
B,
}
fn main() {}
@@ -1,4 +1,4 @@
// Copyright 2017 Serde Developers
// 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
@@ -6,15 +6,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(identity_op)]
#[macro_use]
extern crate serde_derive;
// The derived implementation uses 0+1 to add up the number of fields
// serialized, which Clippy warns about. If the expansion info is registered
// correctly, the Clippy lint is not triggered.
#[derive(Serialize)]
struct A { b: u8 }
struct Foo(#[serde(flatten)] HashMap<String, String>);
//~^^ ERROR: #[serde(flatten)] cannot be used on newtype structs
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)]
struct Foo {
#[serde(flatten, skip_deserializing)]
//~^^^ ERROR: #[serde(flatten] can not be combined with #[serde(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)]
struct Foo {
#[serde(flatten, skip_serializing_if = "Option::is_none")]
//~^^^ ERROR: #[serde(flatten] can not be combined with #[serde(skip_serializing_if = "...")]
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)]
struct Foo {
#[serde(flatten, skip_serializing)]
//~^^^ ERROR: #[serde(flatten] can not be combined with #[serde(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)]
struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
//~^^ ERROR: #[serde(flatten)] cannot be used on tuple structs
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(Serialize)]
#[serde(tag = "conflict")]
//~^^ ERROR: variant field name `conflict` conflicts with internal tag
enum E {
A {
#[serde(rename = "conflict")]
x: (),
},
}
fn main() {}
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs
#[derive(Deserialize)]
#[serde(default)]
//~^^ ERROR: #[serde(default)] can only be used on structs
enum E {
S { f: u8 },
}
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs
#[derive(Deserialize)]
#[serde(default)]
//~^^ ERROR: #[serde(default)] can only be used on structs
struct T(u8, u8);
fn main() { }
fn main() {}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize`
#[serde(rename = "x", serialize = "y")]
//~^^^ ERROR: unknown serde field attribute `serialize`
x: (),
}
@@ -9,10 +9,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
#[serde(rename = "x")]
#[serde(rename(deserialize = "y"))]
//~^^^^ ERROR: duplicate serde attribute `rename`
x: (),
}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
#[serde(rename(serialize = "x"), rename(serialize = "y"))]
//~^^^ ERROR: duplicate serde attribute `rename`
x: (),
}
@@ -9,10 +9,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename`
#[serde(rename(serialize = "x"))]
#[serde(rename = "y")]
//~^^^^ ERROR: duplicate serde attribute `rename`
x: (),
}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
#[serde(rename(serialize = "x", serialize = "y"))]
//~^^^ ERROR: duplicate serde attribute `rename`
x: (),
}
@@ -9,10 +9,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
#[serde(rename(serialize = "x"))]
#[serde(rename(serialize = "y"))]
//~^^^^ ERROR: duplicate serde attribute `rename`
x: (),
}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
struct S {
#[serde(with = "w", serialize_with = "s")] //~^^ HELP: duplicate serde attribute `serialize_with`
#[serde(with = "w", serialize_with = "s")]
//~^^^ ERROR: duplicate serde attribute `serialize_with`
x: (),
}
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] cannot be used with tuple variants
#[derive(Serialize)]
#[serde(tag = "type")]
//~^^ ERROR: #[serde(tag = "...")] cannot be used with tuple variants
enum E {
Tuple(u8, u8),
}
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] can only be used on enums
#[derive(Serialize)]
#[serde(tag = "type")]
//~^^ ERROR: #[serde(tag = "...")] can only be used on enums
struct S;
fn main() {}
@@ -9,9 +9,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
#[serde(untagged)]
#[serde(tag = "type")] //~^^ HELP: enum cannot be both untagged and internally tagged
#[serde(tag = "type")]
//~^^^ ERROR: enum cannot be both untagged and internally tagged
enum E {
A(u8),
B(String),
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)] //~^ HELP: #[serde(untagged)] can only be used on enums
#[derive(Serialize)]
#[serde(untagged)]
//~^^ ERROR: #[serde(untagged)] can only be used on enums
struct S;
fn main() {}
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier, variant_identifier)] //~^ HELP: `field_identifier` and `variant_identifier` cannot both be set
#[derive(Deserialize)]
#[serde(field_identifier, variant_identifier)]
//~^^ ERROR: `field_identifier` and `variant_identifier` cannot both be set
enum F {
A,
B,
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(field_identifier)]
struct S; //~^^ HELP: `field_identifier` can only be used on an enum
//~^^ ERROR: `field_identifier` can only be used on an enum
struct S;
fn main() {}
@@ -9,11 +9,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(field_identifier)]
enum F {
A,
B(u8, u8), //~^^^^ HELP: field_identifier may only contain unit variants
B(u8, u8),
//~^^^^^ ERROR: field_identifier may only contain unit variants
}
fn main() {}
@@ -9,11 +9,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(field_identifier)]
enum F {
A,
Other(String), //~^^^^ HELP: `Other` must be the last variant
Other(String),
//~^^^^^ ERROR: `Other` must be the last variant
B,
}
@@ -9,10 +9,11 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
enum F {
A,
#[serde(other)] //~^^^ HELP: #[serde(other)] may only be used inside a field_identifier
#[serde(other)]
//~^^^^ ERROR: #[serde(other)] may only be used inside a field_identifier
B,
}
@@ -9,11 +9,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(field_identifier)]
enum F {
A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be on a unit variant
#[serde(other)]
//~^^^^^ ERROR: #[serde(other)] must be on a unit variant
Other(u8, u8),
}
@@ -9,11 +9,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(field_identifier)]
enum F {
A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be the last variant
#[serde(other)]
//~^^^^^ ERROR: #[serde(other)] must be the last variant
Other,
B,
}
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)] //~^ HELP: field identifiers cannot be serialized
#[derive(Serialize)]
#[serde(field_identifier)]
//~^^ ERROR: field identifiers cannot be serialized
enum F {
A,
B,
@@ -9,8 +9,9 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(variant_identifier)]
struct S; //~^^ HELP: `variant_identifier` can only be used on an enum
//~^^ ERROR: `variant_identifier` can only be used on an enum
struct S;
fn main() {}
@@ -9,11 +9,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[derive(Deserialize)]
#[serde(variant_identifier)]
enum F {
A,
B(u8, u8), //~^^^^ HELP: variant_identifier may only contain unit variants
B(u8, u8),
//~^^^^^ ERROR: variant_identifier may only contain unit variants
}
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(Deserialize)]
struct S<'de> {
//~^^ ERROR: cannot deserialize when there is a lifetime parameter called 'de
s: &'de str,
}
@@ -0,0 +1,17 @@
// 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)]
struct S {
string: String,
slice: [u8],
//~^^^^ ERROR: cannot deserialize a dynamically sized struct
}
@@ -15,10 +15,11 @@ mod remote {
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[derive(Serialize)]
#[serde(remote = "remote::S")]
struct S {
#[serde(getter = "~~~")] //~^^^ HELP: failed to parse path: "~~~"
#[serde(getter = "~~~")]
//~^^^^ ERROR: failed to parse path: "~~~"
a: u8,
}
@@ -15,8 +15,9 @@ mod remote {
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "~~~")] //~^ HELP: failed to parse path: "~~~"
#[derive(Serialize)]
#[serde(remote = "~~~")]
//~^^ ERROR: failed to parse path: "~~~"
struct S {
a: u8,
}

Some files were not shown because too many files have changed in this diff Show More