Compare commits

...

424 Commits

Author SHA1 Message Date
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
David Tolnay 7aeabddd2f Release 1.0.27 2017-12-30 22:19:41 -05:00
David Tolnay 9df8f5ecc0 Merge pull request #1132 from Lireer/uppercase
Add UPPERCASE to rename_all
2017-12-30 22:18:20 -05:00
Carl Scherer c4fad2883b Add UPPERCASE to rename_all 2017-12-31 03:12:00 +01:00
David Tolnay 9cfcd78c87 Release 1.0.26 2017-12-27 17:33:32 -05:00
David Tolnay 4751627f1c Implement De/Serialize for PhantomData where T: ?Sized 2017-12-27 17:32:49 -05:00
David Tolnay ae59c6b6d2 Release 1.0.25 2017-12-23 23:33:59 -05:00
David Tolnay 4973d7a62d Suppress errors on rustfmt line overflow
Some of the serde_derive lines inside of quote!(...) are too long. Rustfmt
cannot fix these. Will need to follow up.
2017-12-23 20:27:56 -08:00
David Tolnay ed6a1de311 Auto format attributes on their own line 2017-12-23 20:24:57 -08:00
David Tolnay ab234be025 The rustfmt rfc style is now the default 2017-12-23 20:21:52 -08:00
David Tolnay ee75e6c0e9 Format with rustfmt-nightly 0.3.4 2017-12-23 20:17:52 -08:00
David Tolnay c2b390fe63 Merge pull request #1124 from serde-rs/in-place
Rename deserialize_from to deserialize_in_place
2017-12-23 19:56:29 -08:00
David Tolnay 56d5d7f761 Rename deserialize_from to deserialize_in_place 2017-12-17 10:46:44 -08:00
David Tolnay 0b89bc920e Merge pull request #1094 from Gankro/deserialize_from
Add and derive deserialize_from
2017-12-11 21:29:15 -08:00
David Tolnay 0dac13e4db Resolve conflict with pr 1115 2017-12-11 20:59:54 -08:00
David Tolnay 0c2e91f28a Merge branch serde-rs/master into Gankro/deserialize_from 2017-12-11 20:49:23 -08:00
David Tolnay 13e7bee0e6 Eliminate need for unwrap in deserialize_from_seq 2017-12-11 18:13:13 -08:00
David Tolnay 65104aca9c Remove need for allow(unreachable_code) 2017-12-11 17:55:23 -08:00
David Tolnay 9360094ba7 Revert main_body naming change
The naming here isn't great but no need to change it in this PR.
2017-12-10 23:19:31 -08:00
David Tolnay 3700779bfa More meaningful names and types for nop_reserve 2017-12-10 23:18:08 -08:00
David Tolnay d9e894911f Move all the deserialize_from derive code behind flag 2017-12-10 23:15:14 -08:00
David Tolnay 85e3ddc2b8 Less indentiation in deserialize_from_body 2017-12-10 23:04:44 -08:00
David Tolnay ccae35d92a Do not emit deserialize_from if every field has deserialize_with 2017-12-10 22:55:28 -08:00
David Tolnay 61ca928325 Can never see getters in a deserialize_from 2017-12-10 22:46:46 -08:00
David Tolnay a93f2ebff0 Enable deserialize_from in the test suite 2017-12-10 22:46:25 -08:00
David Tolnay a45f1ae915 Remove unused dev-dependency of serde_test on deserialize_from 2017-12-10 22:02:11 -08:00
David Tolnay 9641978481 Hide deserialize_from 2017-12-10 21:55:07 -08:00
David Tolnay ffd2017c6f Use the default deserialize_from for Option<T>
The custom one was functionally identical to the default implementation given by
the Deserialize trait. If someone has benchmarks that the custom one performs
better, we can put it back.
2017-12-10 21:27:44 -08:00
David Tolnay b7eb42aa6b Release 1.0.24 2017-12-09 14:43:55 -08:00
David Tolnay 750f8ba299 Clean up trailing whitespace 2017-12-09 14:42:59 -08:00
David Tolnay 49cdef074d Merge pull request #1115 from Binero/master
Solved #1105.
2017-12-08 08:57:31 -08:00
Jeroen Bollen aa86b04714 Adressed concerns raised by @oli-obk.
Specifically:
 - Change identation in `de.rs`.
 - Make `attr::Field` take a `attr::Default` as opposed to the entire parent `attr::Container`.
2017-12-08 15:13:05 +01:00
Jeroen Bollen c887a0b472 Solved #1105.
When a field should be skipped during deserialization, it will not use its own Default implementation
when the container structure has `#[serde(default)]` set.
2017-12-06 21:14:02 +01:00
Alexis Beingessner 34936be574 test deserialize_from 2017-12-04 13:29:03 -05:00
Alexis Beingessner e354dd0c7f Derive deserialize_from for tuples and structs
This adds a new "deserialize_from" feature (default off) that opts into
deriving deserialize_from with #[derive(Deserialize)].
2017-12-04 13:23:26 -05:00
Alexis Beingessner bc221abb04 Augment builtin std/core Deserialize impls to implement deserialize_from 2017-12-04 13:23:26 -05:00
Alexis Beingessner ab5e8780ab Add deserialize_from to Deserialize 2017-12-04 13:23:26 -05:00
David Tolnay 0c34e06e51 Merge pull request #1106 from khuey/inlines
Inline various deserialization helper methods.
2017-12-02 15:57:07 -08:00
Kyle Huey 4a0c4e0c25 Mark size_hint::cautious as inline. 2017-12-01 14:31:52 -08:00
David Tolnay 8c34e0940f Release 1.0.23 2017-11-29 22:26:32 -08:00
David Tolnay eb6bf16a51 Revert "Catch wrong field names length in serde_test"
There are at least two reasonable things to expect the len field to
check: the length of the fields array passed to deserialize_struct, or
the number of field tokens. Even beyond these, in some cases it can be
useful to test deserialization with a bogus len to test how the
Deserialize impl reacts to an incorrect size_hint.

This reverts commit 436cafb0a3 which was
released in serde_test 1.0.20.
2017-11-29 22:21:05 -08:00
David Tolnay 797d049db5 Release 1.0.22 2017-11-29 20:01:43 -08:00
David Tolnay d61a373f12 Merge pull request #1104 from serde-rs/abs
Fix missing absolute paths in deserialize_seq
2017-11-29 19:58:21 -08:00
David Tolnay e0eea551b4 Fix missing absolute paths in deserialize_seq 2017-11-29 19:45:22 -08:00
David Tolnay c650a92bf7 Update to compiletest-rs 0.3 to fix "every suggestion should have at least one span" 2017-11-24 17:12:58 -08:00
David Tolnay f218f4d7bf Release 1.0.21 2017-11-15 22:24:18 -08:00
Alex Shapiro 8c0a2015be Fix error when deserializing untagged enum
Serde's `ContentDeserializer` and `ContentRefDeserializer`
cannot deserialize struct enum variant associated data when
that data is encoded as a sequence. This failure leads to
errors when decoding an enum nested in another untagged
enum. For example:

    #[derive(Serialize, Deserialize)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize)]
    enum Bar {
        B{f1: String},
    }

    let data1 = Foo::A(Bar::B{f1: "Hello".into()});
    let bytes = rmp_serde::to_vec(&data1).unwrap();
    let data2 = rmp_serde::from_slice::<Foo>(&bytes).unwrap();

Deserializing fails with the error `Syntax("data did not
match any variant of untagged enum Foo")`, but the
underlying failure occurs when decoding the associated data
of `Bar::B`.

This pull request fixes the issue by allowing
`ContentDeserializer` and `ContentRefDeserializer` to
deserialize sequence-encoded struct enum variant data.
2017-11-15 21:56:33 -08:00
142 changed files with 12254 additions and 4873 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 -5
View File
@@ -1,5 +1 @@
fn_args_layout = "Block"
array_layout = "Block"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
error_on_line_overflow = false
+27 -15
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.20" # remember to update html_root_url
version = "1.0.69" # 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"]
+78
View File
@@ -0,0 +1,78 @@
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");
}
// 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)
}
}
}
+11 -6
View File
@@ -8,7 +8,7 @@
use lib::*;
use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// An efficient way of discarding data from a deserializer.
///
@@ -45,7 +45,8 @@ use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = T;
///
@@ -54,7 +55,8 @@ use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de>
/// where
/// A: SeqAccess<'de>,
/// {
/// // Skip over the first `n` elements.
/// for i in 0..self.n {
@@ -82,19 +84,22 @@ use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
/// }
///
/// 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
+672 -191
View File
File diff suppressed because it is too large Load Diff
+313 -55
View File
@@ -52,12 +52,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 +66,7 @@
//! - PhantomData\<T\>
//! - **Wrapper types**:
//! - Box\<T\>
//! - Box\<[T]\>
//! - Box\<\[T\]\>
//! - Box\<str\>
//! - Rc\<T\>
//! - Arc\<T\>
@@ -84,10 +84,9 @@
//! - LinkedList\<T\>
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **Zero-copy types**:
//! - &str
//! - &[u8]
//! - &\[u8\]
//! - **FFI types**:
//! - CString
//! - Box\<CStr\>
@@ -98,7 +97,8 @@
//! - Path
//! - PathBuf
//! - Range\<T\>
//! - NonZero\<T\> (unstable)
//! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
@@ -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"));
@@ -494,6 +512,14 @@ impl<'a> Display for Expected + 'a {
/// [de]: https://docs.serde.rs/serde/de/index.html
/// [codegen]: https://serde.rs/codegen.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.
///
@@ -504,6 +530,35 @@ pub trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>;
/// Deserializes a value into `self` from the given Deserializer.
///
/// The purpose of this method is to allow the deserializer to reuse
/// resources and avoid copies. As such, if this method returns an error,
/// `self` will be in an indeterminate state where some parts of the struct
/// have been overwritten. Although whatever state that is will be
/// memory-safe.
///
/// 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.
///
/// If you manually implement this, your recursive deserializations should
/// use `deserialize_in_place`.
///
/// This method is stable and an official public API, but hidden from the
/// documentation because it is almost never what newbies are looking for.
/// Showing it in rustdoc would cause it to be featured more prominently
/// than it deserves.
#[doc(hidden)]
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
// Default implementation just delegates to `deserialize` impl.
*place = Deserialize::deserialize(deserializer)?;
Ok(())
}
}
/// A data structure that can be deserialized without borrowing any data from
@@ -520,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,
@@ -577,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
@@ -600,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
@@ -608,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 = ();
///
@@ -624,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.
@@ -643,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.
@@ -654,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();
@@ -670,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)?;
@@ -708,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
@@ -719,17 +795,17 @@ 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]
/// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be transient,
/// owned, or borrowed.
/// - **option**
@@ -793,6 +869,23 @@ where
/// 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.
@@ -836,6 +929,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
@@ -856,6 +963,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
@@ -1055,7 +1176,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".
@@ -1078,13 +1200,25 @@ pub trait Deserializer<'de>: Sized {
/// change, as a value serialized in human-readable mode is not required to
/// deserialize from the same data in compact mode.
#[inline]
fn is_human_readable(&self) -> bool { true }
fn is_human_readable(&self) -> bool {
true
}
}
////////////////////////////////////////////////////////////////////////////////
/// 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;
/// #
@@ -1104,7 +1238,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())
@@ -1198,6 +1333,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`].
@@ -1244,6 +1393,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`].
@@ -1475,6 +1638,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(())
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -1483,6 +1655,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.
@@ -1550,6 +1737,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.
@@ -1727,6 +1929,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.
@@ -1759,6 +1976,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`.
@@ -1784,15 +2016,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!() }
/// # }
/// ```
@@ -1819,7 +2054,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;
@@ -1827,11 +2063,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!() }
/// # }
/// ```
@@ -1872,13 +2110,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;
@@ -1886,7 +2128,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!() }
/// # }
/// ```
@@ -1914,17 +2157,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;
@@ -1946,6 +2194,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;
+184 -72
View File
@@ -37,10 +37,26 @@
use lib::*;
use de::{self, IntoDeserializer, Expected, SeqAccess};
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,14 +74,18 @@ type ErrorImpl = ();
impl de::Error for Error {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Error { err: msg.to_string().into_boxed_str() }
Error {
err: msg.to_string().into_boxed_str(),
}
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -76,6 +96,7 @@ impl de::Error for Error {
}
impl ser::Error for Error {
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -112,16 +133,20 @@ where
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer { marker: PhantomData }
UnitDeserializer {
marker: PhantomData,
}
}
}
/// 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,
@@ -129,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>
@@ -151,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,
@@ -182,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>
@@ -211,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,
@@ -239,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>
@@ -284,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,
@@ -332,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
}
}
@@ -357,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> {
@@ -401,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
}
}
@@ -426,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
@@ -476,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
}
}
@@ -502,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
@@ -555,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
}
}
@@ -581,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> {
@@ -611,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
}
}
@@ -648,17 +750,17 @@ 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 {
// First argument is the number of elements in the data, second
// argument is the number of elements expected by the Deserialize.
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInSeq(self.count)),)
Err(de::Error::invalid_length(
self.count + remaining,
&ExpectedInSeq(self.count),
))
}
}
}
@@ -681,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
}
}
@@ -796,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
}
}
@@ -842,17 +944,17 @@ 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 {
// First argument is the number of elements in the data, second
// argument is the number of elements expected by the Deserialize.
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)),)
Err(de::Error::invalid_length(
self.count + remaining,
&ExpectedInMap(self.count),
))
}
}
}
@@ -901,11 +1003,7 @@ where
Ok(value)
}
fn deserialize_tuple<V>(
self,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
@@ -914,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
}
}
@@ -1056,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>
@@ -1204,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
}
}
@@ -1223,7 +1321,12 @@ mod private {
}
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
(t, UnitOnly { marker: PhantomData })
(
t,
UnitOnly {
marker: PhantomData,
},
)
}
impl<'de, E> de::VariantAccess<'de> for UnitOnly<E>
@@ -1240,14 +1343,20 @@ mod private {
where
T: de::DeserializeSeed<'de>,
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"),)
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"newtype variant",
))
}
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"),)
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"tuple variant",
))
}
fn struct_variant<V>(
@@ -1258,7 +1367,10 @@ mod private {
where
V: de::Visitor<'de>,
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"),)
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"struct variant",
))
}
}
+4 -1
View File
@@ -12,10 +12,13 @@ pub use lib::default::Default;
pub use lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some};
pub use lib::result::Result::{self, Ok, Err};
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)*) => {};
}
+58 -55
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,30 +82,24 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.20")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.69")]
// 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
@@ -113,6 +110,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,
@@ -120,38 +118,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::{i8, i16, i32, i64, isize};
pub use self::core::{u8, u16, u32, u64, usize};
pub use self::core::{cmp, iter, mem, num, ops, 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};
@@ -162,40 +162,40 @@ mod lib {
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(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::Arc;
#[cfg(feature = "std")]
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
pub use std::boxed::Box;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::{error, net};
@@ -203,9 +203,9 @@ mod lib {
#[cfg(feature = "std")]
pub use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")]
pub use std::ffi::{CString, CStr, OsString, OsStr};
pub use std::ffi::{CStr, CString, OsStr, OsString};
#[cfg(feature = "std")]
pub use std::hash::{Hash, BuildHasher};
pub use std::hash::{BuildHasher, Hash};
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(feature = "std")]
@@ -213,12 +213,12 @@ 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;
}
////////////////////////////////////////////////////////////////////////////////
@@ -226,13 +226,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>()}
};
+1130 -193
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;
+415 -97
View File
@@ -8,10 +8,12 @@
use lib::*;
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
use self::content::{
Content, ContentSerializer, SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue,
};
/// Used to check that serde(getter) attributes return the expected type.
/// Not public API.
@@ -32,15 +34,13 @@ where
S: Serializer,
T: Serialize,
{
value.serialize(
TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
},
)
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
@@ -60,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,
}
@@ -78,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"),
}
}
@@ -92,13 +94,10 @@ where
S: Serializer,
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(
format_args!(
ser::Error::custom(format_args!(
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident,
self.variant_ident,
what),
)
self.type_ident, self.variant_ident, what
))
}
}
@@ -281,7 +280,11 @@ where
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len),)
Ok(SerializeTupleVariantAsMapValue::new(
map,
inner_variant,
len,
))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -324,7 +327,11 @@ where
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),)
Ok(SerializeStructVariantAsMapValue::new(
map,
inner_variant,
len,
))
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
@@ -402,7 +409,10 @@ mod content {
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
try!(
self.map
.serialize_value(&Content::TupleStruct(self.name, self.fields))
);
self.map.end()
}
}
@@ -444,13 +454,16 @@ mod content {
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
try!(
self.map
.serialize_value(&Content::Struct(self.name, self.fields))
);
self.map.end()
}
}
#[derive(Debug)]
enum Content {
pub enum Content {
Bool(bool),
U8(u8),
@@ -485,7 +498,12 @@ mod content {
TupleVariant(&'static str, u32, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, u32, &'static str, Vec<(&'static str, Content)>),
StructVariant(
&'static str,
u32,
&'static str,
Vec<(&'static str, Content)>,
),
}
impl Serialize for Content {
@@ -570,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 }
}
}
@@ -687,7 +705,10 @@ mod content {
where
T: Serialize,
{
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))),)
Ok(Content::NewtypeStruct(
name,
Box::new(try!(value.serialize(self))),
))
}
fn serialize_newtype_variant<T: ?Sized>(
@@ -700,32 +721,26 @@ mod content {
where
T: Serialize,
{
Ok(
Content::NewtypeVariant(
name,
variant_index,
variant,
Box::new(try!(value.serialize(self))),
),
)
Ok(Content::NewtypeVariant(
name,
variant_index,
variant,
Box::new(try!(value.serialize(self))),
))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
Ok(
SerializeSeq {
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
},
)
Ok(SerializeSeq {
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
Ok(
SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(
@@ -733,13 +748,11 @@ mod content {
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, E> {
Ok(
SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(
@@ -749,25 +762,21 @@ mod content {
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, E> {
Ok(
SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
Ok(
SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
},
)
Ok(SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
}
fn serialize_struct(
@@ -775,13 +784,11 @@ mod content {
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, E> {
Ok(
SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(
@@ -791,19 +798,17 @@ mod content {
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, E> {
Ok(
SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
struct SerializeSeq<E> {
pub struct SerializeSeq<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
@@ -829,7 +834,7 @@ mod content {
}
}
struct SerializeTuple<E> {
pub struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
@@ -855,7 +860,7 @@ mod content {
}
}
struct SerializeTupleStruct<E> {
pub struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
@@ -882,7 +887,7 @@ mod content {
}
}
struct SerializeTupleVariant<E> {
pub struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: u32,
variant: &'static str,
@@ -907,11 +912,16 @@ mod content {
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields),)
Ok(Content::TupleVariant(
self.name,
self.variant_index,
self.variant,
self.fields,
))
}
}
struct SerializeMap<E> {
pub struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
@@ -937,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()));
@@ -961,7 +972,7 @@ mod content {
}
}
struct SerializeStruct<E> {
pub struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
@@ -988,7 +999,7 @@ mod content {
}
}
struct SerializeStructVariant<E> {
pub struct SerializeStructVariant<E> {
name: &'static str,
variant_index: u32,
variant: &'static str,
@@ -1013,7 +1024,314 @@ mod content {
}
fn end(self) -> Result<Content, E> {
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields),)
Ok(Content::StructVariant(
self.name,
self.variant_index,
self.variant,
self.fields,
))
}
}
}
#[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(())
}
}
+131 -29
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")]
@@ -111,7 +122,7 @@ where
////////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
impl<T: ?Sized> Serialize for PhantomData<T> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -245,6 +256,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 +341,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 +365,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 +475,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 +536,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 +559,9 @@ impl Serialize for SystemTime {
S: Serializer,
{
use super::SerializeStruct;
let duration_since_epoch = self.duration_since(UNIX_EPOCH).expect("SystemTime must be later than 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()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
@@ -493,11 +590,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")]
@@ -513,10 +608,12 @@ impl Serialize for net::IpAddr {
}
} else {
match *self {
net::IpAddr::V4(ref a) =>
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a),
net::IpAddr::V6(ref a) =>
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a),
net::IpAddr::V4(ref a) => {
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a)
}
net::IpAddr::V6(ref a) => {
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a)
}
}
}
}
@@ -567,10 +664,12 @@ impl Serialize for net::SocketAddr {
}
} else {
match *self {
net::SocketAddr::V4(ref addr) =>
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr),
net::SocketAddr::V6(ref addr) =>
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr),
net::SocketAddr::V4(ref addr) => {
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr)
}
net::SocketAddr::V6(ref addr) => {
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr)
}
}
}
}
@@ -600,7 +699,10 @@ impl Serialize for net::SocketAddrV6 {
{
if serializer.is_human_readable() {
const MAX_LEN: usize = 47;
debug_assert_eq!(MAX_LEN, "[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len());
debug_assert_eq!(
MAX_LEN,
"[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len()
);
serialize_display_bounded_length!(self, MAX_LEN, serializer)
} else {
(self.ip(), self.port()).serialize(serializer)
+4 -2
View File
@@ -10,8 +10,10 @@
use lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
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.
+268 -73
View File
@@ -48,15 +48,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 +81,6 @@
//! - LinkedList\<T\>
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - **FFI types**:
//! - CStr
//! - CString
@@ -93,7 +92,8 @@
//! - Path
//! - PathBuf
//! - Range\<T\>
//! - NonZero\<T\> (unstable)
//! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
@@ -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),
@@ -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,27 +252,27 @@ 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]
/// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be transient,
/// owned, or borrowed.
/// - **option**
@@ -308,6 +317,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 +394,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 +421,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 +448,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 +475,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 +498,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 +509,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 +556,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 +583,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 +610,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 +633,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 +644,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 +691,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 +714,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 +740,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 +763,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 +829,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 +864,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 +898,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 +920,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 +945,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 +975,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 +1006,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 +1057,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 +1091,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)?;
@@ -1011,7 +1117,8 @@ pub trait Serializer: Sized {
///
/// 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[..] {
@@ -1037,7 +1144,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 ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
@@ -1071,7 +1179,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 +1238,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 {
@@ -1163,7 +1274,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)?;
@@ -1196,7 +1308,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::S { ref r, ref g, ref b } => {
@@ -1233,7 +1346,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))
/// }
@@ -1271,7 +1385,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 +1426,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 +1467,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 +1509,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".
@@ -1412,11 +1530,15 @@ pub trait Serializer: Sized {
/// change, as a value serialized in human-readable mode is not required to
/// deserialize from the same data in compact mode.
#[inline]
fn is_human_readable(&self) -> bool { true }
fn is_human_readable(&self) -> bool {
true
}
}
/// Returned from `Serializer::serialize_seq`.
///
/// # Example use
///
/// ```rust
/// # use std::marker::PhantomData;
/// #
@@ -1439,10 +1561,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 {
@@ -1452,6 +1576,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;
@@ -1470,6 +1601,8 @@ pub trait SerializeSeq {
/// Returned from `Serializer::serialize_tuple`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
///
@@ -1482,12 +1615,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)?;
@@ -1526,10 +1661,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 {
@@ -1539,6 +1676,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;
@@ -1557,6 +1701,8 @@ pub trait SerializeTuple {
/// Returned from `Serializer::serialize_tuple_struct`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct};
///
@@ -1564,7 +1710,8 @@ pub trait SerializeTuple {
///
/// 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)?;
@@ -1574,6 +1721,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;
@@ -1592,6 +1746,8 @@ pub trait SerializeTupleStruct {
/// Returned from `Serializer::serialize_tuple_variant`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant};
///
@@ -1602,7 +1758,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) => {
@@ -1622,6 +1779,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;
@@ -1640,6 +1804,8 @@ pub trait SerializeTupleVariant {
/// Returned from `Serializer::serialize_map`.
///
/// # Example use
///
/// ```rust
/// # use std::marker::PhantomData;
/// #
@@ -1663,11 +1829,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 {
@@ -1677,6 +1845,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;
@@ -1740,6 +1915,8 @@ pub trait SerializeMap {
/// Returned from `Serializer::serialize_struct`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct};
///
@@ -1751,7 +1928,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)?;
@@ -1761,6 +1939,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;
@@ -1790,6 +1975,8 @@ pub trait SerializeStruct {
/// Returned from `Serializer::serialize_struct_variant`.
///
/// # Example use
///
/// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStructVariant};
///
@@ -1799,7 +1986,8 @@ pub trait SerializeStruct {
///
/// 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 } => {
@@ -1813,6 +2001,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;
+10 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.20" # remember to update html_root_url
version = "1.0.69" # 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,20 +8,24 @@ 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" }
[features]
default = []
deserialize_in_place = []
[lib]
name = "serde_derive"
proc-macro = true
[dependencies]
quote = "0.3.8"
serde_derive_internals = { version = "=0.17.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
+202 -157
View File
@@ -8,33 +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()
}
},
)
.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()
}
@@ -46,27 +44,47 @@ 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
}
@@ -81,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.
@@ -123,67 +154,69 @@ 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() {
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);
}
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 {
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(),
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
)
},
);
.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::Type::Path(bounded_ty),
colon_token: <Token![:]>::default(),
// the bound e.g. Serialize
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
}
@@ -194,81 +227,93 @@ 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();
let bound = syn::Lifetime::new(lifetime, Span::call_site());
let def = syn::LifetimeDef {
attrs: Vec::new(),
lifetime: bound.clone(),
colon_token: None,
bounds: Punctuated::new(),
};
for lifetime_def in &mut generics.lifetimes {
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
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()
}
for ty_param in &mut generics.ty_params {
ty_param
.bounds
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
}
generics
.lifetimes
.push(
syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
},
);
generics
}
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(),
},
)
})
}
+1527 -490
View File
File diff suppressed because it is too large Load Diff
+20 -13
View File
@@ -6,14 +6,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{Tokens, ToTokens};
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,17 +59,24 @@ 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<TokenStream> for Fragment {
fn as_ref(&self) -> &TokenStream {
match *self {
Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block,
}
}
}
+178
View File
@@ -0,0 +1,178 @@
// 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::attr;
use internals::check;
use internals::{Ctxt, Derive};
use syn;
use syn::punctuated::Punctuated;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
pub data: Data<'a>,
pub generics: &'a syn::Generics,
}
pub enum Data<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub member: syn::Member,
pub attrs: attr::Field,
pub ty: &'a syn::Type,
pub original: &'a syn::Field,
}
#[derive(Copy, Clone)]
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive) -> Container<'a> {
let mut attrs = attr::Container::from_ast(cx, item);
let mut data = match item.data {
syn::Data::Enum(ref data) => {
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
}
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");
}
};
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 field in &mut variant.fields {
if field.attrs.flatten() {
has_flatten = true;
}
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
},
Data::Struct(_, ref mut fields) => for field in fields {
if field.attrs.flatten() {
has_flatten = true;
}
field.attrs.rename_by_rule(attrs.rename_all());
},
}
if has_flatten {
attrs.mark_has_flatten();
}
let mut item = Container {
ident: item.ident.clone(),
attrs: attrs,
data: data,
generics: &item.generics,
};
check::check(cx, &mut item, derive);
item
}
}
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Data::Enum(ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Data::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
fn enum_from_ast<'a>(
cx: &Ctxt,
variants: &'a Punctuated<syn::Variant, Token![,]>,
container_default: &attr::Default,
) -> Vec<Variant<'a>> {
variants
.iter()
.map(|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) =
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
}
})
.collect()
}
fn struct_from_ast<'a>(
cx: &Ctxt,
fields: &'a syn::Fields,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
match *fields {
syn::Fields::Named(ref fields) => (
Style::Struct,
fields_from_ast(cx, &fields.named, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) => (
Style::Tuple,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::Fields::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(
cx: &Ctxt,
fields: &'a Punctuated<syn::Field, Token![,]>,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(|(i, field)| Field {
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,
original: field,
})
.collect()
}
File diff suppressed because it is too large Load Diff
@@ -7,19 +7,21 @@
// 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,
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "UPPERCASE" style.
UPPERCASE,
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
@@ -31,7 +33,7 @@ pub enum RenameRule {
/// Rename direct children to "kebab-case" style.
KebabCase,
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
ScreamingKebabCase
ScreamingKebabCase,
}
impl RenameRule {
@@ -39,6 +41,7 @@ impl RenameRule {
match *self {
None | PascalCase => variant.to_owned(),
LowerCase => variant.to_ascii_lowercase(),
UPPERCASE => variant.to_ascii_uppercase(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
@@ -52,13 +55,16 @@ impl RenameRule {
}
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-")
ScreamingKebabCase => ScreamingSnakeCase
.apply_to_variant(variant)
.replace('_', "-"),
}
}
pub fn apply_to_field(&self, field: &str) -> String {
match *self {
None | LowerCase | SnakeCase => field.to_owned(),
UPPERCASE => field.to_ascii_uppercase(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
@@ -80,7 +86,7 @@ impl RenameRule {
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-")
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
}
}
}
@@ -91,6 +97,7 @@ impl FromStr for RenameRule {
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str {
"lowercase" => Ok(LowerCase),
"UPPERCASE" => Ok(UPPERCASE),
"PascalCase" => Ok(PascalCase),
"camelCase" => Ok(CamelCase),
"snake_case" => Ok(SnakeCase),
@@ -104,34 +111,58 @@ impl FromStr for RenameRule {
#[test]
fn rename_variants() {
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in
&[
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
("A", "a", "a", "a", "A", "a", "A"),
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
(
"Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
),
(
"VeryTasty",
"verytasty",
"VERYTASTY",
"veryTasty",
"very_tasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("A", "a", "A", "a", "a", "A", "a", "A"),
("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(UPPERCASE.apply_to_variant(original), upper);
assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab);
assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab);
assert_eq!(
ScreamingKebabCase.apply_to_variant(original),
screaming_kebab
);
}
}
#[test]
fn rename_fields() {
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in
&[
("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
("a", "A", "a", "A", "a", "A"),
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
(
"outcome", "OUTCOME", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
),
(
"very_tasty",
"VERY_TASTY",
"VeryTasty",
"veryTasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("a", "A", "A", "a", "A", "a", "A"),
("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(UPPERCASE.apply_to_field(original), upper);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
assert_eq!(SnakeCase.apply_to_field(original), original);
+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 {
@@ -16,7 +17,9 @@ pub struct Ctxt {
impl Ctxt {
pub fn new() -> Self {
Ctxt { errors: RefCell::new(Some(Vec::new())) }
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
}
pub fn error<T: Display>(&self, msg: T) {
@@ -46,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.17.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,
}
+42 -19
View File
@@ -22,45 +22,68 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.20")]
#![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.69")]
#![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"]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate serde_derive_internals as internals;
#[macro_use]
extern crate syn;
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);
}
}
+140
View File
@@ -0,0 +1,140 @@
use proc_macro2::{Span, TokenStream};
use syn::Ident;
use internals::ast::{Container, Data, Field, Style};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
// never has its fields referenced and an enum annotated with remote derive
// never has its variants constructed.
//
// warning: field is never used: `i`
// --> src/main.rs:4:20
// |
// 4 | struct StructDef { i: i32 }
// | ^^^^^^
//
// warning: variant is never constructed: `V`
// --> src/main.rs:8:16
// |
// 8 | enum EnumDef { V }
// | ^
//
pub fn pretend_used(cont: &Container) -> TokenStream {
let pretend_fields = pretend_fields_used(cont);
let pretend_variants = pretend_variants_used(cont);
quote! {
#pretend_fields
#pretend_variants
}
}
// For structs with named fields, expands to:
//
// match None::<T> {
// Some(T { a: ref __v0, b: ref __v1 }) => {}
// _ => {}
// }
//
// For enums, expands to the following but only including struct variants:
//
// match None::<T> {
// Some(T::A { a: ref __v0 }) => {}
// Some(T::B { b: ref __v0 }) => {}
// _ => {}
// }
//
// The `ref` is important in case the user has written a Drop impl on their
// type. Rust does not allow destructuring a struct or enum that has a Drop
// impl.
fn pretend_fields_used(cont: &Container) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = &variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
Data::Struct(_, _) => {
return quote!();
}
};
quote! {
match _serde::export::None::<#type_ident #ty_generics> {
#(
_serde::export::Some(#patterns) => {}
)*
_ => {}
}
}
}
// Expands to one of these per enum variant:
//
// match None {
// Some((__v0, __v1,)) => {
// let _ = E::V { a: __v0, b: __v1 };
// }
// _ => {}
// }
//
fn pretend_variants_used(cont: &Container) -> TokenStream {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
};
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let turbofish = ty_generics.as_turbofish();
let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.collect::<Vec<_>>();
let pat = match variant.style {
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote!({ #(#members: #placeholders),* })
}
Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
Style::Unit => quote!(),
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
}
});
quote!(#(#cases)*)
}
fn struct_pattern(fields: &[Field]) -> TokenStream {
let members = fields.iter().map(|field| &field.member);
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#members: ref #placeholders),* })
}
+582 -339
View File
File diff suppressed because it is too large Load Diff
+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);
}
}
}
}
}
}
+8 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive_internals"
version = "0.17.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,15 @@ 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" }
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+23
View File
@@ -0,0 +1,23 @@
// 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/
-144
View File
@@ -1,144 +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 syn;
use attr;
use check;
use Ctxt;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
pub body: Body<'a>,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a syn::Ty,
}
#[derive(Copy, Clone)]
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
let 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)),
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data, None);
Body::Struct(style, fields)
}
};
match body {
Body::Enum(ref mut variants) => {
for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
}
}
Body::Struct(_, ref mut fields) => {
for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
}
}
}
let item = Container {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: &item.generics,
};
check::check(cx, &item);
item
}
}
impl<'a> Body<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
variants
.iter()
.map(
|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
}
},
)
.collect()
}
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields, attrs))
}
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(
|(i, field)| {
Field {
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field, attrs),
ty: &field.ty,
}
},
)
.collect()
}
File diff suppressed because it is too large Load Diff
-152
View File
@@ -1,152 +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));
}
}
}
}
}
+5 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.20" # remember to update html_root_url
version = "1.0.69" # 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,14 +8,14 @@ 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]
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+18 -2
View File
@@ -184,11 +184,27 @@ where
T: Deserialize<'de> + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) {
Ok(v) => assert_eq!(v, *value),
let mut deserialized_val = match T::deserialize(&mut de) {
Ok(v) => {
assert_eq!(v, *value);
v
}
Err(e) => panic!("tokens failed to deserialize: {}", e),
};
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
// Do the same thing for deserialize_in_place. This isn't *great* because a
// no-op impl of deserialize_in_place can technically succeed here. Still,
// this should catch a lot of junk.
let mut de = Deserializer::new(tokens);
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
Ok(()) => {
assert_eq!(deserialized_val, *value);
}
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
}
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
File diff suppressed because it is too large Load Diff
+87 -70
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> {
@@ -95,15 +97,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(
visitor.visit_seq(
DeserializerSeqVisitor {
de: self,
len: len,
end: end,
},
)
);
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
end: end,
},));
assert_next_token!(self, end);
Ok(value)
}
@@ -117,15 +115,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(
visitor.visit_map(
DeserializerMapVisitor {
de: self,
len: len,
end: end,
},
)
);
let value = try!(visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
end: end,
},));
assert_next_token!(self, end);
Ok(value)
}
@@ -135,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>
@@ -169,7 +163,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
Token::TupleStruct { len, .. } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
Token::TupleStruct { len, .. } => {
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
Token::Enum { .. } => {
@@ -195,17 +191,28 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
}
}
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
Token::NewtypeVariant { variant, .. } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
}
Token::TupleVariant { variant, .. } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
}
Token::StructVariant { variant, .. } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
}
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => {
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Any,
)),
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Seq,
)),
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Map,
)),
Token::SeqEnd
| Token::TupleEnd
| Token::TupleStructEnd
| Token::MapEnd
| Token::StructEnd
| Token::TupleVariantEnd
| Token::StructVariantEnd => {
unexpected!(token);
}
}
@@ -216,8 +223,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit |
Token::None => {
Token::Unit | Token::None => {
self.next_token();
visitor.visit_none()
}
@@ -244,10 +250,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
Token::UnitVariant { name: n, .. } |
Token::NewtypeVariant { name: n, .. } |
Token::TupleVariant { name: n, .. } |
Token::StructVariant { name: n, .. } if name == n => {
Token::UnitVariant { name: n, .. }
| Token::NewtypeVariant { name: n, .. }
| Token::TupleVariant { name: n, .. }
| Token::StructVariant { name: n, .. } if name == n =>
{
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
_ => {
@@ -269,7 +276,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
}
}
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
@@ -287,8 +298,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit |
Token::UnitStruct { .. } => {
Token::Unit | Token::UnitStruct { .. } => {
self.next_token();
visitor.visit_unit()
}
@@ -352,8 +362,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>,
{
match self.peek_token() {
Token::Struct { .. } => {
assert_next_token!(self, Token::Struct { name: name, len: fields.len() });
Token::Struct { len: n, .. } => {
assert_next_token!(self, Token::Struct { name: name, len: n });
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
}
Token::Map { .. } => {
@@ -448,10 +458,10 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
V: DeserializeSeed<'de>,
{
match self.de.peek_token() {
Token::UnitVariant { variant: v, .. } |
Token::NewtypeVariant { variant: v, .. } |
Token::TupleVariant { variant: v, .. } |
Token::StructVariant { variant: v, .. } => {
Token::UnitVariant { variant: v, .. }
| Token::NewtypeVariant { variant: v, .. }
| Token::TupleVariant { variant: v, .. }
| Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
Ok((value, self))
@@ -505,7 +515,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
unexpected!(token);
}
}
Token::Seq { len: Some(enum_len) } => {
Token::Seq {
len: Some(enum_len),
} => {
let token = self.de.next_token();
if len == enum_len {
@@ -518,7 +530,11 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
}
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
@@ -533,7 +549,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
unexpected!(token);
}
}
Token::Map { len: Some(enum_len) } => {
Token::Map {
len: Some(enum_len),
} => {
let token = self.de.next_token();
if fields.len() == enum_len {
@@ -581,10 +599,9 @@ 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 })
.map(Some)
}
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),
None => Ok(None),
@@ -640,8 +657,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
}
}
+7 -3
View File
@@ -9,7 +9,7 @@
use std::error;
use std::fmt::{self, Display};
use serde::{ser, de};
use serde::{de, ser};
#[derive(Clone, Debug)]
pub struct Error {
@@ -18,13 +18,17 @@ pub struct Error {
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() }
Error {
msg: msg.to_string(),
}
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() }
Error {
msg: msg.to_string(),
}
}
}
+30 -22
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,33 +161,35 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.20")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.69")]
#![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};
+3 -3
View File
@@ -45,7 +45,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 +56,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
);
+18 -12
View File
@@ -232,7 +232,10 @@ pub enum Token {
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
/// # }
/// ```
UnitVariant { name: &'static str, variant: &'static str },
UnitVariant {
name: &'static str,
variant: &'static str,
},
/// The header to a serialized newtype struct of the given name.
///
@@ -286,7 +289,10 @@ pub enum Token {
/// ]);
/// # }
/// ```
NewtypeVariant { name: &'static str, variant: &'static str },
NewtypeVariant {
name: &'static str,
variant: &'static str,
},
/// The header to a sequence.
///
@@ -391,7 +397,11 @@ pub enum Token {
/// ]);
/// # }
/// ```
TupleVariant { name: &'static str, variant: &'static str, len: usize },
TupleVariant {
name: &'static str,
variant: &'static str,
len: usize,
},
/// An indicator of the end of a tuple variant.
TupleVariantEnd,
@@ -425,10 +435,6 @@ pub enum Token {
/// The header of a struct.
///
/// When testing deserialization, the `len` field must match the number of
/// fields that the struct expects to deserialize. This may be different
/// from the number of fields contained in the input tokens.
///
/// After this header are the fields of the struct, followed by `StructEnd`.
///
/// ```rust
@@ -465,10 +471,6 @@ pub enum Token {
/// The header of a struct variant of an enum.
///
/// When testing deserialization, the `len` field must match the number of
/// fields that the struct variant expects to deserialize. This may be
/// different from the number of fields contained in the input tokens.
///
/// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`.
///
@@ -496,7 +498,11 @@ pub enum Token {
/// ]);
/// # }
/// ```
StructVariant { name: &'static str, variant: &'static str, len: usize },
StructVariant {
name: &'static str,
variant: &'static str,
len: usize,
},
/// An indicator of the end of a struct variant.
StructVariantEnd,
+3 -2
View File
@@ -9,10 +9,11 @@ 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" }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.2", optional = true }
compiletest_rs = { version = "0.3", optional = true }
+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() {}
@@ -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(#[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() {}

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