Compare commits

...

285 Commits

Author SHA1 Message Date
David Tolnay 85c73ef8de Release 1.0.206 2024-08-11 00:08:37 -07:00
David Tolnay 5ba1796a7e Resolve doc_markdown pedantic lint on regression test function
warning: you should put bare URLs between `<`/`>` or make a proper Markdown link
        --> test_suite/tests/test_annotations.rs:2383:25
         |
    2383 | /// Regression test for https://github.com/serde-rs/serde/issues/1904
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<https://github.com/serde-rs/serde/issues/1904>`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
         = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic`
         = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_markdown)]`
2024-08-11 00:08:16 -07:00
David Tolnay e52b7b380f Touch up PR 2567 2024-08-11 00:05:56 -07:00
David Tolnay 84c7419652 Merge pull request #2794 from dtolnay/neverread
Temporarily ignore collection_is_never_read on FlattenSkipDeserializing
2024-08-11 00:05:31 -07:00
David Tolnay 536221b1f9 Temporarily ignore collection_is_never_read on FlattenSkipDeserializing
error: collection is never read
       --> test_suite/tests/test_gen.rs:723:25
        |
    723 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:23:9
        |
    23  | #![deny(clippy::collection_is_never_read)]
        |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2024-08-10 23:59:23 -07:00
David Tolnay fc55ac70d3 Merge pull request #2567 from Mingun/fix-2565
Correctly process flatten fields in enum variants
2024-08-10 23:28:22 -07:00
Mingun 2afe5b4ef9 Add regression test for issue #2792 2024-08-10 21:29:39 +05:00
Mingun b4ec2595c9 Correctly process flatten fields in enum variants
- Fix incorrect deserialization of variants that doesn't contain flatten field when other contains
- Fix a panic when deriving `Deserialize` for an enum with tuple and struct with flatten field

Fixes (2):
    regression::issue2565::simple_variant
    regression::issue1904 (compilation)
2024-08-09 19:59:23 +05:00
Mingun c3ac7b675a Add regression test for issue #1904
Currently panics in derive:

error: proc-macro derive panicked
    --> test_suite\tests\test_annotations.rs:2386:25
     |
2386 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
     |                         ^^^^^^^^^^^
     |
     = help: message: assertion failed: !cattrs.has_flatten()

error: proc-macro derive panicked
  --> test_suite\tests\regression\issue1904.rs:57:10
   |
57 | #[derive(Deserialize)]
   |          ^^^^^^^^^^^
   |
   = help: message: assertion failed: !cattrs.has_flatten()

error: proc-macro derive panicked
  --> test_suite\tests\regression\issue1904.rs:47:10
   |
47 | #[derive(Deserialize)]
   |          ^^^^^^^^^^^
   |
   = help: message: assertion failed: !cattrs.has_flatten()

error: proc-macro derive panicked
  --> test_suite\tests\regression\issue1904.rs:37:10
   |
37 | #[derive(Deserialize)]
   |          ^^^^^^^^^^^
   |
   = help: message: assertion failed: !cattrs.has_flatten()

error: proc-macro derive panicked
  --> test_suite\tests\regression\issue1904.rs:27:10
   |
27 | #[derive(Deserialize)]
   |          ^^^^^^^^^^^
   |
   = help: message: assertion failed: !cattrs.has_flatten()

error: proc-macro derive panicked
  --> test_suite\tests\regression\issue1904.rs:16:10
   |
16 | #[derive(Deserialize)]
   |          ^^^^^^^^^^^
   |
   = help: message: assertion failed: !cattrs.has_flatten()

error: proc-macro derive panicked
 --> test_suite\tests\regression\issue1904.rs:7:10
  |
7 | #[derive(Deserialize)]
  |          ^^^^^^^^^^^
  |
  = help: message: assertion failed: !cattrs.has_flatten()
2024-08-09 19:55:56 +05:00
Mingun 24614e44bf Add regression test for issue #2565
failures (1):
    regression::issue2565::simple_variant
2024-08-09 19:53:14 +05:00
David Tolnay 9b868ef831 Release 1.0.205 2024-08-07 18:53:21 -07:00
David Tolnay c3eaf76430 Merge pull request #2791 from dtolnay/flatten
Skip collecting unmatched fields in variants that do not use flatten
2024-08-07 18:52:21 -07:00
David Tolnay 32958dec3b Skip collecting unmatched fields in variants that do not use flatten 2024-08-07 18:43:47 -07:00
David Tolnay d64a97ba1e Ignore confusable_idents warning in test
error: found both `σ` and `o` as identifiers, which look alike
       --> test_suite/tests/test_gen.rs:734:13
        |
    292 |         σ: f64,
        |         - other identifier used here
    ...
    734 |             o: T,
        |             ^ this identifier can be confused with `σ`
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(confusable_idents)]` implied by `#[deny(warnings)]`
2024-08-07 18:19:51 -07:00
David Tolnay c3df3372a1 Add test of flatten in enum
error: collection is never read
       --> test_suite/tests/test_gen.rs:728:25
        |
    728 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2024-08-07 18:19:17 -07:00
David Tolnay 8764353fe2 Enable collection_is_never_read nursury lint in test
error: collection is never read
       --> test_suite/tests/test_gen.rs:722:25
        |
    722 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:22:9
        |
    22  | #![deny(clippy::collection_is_never_read)]
        |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2024-08-07 18:16:55 -07:00
David Tolnay e08c5de5dd Merge pull request #2785 from Mingun/serialize_entry-in-flatten-newtype-variant
Use serialize_entry instead of serialize_key + serialize_value when serialize flatten newtype enum variant
2024-08-05 00:17:58 -07:00
Mingun bc5af506bd Use serialize_entry instead of serialize_key + serialize_value when serialize flatten newtype enum variant
Serializers that reimplements serialize_entry will get benefits from that
2024-08-03 14:49:38 +05:00
David Tolnay 28a092261b Work around test suite dead code warnings in nightly-2024-07-07
warning: struct `Cows` is never constructed
       --> test_suite/tests/test_borrow.rs:165:12
        |
    165 |     struct Cows<'a, 'b> {
        |            ^^^^

    warning: struct `Wrap` is never constructed
       --> test_suite/tests/test_borrow.rs:181:12
        |
    181 |     struct Wrap<'a, 'b> {
        |            ^^^^

    warning: struct `StructSkipDefaultGeneric` is never constructed
      --> test_suite/tests/test_de.rs:96:8
       |
    96 | struct StructSkipDefaultGeneric<T> {
       |        ^^^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `NonAsciiIdents` is never constructed
       --> test_suite/tests/test_gen.rs:290:12
        |
    290 |     struct NonAsciiIdents {
        |            ^^^^^^^^^^^^^^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[warn(dead_code)]` implied by `#[warn(warnings)]`

    warning: struct `EmptyBraced` is never constructed
       --> test_suite/tests/test_gen.rs:295:12
        |
    295 |     struct EmptyBraced {}
        |            ^^^^^^^^^^^

    warning: struct `EmptyBracedDenyUnknown` is never constructed
       --> test_suite/tests/test_gen.rs:299:12
        |
    299 |     struct EmptyBracedDenyUnknown {}
        |            ^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `BracedSkipAll` is never constructed
       --> test_suite/tests/test_gen.rs:302:12
        |
    302 |     struct BracedSkipAll {
        |            ^^^^^^^^^^^^^

    warning: struct `BracedSkipAllDenyUnknown` is never constructed
       --> test_suite/tests/test_gen.rs:309:12
        |
    309 |     struct BracedSkipAllDenyUnknown {
        |            ^^^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `EmptyTuple` is never constructed
       --> test_suite/tests/test_gen.rs:315:12
        |
    315 |     struct EmptyTuple();
        |            ^^^^^^^^^^

    warning: struct `EmptyTupleDenyUnknown` is never constructed
       --> test_suite/tests/test_gen.rs:319:12
        |
    319 |     struct EmptyTupleDenyUnknown();
        |            ^^^^^^^^^^^^^^^^^^^^^

    warning: struct `TupleSkipAll` is never constructed
       --> test_suite/tests/test_gen.rs:322:12
        |
    322 |     struct TupleSkipAll(#[serde(skip_deserializing)] u8);
        |            ^^^^^^^^^^^^

    warning: struct `TupleSkipAllDenyUnknown` is never constructed
       --> test_suite/tests/test_gen.rs:326:12
        |
    326 |     struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
        |            ^^^^^^^^^^^^^^^^^^^^^^^

    warning: enum `EmptyEnum` is never used
       --> test_suite/tests/test_gen.rs:329:10
        |
    329 |     enum EmptyEnum {}
        |          ^^^^^^^^^

    warning: enum `EmptyEnumDenyUnknown` is never used
       --> test_suite/tests/test_gen.rs:333:10
        |
    333 |     enum EmptyEnumDenyUnknown {}
        |          ^^^^^^^^^^^^^^^^^^^^

    warning: enum `EnumSkipAll` is never used
       --> test_suite/tests/test_gen.rs:336:10
        |
    336 |     enum EnumSkipAll {
        |          ^^^^^^^^^^^

    warning: enum `EmptyVariants` is never used
       --> test_suite/tests/test_gen.rs:343:10
        |
    343 |     enum EmptyVariants {
        |          ^^^^^^^^^^^^^

    warning: enum `EmptyVariantsDenyUnknown` is never used
       --> test_suite/tests/test_gen.rs:355:10
        |
    355 |     enum EmptyVariantsDenyUnknown {
        |          ^^^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `UnitDenyUnknown` is never constructed
       --> test_suite/tests/test_gen.rs:367:12
        |
    367 |     struct UnitDenyUnknown;
        |            ^^^^^^^^^^^^^^^

    warning: struct `EmptyArray` is never constructed
       --> test_suite/tests/test_gen.rs:370:12
        |
    370 |     struct EmptyArray {
        |            ^^^^^^^^^^

    warning: enum `Or` is never used
       --> test_suite/tests/test_gen.rs:374:10
        |
    374 |     enum Or<A, B> {
        |          ^^

    warning: enum `OrDef` is never used
       --> test_suite/tests/test_gen.rs:381:10
        |
    381 |     enum OrDef<A, B> {
        |          ^^^^^

    warning: struct `Str` is never constructed
       --> test_suite/tests/test_gen.rs:386:12
        |
    386 |     struct Str<'a>(&'a str);
        |            ^^^

    warning: struct `StrDef` is never constructed
       --> test_suite/tests/test_gen.rs:390:12
        |
    390 |     struct StrDef<'a>(&'a str);
        |            ^^^^^^

    warning: struct `Remote` is never constructed
       --> test_suite/tests/test_gen.rs:393:12
        |
    393 |     struct Remote<'a> {
        |            ^^^^^^

    warning: enum `BorrowVariant` is never used
       --> test_suite/tests/test_gen.rs:401:10
        |
    401 |     enum BorrowVariant<'a> {
        |          ^^^^^^^^^^^^^

    warning: struct `RemoteVisibility` is never constructed
       --> test_suite/tests/test_gen.rs:418:12
        |
    418 |     struct RemoteVisibility {
        |            ^^^^^^^^^^^^^^^^

    warning: struct `FlattenDenyUnknown` is never constructed
       --> test_suite/tests/test_gen.rs:551:12
        |
    551 |     struct FlattenDenyUnknown<T> {
        |            ^^^^^^^^^^^^^^^^^^

    warning: struct `StaticStrStruct` is never constructed
       --> test_suite/tests/test_gen.rs:557:12
        |
    557 |     struct StaticStrStruct<'a> {
        |            ^^^^^^^^^^^^^^^

    warning: struct `StaticStrTupleStruct` is never constructed
       --> test_suite/tests/test_gen.rs:563:12
        |
    563 |     struct StaticStrTupleStruct<'a>(&'a str, &'static str);
        |            ^^^^^^^^^^^^^^^^^^^^

    warning: struct `StaticStrNewtypeStruct` is never constructed
       --> test_suite/tests/test_gen.rs:566:12
        |
    566 |     struct StaticStrNewtypeStruct(&'static str);
        |            ^^^^^^^^^^^^^^^^^^^^^^

    warning: enum `StaticStrEnum` is never used
       --> test_suite/tests/test_gen.rs:569:10
        |
    569 |     enum StaticStrEnum<'a> {
        |          ^^^^^^^^^^^^^

    warning: enum `AdjacentlyTaggedVoid` is never used
       --> test_suite/tests/test_gen.rs:652:10
        |
    652 |     enum AdjacentlyTaggedVoid {}
        |          ^^^^^^^^^^^^^^^^^^^^

    warning: struct `ImplicitlyBorrowedOption` is never constructed
       --> test_suite/tests/test_gen.rs:665:12
        |
    665 |     struct ImplicitlyBorrowedOption<'a> {
        |            ^^^^^^^^^^^^^^^^^^^^^^^^

    warning: enum `UntaggedNewtypeVariantWith` is never used
       --> test_suite/tests/test_gen.rs:672:10
        |
    672 |     enum UntaggedNewtypeVariantWith {
        |          ^^^^^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `TransparentWith` is never constructed
       --> test_suite/tests/test_gen.rs:682:12
        |
    682 |     struct TransparentWith {
        |            ^^^^^^^^^^^^^^^

    warning: struct `FlattenSkipSerializing` is never constructed
       --> test_suite/tests/test_gen.rs:712:12
        |
    712 |     struct FlattenSkipSerializing<T> {
        |            ^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `FlattenSkipSerializingIf` is never constructed
       --> test_suite/tests/test_gen.rs:719:12
        |
    719 |     struct FlattenSkipSerializingIf<T> {
        |            ^^^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `FlattenSkipDeserializing` is never constructed
       --> test_suite/tests/test_gen.rs:725:12
        |
    725 |     struct FlattenSkipDeserializing<T> {
        |            ^^^^^^^^^^^^^^^^^^^^^^^^

    warning: enum `Message` is never used
       --> test_suite/tests/test_gen.rs:732:10
        |
    732 |     enum Message {
        |          ^^^^^^^

    warning: struct `MacroRules` is never constructed
       --> test_suite/tests/test_gen.rs:751:20
        |
    751 |             struct MacroRules<'a> {
        |                    ^^^^^^^^^^
    ...
    758 |     deriving!(&'a str);
        |     ------------------ in this macro invocation
        |
        = note: this warning originates in the macro `deriving` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: struct `BorrowLifetimeInsideMacro` is never constructed
       --> test_suite/tests/test_gen.rs:767:12
        |
    767 |     struct BorrowLifetimeInsideMacro<'a> {
        |            ^^^^^^^^^^^^^^^^^^^^^^^^^

    warning: struct `GenericUnitStruct` is never constructed
       --> test_suite/tests/test_gen.rs:782:12
        |
    782 |     struct GenericUnitStruct<const N: usize>;
        |            ^^^^^^^^^^^^^^^^^

    warning: enum `InternallyTagged` is never used
       --> test_suite/tests/test_gen.rs:869:6
        |
    869 | enum InternallyTagged {
        |      ^^^^^^^^^^^^^^^^

    warning: function `deserialize_generic` is never used
       --> test_suite/tests/test_gen.rs:880:4
        |
    880 | fn deserialize_generic<'de, T, D>(deserializer: D) -> StdResult<T, D::Error>
        |    ^^^^^^^^^^^^^^^^^^^

    warning: struct `Restricted` is never constructed
       --> test_suite/tests/test_gen.rs:643:20
        |
    643 |             struct Restricted {
        |                    ^^^^^^^^^^

    warning: struct `Test` is never constructed
      --> test_suite/tests/test_remote.rs:95:8
       |
    95 | struct Test {
       |        ^^^^

    warning: struct `UnitDef` is never constructed
       --> test_suite/tests/test_remote.rs:135:8
        |
    135 | struct UnitDef;
        |        ^^^^^^^

    warning: struct `PrimitivePubDef` is never constructed
       --> test_suite/tests/test_remote.rs:143:8
        |
    143 | struct PrimitivePubDef(u8);
        |        ^^^^^^^^^^^^^^^

    warning: struct `NewtypePubDef` is never constructed
       --> test_suite/tests/test_remote.rs:151:8
        |
    151 | struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
        |        ^^^^^^^^^^^^^

    warning: struct `TuplePubDef` is never constructed
       --> test_suite/tests/test_remote.rs:162:8
        |
    162 | struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
        |        ^^^^^^^^^^^

    warning: struct `StructPubDef` is never constructed
       --> test_suite/tests/test_remote.rs:177:8
        |
    177 | struct StructPubDef {
        |        ^^^^^^^^^^^^

    warning: struct `StructConcrete` is never constructed
       --> test_suite/tests/test_remote.rs:193:8
        |
    193 | struct StructConcrete {
        |        ^^^^^^^^^^^^^^

    warning: enum `EnumConcrete` is never used
       --> test_suite/tests/test_remote.rs:199:6
        |
    199 | enum EnumConcrete {
        |      ^^^^^^^^^^^^

    warning: enum `ErrorKind` is never used
       --> test_suite/tests/test_remote.rs:204:6
        |
    204 | enum ErrorKind {
        |      ^^^^^^^^^

    warning: enum `ErrorKindDef` is never used
       --> test_suite/tests/test_remote.rs:214:6
        |
    214 | enum ErrorKindDef {
        |      ^^^^^^^^^^^^

    warning: struct `PrimitivePub` is never constructed
      --> test_suite/tests/test_remote.rs:10:16
       |
    10 |     pub struct PrimitivePub(pub u8);
       |                ^^^^^^^^^^^^

    warning: struct `NewtypePub` is never constructed
      --> test_suite/tests/test_remote.rs:14:16
       |
    14 |     pub struct NewtypePub(pub Unit);
       |                ^^^^^^^^^^

    warning: struct `TuplePub` is never constructed
      --> test_suite/tests/test_remote.rs:18:16
       |
    18 |     pub struct TuplePub(pub u8, pub Unit);
       |                ^^^^^^^^

    warning: struct `StructPub` is never constructed
      --> test_suite/tests/test_remote.rs:25:16
       |
    25 |     pub struct StructPub {
       |                ^^^^^^^^^

    warning: enum `EnumGeneric` is never used
      --> test_suite/tests/test_remote.rs:89:14
       |
    89 |     pub enum EnumGeneric<T> {
       |              ^^^^^^^^^^^

    warning: struct `Tuple` is never constructed
      --> test_suite/tests/test_self.rs:44:12
       |
    44 |     struct Tuple(
       |            ^^^^^

    warning: associated items `ASSOC` and `assoc` are never used
      --> test_suite/tests/test_self.rs:52:15
       |
    51 |     impl Tuple {
       |     ---------- associated items in this implementation
    52 |         const ASSOC: usize = 1;
       |               ^^^^^
    53 |         const fn assoc() -> usize {
       |                  ^^^^^

    warning: enum `Enum` is never used
      --> test_suite/tests/test_self.rs:63:10
       |
    63 |     enum Enum {
       |          ^^^^

    warning: associated items `ASSOC` and `assoc` are never used
      --> test_suite/tests/test_self.rs:79:15
       |
    78 |     impl Enum {
       |     --------- associated items in this implementation
    79 |         const ASSOC: usize = 1;
       |               ^^^^^
    80 |         const fn assoc() -> usize {
       |                  ^^^^^

    warning: struct `Unit` is never constructed
      --> test_suite/no_std/src/main.rs:26:8
       |
    26 | struct Unit;
       |        ^^^^

    warning: struct `Newtype` is never constructed
      --> test_suite/no_std/src/main.rs:29:8
       |
    29 | struct Newtype(u8);
       |        ^^^^^^^

    warning: struct `Tuple` is never constructed
      --> test_suite/no_std/src/main.rs:32:8
       |
    32 | struct Tuple(u8, u8);
       |        ^^^^^

    warning: struct `Struct` is never constructed
      --> test_suite/no_std/src/main.rs:35:8
       |
    35 | struct Struct {
       |        ^^^^^^

    warning: enum `Enum` is never used
      --> test_suite/no_std/src/main.rs:40:6
       |
    40 | enum Enum {
       |      ^^^^
2024-07-06 19:26:29 -07:00
David Tolnay 18dcae0a77 Release 1.0.204 2024-07-06 13:38:01 -07:00
David Tolnay 58c307f9cc Alphabetize list of rustc-check-cfg 2024-07-06 13:37:24 -07:00
David Tolnay 8cc4809414 Merge pull request #2769 from dtolnay/onunimpl
Add ui test of unsatisfied serde trait bound
2024-07-06 13:33:50 -07:00
David Tolnay 1179158def Update ui test with diagnostic::on_unimplemented from PR 2767 2024-07-06 13:29:51 -07:00
David Tolnay 91aa40e749 Add ui test of unsatisfied serde trait bound 2024-07-06 13:29:50 -07:00
David Tolnay 595019e979 Cut test_suite from workspace members in old toolchain CI jobs
The test suite's dependencies cannot be resolved by an old toolchain.

    error: failed to select a version for the requirement `toml = "^0.8"`
    candidate versions found which didn't match: 0.5.11, 0.5.10, 0.5.9, ...
    location searched: crates.io index
    required by package `trybuild v1.0.97`
        ... which satisfies dependency `trybuild = "^1.0.97"` of package `serde_test_suite v0.0.0`
2024-07-06 13:25:55 -07:00
David Tolnay b0d7917f88 Pull in trybuild 'following types implement trait' fix 2024-07-06 13:13:32 -07:00
David Tolnay 8e6637a1e4 Merge pull request #2767 from weiznich/feature/diagnostic_on_unimplemented
Use the `#[diagnostic::on_unimplemented]` attribute when possible
2024-07-06 10:29:08 -07:00
Georg Semmler 694fe05953 Use the #[diagnostic::on_unimplemented] attribute when possible
This change enables the `#[diagnostic::on_unimplemented]` attribute for
the `Serialize` and `Deserialize` trait to point the user to the
relevant derives and point out that they might want to check crates
features for external types by adding the relevant hints an note.
2024-07-02 16:39:06 +02:00
David Tolnay f3dfd2a237 Suppress dead code warning in test of unit struct remote derive
error: struct `RemoteSelf` is never constructed
       --> test_suite/tests/test_gen.rs:425:12
        |
    425 |     struct RemoteSelf;
        |            ^^^^^^^^^^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
2024-06-26 19:41:25 -07:00
David Tolnay 9e6158e9e6 Nightly no longer requires error_in_core feature
warning: the feature `error_in_core` has been stable since 1.81.0-nightly and no longer requires an attribute to enable
       --> serde/src/lib.rs:108:43
        |
    108 | #![cfg_attr(feature = "unstable", feature(error_in_core, never_type))]
        |                                           ^^^^^^^^^^^^^
        |
        = note: `#[warn(stable_features)]` on by default
2024-06-10 09:47:24 -07:00
David Tolnay d577c4a2ce Merge pull request #2754 from bm-w/master
Fix missing close paren in crates-io.md
2024-06-06 21:32:01 -07:00
Bastiaan Marinus van de Weerd fee0b82a40 Fix missing close paren in crates-io.md 2024-06-06 23:19:04 -04:00
David Tolnay 7aafa26314 Fill in ignore reasons in all #[ignore] attributes 2024-06-01 22:13:43 -07:00
David Tolnay d5bc546ca5 Release 1.0.203 2024-05-25 10:43:27 -07:00
David Tolnay 45ae217728 Merge pull request #2747 from dtolnay/variadic
Document tuple impls as fake variadic
2024-05-25 10:15:58 -07:00
David Tolnay b7b97dda73 Unindent implementation inside tuple_impl_body macro 2024-05-25 10:11:45 -07:00
David Tolnay 5d3c563d46 Document tuple impls as fake variadic 2024-05-25 10:11:04 -07:00
David Tolnay 376185458b Merge pull request #2745 from dtolnay/docsrs
Rely on docs.rs to define --cfg=docsrs by default
2024-05-18 21:25:44 -07:00
David Tolnay a8f14840ab Rely on docs.rs to define --cfg=docsrs by default 2024-05-18 21:16:37 -07:00
David Tolnay 9e32a40b1c Release 1.0.202 2024-05-15 00:42:49 -07:00
David Tolnay 87f635e54d Release serde_derive_internals 0.29.1 2024-05-15 00:35:14 -07:00
David Tolnay d4b2dfbde2 Merge pull request #2743 from dtolnay/renameallrules
Provide public access to RenameAllRules in serde_derive_internals
2024-05-15 00:34:38 -07:00
David Tolnay f6ab0bc56f Provide public access to RenameAllRules in serde_derive_internals 2024-05-15 00:30:55 -07:00
David Tolnay 48cc2a6327 Replace use of a syn From impl
The From impls may be going away in the next version of syn.
2024-05-14 23:02:28 -07:00
David Tolnay 3202a6858a Skip rerunning build script on library code changes 2024-05-08 21:59:41 -07:00
David Tolnay b4f1bc16ff Release 1.0.201 2024-05-07 17:02:11 -07:00
David Tolnay 029ab46f71 Merge pull request #2737 from dtolnay/checkcfg
Resolve unexpected_cfgs warning
2024-05-07 17:01:43 -07:00
David Tolnay 220ca0ca9d Resolve unexpected_cfgs warning
warning: unexpected `cfg` condition name: `serde_build_from_git`
      --> serde_derive_internals/lib.rs:45:12
       |
    45 | #[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
       |            ^^^^^^^^^^^^^^^^^^^^
       |
       = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
       = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(serde_build_from_git)");` to the top of the `build.rs`
       = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
       = note: `#[warn(unexpected_cfgs)]` on by default

    warning: unexpected `cfg` condition name: `serde_build_from_git`
      --> serde_derive_internals/lib.rs:46:16
       |
    46 | #[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
       |                ^^^^^^^^^^^^^^^^^^^^
       |
       = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(serde_build_from_git)");` to the top of the `build.rs`
       = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition value: `deserialize_in_place`
       --> serde_derive_internals/src/attr.rs:276:11
        |
    276 |     #[cfg(feature = "deserialize_in_place")]
        |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the condition
        |
        = note: no expected values for `feature`
        = help: consider adding `deserialize_in_place` as a feature in `Cargo.toml`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
        --> serde_derive_internals/src/attr.rs:1797:31
         |
    1797 |         #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
         |                               ^^^^^^^^^^
         |
         = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
         = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive_internals/src/receiver.rs:110:35
        |
    110 |             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                   ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive_internals/src/receiver.rs:181:47
        |
    181 |                         #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                               ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive_internals/src/receiver.rs:210:35
        |
    210 |             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                   ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive_internals/src/receiver.rs:231:43
        |
    231 |                     #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                           ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
      --> serde_derive/src/lib.rs:62:23
       |
    62 | #![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
       |                       ^^^^^^^^^^
       |
       = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
       = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
       = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
       = note: `#[warn(unexpected_cfgs)]` on by default

    warning: unexpected `cfg` condition name: `exhaustive`
        --> serde_derive/src/internals/attr.rs:1797:31
         |
    1797 |         #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
         |                               ^^^^^^^^^^
         |
         = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
         = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/internals/receiver.rs:110:35
        |
    110 |             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                   ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/internals/receiver.rs:181:47
        |
    181 |                         #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                               ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/internals/receiver.rs:210:35
        |
    210 |             #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                   ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/internals/receiver.rs:231:43
        |
    231 |                     #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                           ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/bound.rs:147:39
        |
    147 |                 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                       ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/bound.rs:199:51
        |
    199 | ...                   #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                             ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `exhaustive`
       --> serde_derive/src/bound.rs:228:39
        |
    228 |                 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                       ^^^^^^^^^^
        |
        = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs`
        = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration

    warning: unexpected `cfg` condition name: `systemtime_checked_add`
        --> test_suite/tests/test_de_error.rs:1527:7
         |
    1527 | #[cfg(systemtime_checked_add)]
         |       ^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
         = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(systemtime_checked_add)");` to the top of the `build.rs`
         = note: see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration
         = note: `#[warn(unexpected_cfgs)]` on by default
2024-05-07 16:55:01 -07:00
David Tolnay 20306f493a Fix cfg on test_systemtime_overflow 2024-05-07 16:53:53 -07:00
David Tolnay cc865ac523 Release 1.0.200 2024-05-01 08:58:52 -07:00
David Tolnay 2d973c1805 Merge pull request #2733 from jamessan/nan-decimal
Only format Unexpected::Float with decimal point if it is finite
2024-05-01 11:57:52 -04:00
James McCoy 6ca499b2dd Only format Unexpected::Float with decimal point if it is finite
bef110b92a changed the display for unexpected floats to always append a
".0" if there was no decimal point found in the formatting of the float.

However, this should only be relevant for finite (i.e., not NaN or inf)
values.  The change introduced a test failure in the ordered-float
crate due to this:

     ---- impl_serde::test_fail_on_nan stdout ----
     thread 'impl_serde::test_fail_on_nan' panicked at 'assertion failed: `(left == right)`
       left: `Error { msg: "invalid value: floating point `NaN.0`, expected float (but not NaN)" }`,
      right: `"invalid value: floating point `NaN`, expected float (but not NaN)"`', src/lib.rs:1554:9
     stack backtrace:
        0: rust_begin_unwind
                  at /usr/src/rustc-1.70.0/library/std/src/panicking.rs:578:5
        1: core::panicking::panic_fmt
                  at /usr/src/rustc-1.70.0/library/core/src/panicking.rs:67:14
        2: core::panicking::assert_failed_inner
        3: core::panicking::assert_failed
                  at /usr/src/rustc-1.70.0/library/core/src/panicking.rs:228:5
        4: serde_test::assert::assert_de_tokens_error
                  at /usr/share/cargo/registry/serde_test-1.0.171/src/assert.rs:228:19
        5: ordered_float::impl_serde::test_fail_on_nan
                  at ./src/lib.rs:1554:9
        6: ordered_float::impl_serde::test_fail_on_nan::{{closure}}
                  at ./src/lib.rs:1553:27
        7: core::ops::function::FnOnce::call_once
                  at /usr/src/rustc-1.70.0/library/core/src/ops/function.rs:250:5
        8: core::ops::function::FnOnce::call_once
                  at /usr/src/rustc-1.70.0/library/core/src/ops/function.rs:250:5
     note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
2024-05-01 09:10:09 -04:00
David Tolnay 1477028717 Release 1.0.199 2024-04-26 21:22:11 -07:00
David Tolnay 789740be0d Merge pull request #2732 from aatifsyed/master
fix: ambiguous associated item in forward_to_deserialize_any!
2024-04-26 21:21:40 -07:00
Aatif Syed 8fe7539bb2 fix: ambiguous associated type in forward_to_deserialize_any! 2024-04-26 13:04:00 +02:00
David Tolnay f6623a3654 Ignore cast_precision_loss pedantic clippy lint
warning: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
       --> serde/src/de/impls.rs:197:16
        |
    197 |               Ok(v as Self::Value)
        |                  ^^^^^^^^^^^^^^^^
    ...
    457 | / impl_deserialize_num! {
    458 | |     f32, deserialize_f32
    459 | |     num_self!(f32:visit_f32);
    460 | |     num_as_copysign_self!(f64:visit_f64);
    461 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    462 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    463 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
        = note: `-W clippy::cast-precision-loss` implied by `-W clippy::pedantic`
        = help: to override `-W clippy::pedantic` add `#[allow(clippy::cast_precision_loss)]`
        = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
       --> serde/src/de/impls.rs:197:16
        |
    197 |               Ok(v as Self::Value)
        |                  ^^^^^^^^^^^^^^^^
    ...
    457 | / impl_deserialize_num! {
    458 | |     f32, deserialize_f32
    459 | |     num_self!(f32:visit_f32);
    460 | |     num_as_copysign_self!(f64:visit_f64);
    461 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    462 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    463 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
        = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
       --> serde/src/de/impls.rs:197:16
        |
    197 |               Ok(v as Self::Value)
        |                  ^^^^^^^^^^^^^^^^
    ...
    457 | / impl_deserialize_num! {
    458 | |     f32, deserialize_f32
    459 | |     num_self!(f32:visit_f32);
    460 | |     num_as_copysign_self!(f64:visit_f64);
    461 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    462 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    463 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
        = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
       --> serde/src/de/impls.rs:197:16
        |
    197 |               Ok(v as Self::Value)
        |                  ^^^^^^^^^^^^^^^^
    ...
    457 | / impl_deserialize_num! {
    458 | |     f32, deserialize_f32
    459 | |     num_self!(f32:visit_f32);
    460 | |     num_as_copysign_self!(f64:visit_f64);
    461 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    462 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    463 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
        = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
       --> serde/src/de/impls.rs:197:16
        |
    197 |               Ok(v as Self::Value)
        |                  ^^^^^^^^^^^^^^^^
    ...
    465 | / impl_deserialize_num! {
    466 | |     f64, deserialize_f64
    467 | |     num_self!(f64:visit_f64);
    468 | |     num_as_copysign_self!(f32:visit_f32);
    469 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    470 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    471 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
        = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
       --> serde/src/de/impls.rs:197:16
        |
    197 |               Ok(v as Self::Value)
        |                  ^^^^^^^^^^^^^^^^
    ...
    465 | / impl_deserialize_num! {
    466 | |     f64, deserialize_f64
    467 | |     num_self!(f64:visit_f64);
    468 | |     num_as_copysign_self!(f32:visit_f32);
    469 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    470 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    471 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
        = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)
2024-04-19 20:57:45 -07:00
David Tolnay c4fb923335 Release 1.0.198 2024-04-16 14:18:01 -07:00
David Tolnay 65b7eea775 Merge pull request #2729 from dtolnay/saturating
Integrate Saturating<T> deserialization into impl_deserialize_num macro
2024-04-16 14:17:19 -07:00
David Tolnay 01cd696fd1 Integrate Saturating<T> deserialization into impl_deserialize_num macro 2024-04-16 14:09:00 -07:00
David Tolnay c13b3f7e68 Format PR 2709 2024-04-16 13:34:22 -07:00
Oli Scherer a6571ee0da Merge pull request #2709 from jbethune/master
Implement Ser+De for Saturating<T>
2024-04-11 10:18:20 +02:00
David Tolnay 6e38afff49 Revert "Temporarily disable miri on doctests"
This reverts commit 3bfab6ef7f.
2024-04-08 11:58:08 -07:00
Jörn Bethune 3d1b19ed90 Implement Ser+De for Saturating<T>
The serialization implementation is heavily
inspired by the existing trait implentation for
`std::num::Wrapping<T>`.

The deserializing implementation maps input values
that lie outside of the numerical range of the
output type to the `MIN` or `MAX` value of the
output type, depending on the sign of the input
value. This behaviour follows to the `Saturating`
semantics of the output type.

fix #2708
2024-04-06 19:58:01 +02:00
David Tolnay 5b24f88e73 Resolve legacy_numeric_constants clippy lints
warning: usage of a legacy numeric method
       --> serde_derive/src/ser.rs:292:51
        |
    292 |     assert!(fields.len() as u64 <= u64::from(u32::max_value()));
        |                                                   ^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
        = note: `#[warn(clippy::legacy_numeric_constants)]` on by default
    help: use the associated constant instead
        |
    292 |     assert!(fields.len() as u64 <= u64::from(u32::MAX));
        |                                                   ~~~

    warning: usage of a legacy numeric method
       --> serde_derive/src/ser.rs:400:53
        |
    400 |     assert!(variants.len() as u64 <= u64::from(u32::max_value()));
        |                                                     ^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
    help: use the associated constant instead
        |
    400 |     assert!(variants.len() as u64 <= u64::from(u32::MAX));
        |                                                     ~~~

    warning: usage of a legacy numeric method
        --> test_suite/tests/test_de_error.rs:1462:29
         |
    1462 |             Token::U64(u64::max_value()),
         |                             ^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
         = note: `-W clippy::legacy-numeric-constants` implied by `-W clippy::all`
         = help: to override `-W clippy::all` add `#[allow(clippy::legacy_numeric_constants)]`
    help: use the associated constant instead
         |
    1462 |             Token::U64(u64::MAX),
         |                             ~~~

    warning: usage of a legacy numeric method
        --> test_suite/tests/test_de_error.rs:1479:29
         |
    1479 |             Token::U64(u64::max_value()),
         |                             ^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
    help: use the associated constant instead
         |
    1479 |             Token::U64(u64::MAX),
         |                             ~~~

    warning: usage of a legacy numeric method
        --> test_suite/tests/test_de_error.rs:1493:29
         |
    1493 |             Token::U64(u64::max_value()),
         |                             ^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
    help: use the associated constant instead
         |
    1493 |             Token::U64(u64::MAX),
         |                             ~~~

    warning: usage of a legacy numeric method
        --> test_suite/tests/test_de_error.rs:1510:29
         |
    1510 |             Token::U64(u64::max_value()),
         |                             ^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
    help: use the associated constant instead
         |
    1510 |             Token::U64(u64::MAX),
         |                             ~~~
2024-04-05 19:19:14 -07:00
David Tolnay 74d06708dd Explicitly install a Rust toolchain for cargo-outdated job
Debugging a recent cargo-outdated bug, it would have been nice not to
wonder whether a rustc version change in GitHub's runner image was a
contributing factor.
2024-03-25 22:24:55 -07:00
David Tolnay 3bfab6ef7f Temporarily disable miri on doctests 2024-03-24 19:52:00 -07:00
David Tolnay 364cd8d8f7 Ignore dead code lint in tests
New in nightly-2024-03-24 from https://github.com/rust-lang/rust/pull/119552.

    warning: fields `nested` and `string` are never read
      --> test_suite/tests/regression/issue2371.rs:10:9
       |
    8  |     Flatten {
       |     ------- fields in this variant
    9  |         #[serde(flatten)]
    10 |         nested: Nested,
       |         ^^^^^^
    11 |         string: &'static str,
       |         ^^^^^^
       |
       = note: `#[warn(dead_code)]` on by default

    warning: fields `nested` and `string` are never read
      --> test_suite/tests/regression/issue2371.rs:20:9
       |
    18 |     Flatten {
       |     ------- fields in this variant
    19 |         #[serde(flatten)]
    20 |         nested: Nested,
       |         ^^^^^^
    21 |         string: &'static str,
       |         ^^^^^^

    warning: fields `nested` and `string` are never read
      --> test_suite/tests/regression/issue2371.rs:30:9
       |
    28 |     Flatten {
       |     ------- fields in this variant
    29 |         #[serde(flatten)]
    30 |         nested: Nested,
       |         ^^^^^^
    31 |         string: &'static str,
       |         ^^^^^^

    warning: fields `nested` and `string` are never read
      --> test_suite/tests/regression/issue2371.rs:40:9
       |
    38 |     Flatten {
       |     ------- fields in this variant
    39 |         #[serde(flatten)]
    40 |         nested: Nested,
       |         ^^^^^^
    41 |         string: &'static str,
       |         ^^^^^^

    warning: field `0` is never read
       --> test_suite/tests/test_gen.rs:690:33
        |
    690 |         Single(#[serde(borrow)] RelObject<'a>),
        |         ------                  ^^^^^^^^^^^^^
        |         |
        |         field in this variant
        |
        = note: `#[warn(dead_code)]` on by default
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    690 |         Single(#[serde(borrow)] ()),
        |                                 ~~

    warning: field `0` is never read
       --> test_suite/tests/test_gen.rs:691:31
        |
    691 |         Many(#[serde(borrow)] Vec<RelObject<'a>>),
        |         ----                  ^^^^^^^^^^^^^^^^^^
        |         |
        |         field in this variant
        |
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    691 |         Many(#[serde(borrow)] ()),
        |                               ~~
2024-03-23 20:26:05 -07:00
David Tolnay 9f8c579bf5 Merge pull request #2714 from Marcono1234/skipped-field-struct-len
Document that `len` does not include skipped struct fields
2024-03-16 12:49:50 -07:00
Marcono1234 eae7c2d684 Document that len does not include skipped struct fields 2024-03-16 14:40:28 +01:00
David Tolnay 3f43fca90d Fix warning on no edition set in serde_derive
New warning since nightly-2024-03-03:

    warning: serde_derive/Cargo.toml: no edition set: defaulting to the 2015 edition while 2018 is compatible with `rust-version`
    warning: serde_derive_internals/Cargo.toml: no edition set: defaulting to the 2015 edition while 2018 is compatible with `rust-version`
2024-03-11 20:18:10 -07:00
David Tolnay 76449488ca Ignore new dead_code warnings in test
Since nightly-2024-03-12.

    warning: struct `PackedC` is never constructed
        --> test_suite/tests/test_macros.rs:2237:12
         |
    2237 |     struct PackedC {
         |            ^^^^^^^
         |
         = note: `#[warn(dead_code)]` on by default

    warning: struct `CPacked` is never constructed
        --> test_suite/tests/test_macros.rs:2243:12
         |
    2243 |     struct CPacked {
         |            ^^^^^^^

    warning: struct `CPacked2` is never constructed
        --> test_suite/tests/test_macros.rs:2249:12
         |
    2249 |     struct CPacked2 {
         |            ^^^^^^^^

    warning: struct `Packed2C` is never constructed
        --> test_suite/tests/test_macros.rs:2255:12
         |
    2255 |     struct Packed2C {
         |            ^^^^^^^^

    error: struct `Packed` is never constructed
       --> test_suite/tests/test_gen.rs:733:12
        |
    733 |     struct Packed {
        |            ^^^^^^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`

    error: struct `Struct` is never constructed
       --> test_suite/tests/test_gen.rs:764:12
        |
    764 |     struct Struct {
        |            ^^^^^^

    error: function `vec_first_element` is never used
       --> test_suite/tests/test_gen.rs:846:4
        |
    846 | fn vec_first_element<T, S>(vec: &[T], serializer: S) -> StdResult<S::Ok, S::Error>
        |    ^^^^^^^^^^^^^^^^^
2024-03-11 20:10:30 -07:00
David Tolnay 00c4b0cef8 Merge pull request 2560 from Mingun/honest-test 2024-03-03 15:54:47 -08:00
David Tolnay 89139e2c11 Remove ineffective ?Sized bound on weak rc Deserialize impls
These impls have both `T: ?Sized` and `T: Deserialize<'de>`. But
`Deserialize<'de>: Sized`.
2024-02-27 22:52:20 -08:00
David Tolnay c9cab490f7 Resolve multiple_bound_locations clippy lint
warning: bound is defined in more than one place
      --> serde/src/ser/fmt.rs:77:33
       |
    77 |     fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
       |                                 ^
    78 |     where
    79 |         T: Serialize,
       |         ^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations
       = note: `-W clippy::multiple-bound-locations` implied by `-W clippy::all`
       = help: to override `-W clippy::all` add `#[allow(clippy::multiple_bound_locations)]`

    warning: bound is defined in more than one place
      --> serde/src/ser/fmt.rs:92:23
       |
    92 |     fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
       |                       ^
    93 |     where
    94 |         T: Serialize,
       |         ^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/fmt.rs:103:34
        |
    103 |     fn serialize_newtype_variant<T: ?Sized>(
        |                                  ^
    ...
    111 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/fmt.rs:164:20
        |
    164 |     fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
        |                    ^
    165 |     where
    166 |         T: Display,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
      --> serde/src/ser/impossible.rs:75:26
       |
    75 |     fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
       |                          ^
    76 |     where
    77 |         T: Serialize,
       |         ^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
      --> serde/src/ser/impossible.rs:95:26
       |
    95 |     fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
       |                          ^
    96 |     where
    97 |         T: Serialize,
       |         ^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/impossible.rs:115:24
        |
    115 |     fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        |                        ^
    116 |     where
    117 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/impossible.rs:135:24
        |
    135 |     fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        |                        ^
    136 |     where
    137 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/impossible.rs:155:22
        |
    155 |     fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
        |                      ^
    156 |     where
    157 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/impossible.rs:163:24
        |
    163 |     fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        |                        ^
    164 |     where
    165 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/impossible.rs:183:24
        |
    183 |     fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
        |                        ^
    184 |     where
    185 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/impossible.rs:204:24
        |
    204 |     fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
        |                        ^
    205 |     where
    206 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/mod.rs:799:23
        |
    799 |     fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
        |                       ^
    800 |     where
    801 |         T: Serialize;
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/mod.rs:894:33
        |
    894 |     fn serialize_newtype_struct<T: ?Sized>(
        |                                 ^
    ...
    900 |         T: Serialize;
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/ser/mod.rs:928:34
        |
    928 |     fn serialize_newtype_variant<T: ?Sized>(
        |                                  ^
    ...
    936 |         T: Serialize;
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1349:20
         |
    1349 |     fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
         |                    ^
    1350 |     where
    1351 |         T: Display,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1496:26
         |
    1496 |     fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                          ^
    1497 |     where
    1498 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1596:26
         |
    1596 |     fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                          ^
    1597 |     where
    1598 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1641:24
         |
    1641 |     fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                        ^
    1642 |     where
    1643 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1699:24
         |
    1699 |     fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                        ^
    1700 |     where
    1701 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1770:22
         |
    1770 |     fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
         |                      ^
    1771 |     where
    1772 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1780:24
         |
    1780 |     fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                        ^
    1781 |     where
    1782 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1801:24
         |
    1801 |     fn serialize_entry<K: ?Sized, V: ?Sized>(
         |                        ^
    ...
    1807 |         K: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1801:35
         |
    1801 |     fn serialize_entry<K: ?Sized, V: ?Sized>(
         |                                   ^
    ...
    1808 |         V: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1859:24
         |
    1859 |     fn serialize_field<T: ?Sized>(
         |                        ^
    ...
    1865 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/ser/mod.rs:1925:24
         |
    1925 |     fn serialize_field<T: ?Sized>(
         |                        ^
    ...
    1931 |         T: Serialize;
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:177:23
        |
    177 |     fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
        |                       ^
    178 |     where
    179 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:208:33
        |
    208 |     fn serialize_newtype_struct<T: ?Sized>(
        |                                 ^
    ...
    214 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:219:34
        |
    219 |     fn serialize_newtype_variant<T: ?Sized>(
        |                                  ^
    ...
    227 |         T: Serialize,
        |         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:367:28
        |
    367 |         fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), M::Error>
        |                            ^
    368 |         where
    369 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:407:28
        |
    407 |         fn serialize_field<T: ?Sized>(
        |                            ^
    ...
    413 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:638:27
        |
    638 |         fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Content, E>
        |                           ^
    639 |         where
    640 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:662:37
        |
    662 |         fn serialize_newtype_struct<T: ?Sized>(
        |                                     ^
    ...
    668 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:676:38
        |
    676 |         fn serialize_newtype_variant<T: ?Sized>(
        |                                      ^
    ...
    684 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:785:30
        |
    785 |         fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
        |                              ^
    786 |         where
    787 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:811:30
        |
    811 |         fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
        |                              ^
    812 |         where
    813 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:838:28
        |
    838 |         fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
        |                            ^
    839 |         where
    840 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:867:28
        |
    867 |         fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
        |                            ^
    868 |         where
    869 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:899:26
        |
    899 |         fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), E>
        |                          ^
    900 |         where
    901 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:908:28
        |
    908 |         fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
        |                            ^
    909 |         where
    910 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:925:28
        |
    925 |         fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E>
        |                            ^
    926 |         where
    927 |             K: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:925:39
        |
    925 |         fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E>
        |                                       ^
    ...
    928 |             V: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:950:28
        |
    950 |         fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
        |                            ^
    951 |         where
    952 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
       --> serde/src/private/ser.rs:979:28
        |
    979 |         fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
        |                            ^
    980 |         where
    981 |             T: Serialize,
        |             ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1091:23
         |
    1091 |     fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
         |                       ^
    1092 |     where
    1093 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1115:33
         |
    1115 |     fn serialize_newtype_struct<T: ?Sized>(
         |                                 ^
    ...
    1121 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1126:34
         |
    1126 |     fn serialize_newtype_variant<T: ?Sized>(
         |                                  ^
    ...
    1134 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1205:22
         |
    1205 |     fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
         |                      ^
    1206 |     where
    1207 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1212:24
         |
    1212 |     fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                        ^
    1213 |     where
    1214 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1219:24
         |
    1219 |     fn serialize_entry<K: ?Sized, V: ?Sized>(
         |                        ^
    ...
    1225 |         K: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1219:35
         |
    1219 |     fn serialize_entry<K: ?Sized, V: ?Sized>(
         |                                   ^
    ...
    1226 |         V: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1247:24
         |
    1247 |     fn serialize_field<T: ?Sized>(
         |                        ^
    ...
    1253 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1292:24
         |
    1292 |     fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
         |                        ^
    1293 |     where
    1294 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations

    warning: bound is defined in more than one place
        --> serde/src/private/ser.rs:1338:24
         |
    1338 |     fn serialize_field<T: ?Sized>(
         |                        ^
    ...
    1344 |         T: Serialize,
         |         ^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations
2024-02-27 22:45:50 -08:00
David Tolnay 5fa711d75d Release 1.0.197 2024-02-19 16:22:07 -08:00
David Tolnay f5d8ae423a Resolve prelude redundant import warnings
warning: the item `Into` is imported redundantly
       --> serde/src/lib.rs:184:47
        |
    184 |     pub use self::core::convert::{self, From, Into};
        |                                               ^^^^
        |
       ::: nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/prelude/mod.rs:115:13
        |
    115 |     pub use super::v1::*;
        |             --------- the item `Into` is already defined here
        |
        = note: `#[warn(unused_imports)]` on by default
2024-02-19 16:16:40 -08:00
David Tolnay 1d54973b92 Merge pull request #2697 from nyurik/format-str
A few minor `write_str` optimizations
2024-02-12 19:49:34 -08:00
Yuri Astrakhan b8fafefd85 A few minor write_str optimizations and inlining
Apparently `write!` generates more code than `write_str` when used with a simple string, so optimizing it.
2024-02-12 16:12:08 -05:00
David Tolnay c42ebb8839 Update ui test suite to nightly-2024-02-12 2024-02-11 20:00:23 -08:00
David Tolnay 9e680620b5 Ignore incompatible_msrv clippy lint for conditionally compiled code
warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.35.0`
       --> serde/src/de/impls.rs:200:39
        |
    200 |                   Ok((v as Self::Value).copysign(sign))
        |                                         ^^^^^^^^^^^^^^
    ...
    374 | / impl_deserialize_num! {
    375 | |     f32, deserialize_f32
    376 | |     num_self!(f32:visit_f32);
    377 | |     num_as_copysign_self!(f64:visit_f64);
    378 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    379 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    380 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv
        = note: `-W clippy::incompatible-msrv` implied by `-W clippy::all`
        = help: to override `-W clippy::all` add `#[allow(clippy::incompatible_msrv)]`
        = note: this warning originates in the macro `num_as_copysign_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.35.0`
       --> serde/src/de/impls.rs:200:39
        |
    200 |                   Ok((v as Self::Value).copysign(sign))
        |                                         ^^^^^^^^^^^^^^
    ...
    382 | / impl_deserialize_num! {
    383 | |     f64, deserialize_f64
    384 | |     num_self!(f64:visit_f64);
    385 | |     num_as_copysign_self!(f32:visit_f32);
    386 | |     num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
    387 | |     num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
    388 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv
        = note: this warning originates in the macro `num_as_copysign_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0`
        --> serde/src/de/impls.rs:2308:14
         |
    2308 |             .checked_add(duration)
         |              ^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv

    warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0`
       --> serde/src/ser/impls.rs:606:26
        |
    606 |                       self.get().serialize(serializer)
        |                            ^^^^^
    ...
    623 | / nonzero_integers! {
    624 | |     NonZeroI8,
    625 | |     NonZeroI16,
    626 | |     NonZeroI32,
    ...   |
    629 | |     NonZeroIsize,
    630 | | }
        | |_- in this macro invocation
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv
        = note: this warning originates in the macro `nonzero_integers` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0`
        --> serde/src/ser/impls.rs:1053:26
         |
    1053 |                       self.load(Ordering::Relaxed).serialize(serializer)
         |                            ^^^^^^^^^^^^^^^^^^^^^^^
    ...
    1061 | / atomic_impl! {
    1062 | |     AtomicBool "8"
    1063 | |     AtomicI8 "8"
    1064 | |     AtomicI16 "16"
    ...    |
    1070 | |     AtomicUsize "ptr"
    1071 | | }
         | |_- in this macro invocation
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv
         = note: this warning originates in the macro `atomic_impl` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0`
        --> serde/src/ser/impls.rs:1053:26
         |
    1053 |                       self.load(Ordering::Relaxed).serialize(serializer)
         |                            ^^^^^^^^^^^^^^^^^^^^^^^
    ...
    1074 | / atomic_impl! {
    1075 | |     AtomicI64 "64"
    1076 | |     AtomicU64 "64"
    1077 | | }
         | |_- in this macro invocation
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv
         = note: this warning originates in the macro `atomic_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
2024-02-09 18:55:58 -08:00
David Tolnay 846f865de2 Ignore dead_code warnings in test
warning: trait `AssertNotSerdeSerialize` is never used
      --> test_suite/tests/test_serde_path.rs:39:7
       |
    39 | trait AssertNotSerdeSerialize {}
       |       ^^^^^^^^^^^^^^^^^^^^^^^
       |
       = note: `#[warn(dead_code)]` on by default

    warning: trait `AssertNotSerdeDeserialize` is never used
      --> test_suite/tests/test_serde_path.rs:43:7
       |
    43 | trait AssertNotSerdeDeserialize<'a> {}
       |       ^^^^^^^^^^^^^^^^^^^^^^^^^

    warning: method `serialize` is never used
      --> test_suite/tests/test_serde_path.rs:31:12
       |
    30 |     pub trait Serialize {
       |               --------- method in this trait
    31 |         fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
       |            ^^^^^^^^^

    warning: associated function `deserialize` is never used
      --> test_suite/tests/test_serde_path.rs:35:12
       |
    34 |     pub trait Deserialize<'a>: Sized {
       |               ----------- associated function in this trait
    35 |         fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error>;
       |            ^^^^^^^^^^^
2024-02-07 22:15:42 -08:00
David Tolnay ede9762a58 Release 1.0.196 2024-01-26 14:00:35 -08:00
David Tolnay d438c2d67b Merge pull request #2682 from dtolnay/decimalpoint
Format Unexpected::Float with decimal point
2024-01-26 13:59:58 -08:00
David Tolnay bef110b92a Format Unexpected::Float with decimal point 2024-01-26 13:55:13 -08:00
David Tolnay b971ef11d1 Merge pull request #2681 from dtolnay/workspacedeps
Fix workspace.dependencies default-features future compat warning
2024-01-26 13:41:27 -08:00
David Tolnay 29d9f69399 Fix workspace.dependencies default-features future compat warning
warning: serde_derive_internals/Cargo.toml: `default-features` is
    ignored for syn, since `default-features` was not specified for
    `workspace.dependencies.syn`, this could become a hard error in the
    future
2024-01-26 13:36:03 -08:00
David Tolnay aecb4083bd Sort workspace dependencies 2024-01-23 10:08:00 -08:00
David Tolnay 1c675ab3a3 Merge pull request #2678 from rodoufu/workspaceDependencies
Adding workspace dependencies
2024-01-23 10:07:38 -08:00
Rodolfo P A dd619630a3 Adding workspace dependencies 2024-01-23 12:53:29 +00:00
David Tolnay 111803ab07 Merge pull request #2673 from Sky9x/msrv-badge
Use shields.io's MSRV badges
2024-01-08 20:51:26 -08:00
Sky 0024f74f34 Use shields.io's MSRV badges 2024-01-08 22:22:03 -05:00
David Tolnay 03eec42c33 Release 1.0.195 2024-01-05 18:33:24 -08:00
David Tolnay 196f311ae2 Merge pull request #2671 from dtolnay/deadremote
Fix new dead_code warning in tuple struct and tuple variant remote defs
2024-01-05 18:30:01 -08:00
David Tolnay 38d9e0b209 Revert "Add FIXME to fix dead_code warning when using serde(remote)" 2024-01-05 18:26:24 -08:00
David Tolnay 6502b31316 Fix new dead_code warning in tuple struct and tuple variant remote defs 2024-01-05 18:26:24 -08:00
David Tolnay 6f1a8c3115 Add FIXME to fix dead_code warning when using serde(remote)
warning: field `0` is never read
       --> test_suite/tests/test_remote.rs:143:24
        |
    143 | struct PrimitivePubDef(u8);
        |        --------------- ^^
        |        |
        |        field in this struct
        |
        = note: `#[warn(dead_code)]` on by default
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    143 | struct PrimitivePubDef(());
        |                        ~~

    warning: field `0` is never read
       --> test_suite/tests/test_remote.rs:162:20
        |
    162 | struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
        |        ----------- ^^
        |        |
        |        field in this struct
        |
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    162 | struct TuplePubDef((), #[serde(with = "UnitDef")] remote::Unit);
        |                    ~~

    warning: field `0` is never read
       --> test_suite/tests/test_remote.rs:200:13
        |
    200 |     Variant(u8),
        |     ------- ^^
        |     |
        |     field in this variant
        |
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    200 |     Variant(()),
        |             ~~

    error: field `0` is never read
       --> test_suite/tests/test_gen.rs:390:23
        |
    390 |     struct StrDef<'a>(&'a str);
        |            ------     ^^^^^^^
        |            |
        |            field in this struct
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    390 |     struct StrDef<'a>(());
        |                       ~~
2024-01-05 18:12:26 -08:00
David Tolnay d883c94cc9 Work around dead_code warning in tests
error: field `0` is never read
       --> test_suite/tests/test_gen.rs:690:33
        |
    690 |         Single(#[serde(borrow)] RelObject<'a>),
        |         ------                  ^^^^^^^^^^^^^
        |         |
        |         field in this variant
        |
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    690 |         Single(#[serde(borrow)] ()),
        |                                 ~~

    error: field `0` is never read
       --> test_suite/tests/test_gen.rs:691:31
        |
    691 |         Many(#[serde(borrow)] Vec<RelObject<'a>>),
        |         ----                  ^^^^^^^^^^^^^^^^^^
        |         |
        |         field in this variant
        |
    help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
        |
    691 |         Many(#[serde(borrow)] ()),
        |                               ~~
2024-01-05 18:11:07 -08:00
David Tolnay 961fa59a74 Merge pull request #2670 from serde-rs/exhaustive
Pick up changes to non_exhaustive_omitted_patterns lint
2024-01-03 18:42:59 -08:00
David Tolnay 8bc71def55 Fill in omitted patterns for GenericArguments match
error: some variants are not matched explicitly
        --> serde_derive/src/internals/attr.rs:1823:31
         |
    1823 |                         match arg {
         |                               ^^^ patterns `&GenericArgument::Const(_)`, `&GenericArgument::AssocConst(_)` and `&GenericArgument::Constraint(_)` not covered
         |
         = help: ensure that all variants are matched explicitly by adding the suggested match arms
         = note: the matched value is of type `&GenericArgument` and the `non_exhaustive_omitted_patterns` attribute was found
    note: the lint level is defined here
        --> serde_derive/src/internals/attr.rs:1797:49
         |
    1797 |         #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
         |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-01-03 18:38:58 -08:00
David Tolnay 7c65a9dc0e Pick up changes to non_exhaustive_omitted_patterns lint
warning: the lint level must be set on the whole match
        --> serde_derive/src/internals/attr.rs:1855:9
         |
    1854 |         #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
         |                                                ------------------------------- remove this attribute
    1855 |         _ => {}
         |         ^
         |
         = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
         |
    1796 +     #[deny(non_exhaustive_omitted_patterns)]
    1797 |     match ty {
         |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/internals/receiver.rs:151:13
        |
    150 |             #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                                    ------------------------------- remove this attribute
    151 |             _ => {}
        |             ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    109 +         #[deny(non_exhaustive_omitted_patterns)]
    110 |         match ty {
        |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/internals/receiver.rs:188:25
        |
    187 |                         #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                                                ------------------------------- remove this attribute
    188 |                         _ => {}
        |                         ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    180 +                     #[deny(non_exhaustive_omitted_patterns)]
    181 |                     match arg {
        |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/internals/receiver.rs:213:13
        |
    212 |             #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                                    ------------------------------- remove this attribute
    213 |             _ => {}
        |             ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    209 +         #[deny(non_exhaustive_omitted_patterns)]
    210 |         match bound {
        |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/internals/receiver.rs:239:21
        |
    238 |                     #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                                            ------------------------------- remove this attribute
    239 |                     _ => {}
        |                     ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    230 +                 #[deny(non_exhaustive_omitted_patterns)]
    231 |                 match predicate {
        |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/bound.rs:185:17
        |
    184 |                 #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                                        ------------------------------- remove this attribute
    185 |                 _ => {}
        |                 ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    146 +             #[deny(non_exhaustive_omitted_patterns)]
    147 |             match ty {
        |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/bound.rs:209:29
        |
    207 | ...                       deny(non_exhaustive_omitted_patterns)
        |                                ------------------------------- remove this attribute
    208 | ...                   )]
    209 | ...                   _ => {}
        |                       ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    198 +                         #[deny(non_exhaustive_omitted_patterns)]
    199 |                         match arg {
        |

    warning: the lint level must be set on the whole match
       --> serde_derive/src/bound.rs:234:17
        |
    233 |                 #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
        |                                                        ------------------------------- remove this attribute
    234 |                 _ => {}
        |                 ^
        |
        = help: it no longer has any effect to set the lint level on an individual match arm
    help: set the lint level on the whole match
        |
    230 +             #[deny(non_exhaustive_omitted_patterns)]
    231 |             match bound {
        |
2024-01-03 18:38:58 -08:00
David Tolnay d2d977a6c6 Release 1.0.194 2024-01-01 23:07:27 -08:00
David Tolnay a9a6ee9d7f Pull in proc-macro2 sccache fix 2024-01-01 23:03:34 -08:00
David Tolnay 28c5d215c1 Merge pull request #2669 from dtolnay/optionifletelse
Remove option_if_let_else clippy suppression
2023-12-30 14:49:23 -08:00
David Tolnay 3d6a789562 Remove option_if_let_else clippy suppression 2023-12-30 14:46:51 -08:00
David Tolnay a0e68698e3 Work around doc_link_with_quotes pedantic clippy lint
warning: possible intra-doc link using quotes instead of backticks
      --> serde/src/de/mod.rs:67:41
       |
    67 | //!    - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
       |                                         ^^^^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
       = note: `-W clippy::doc-link-with-quotes` implied by `-W clippy::pedantic`
       = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_link_with_quotes)]`

    warning: possible intra-doc link using quotes instead of backticks
      --> serde/src/de/mod.rs:68:42
       |
    68 | //!    - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
       |                                          ^^^^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes

    warning: possible intra-doc link using quotes instead of backticks
      --> serde/src/ser/mod.rs:64:41
       |
    64 | //!    - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
       |                                         ^^^^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes

    warning: possible intra-doc link using quotes instead of backticks
      --> serde/src/ser/mod.rs:65:42
       |
    65 | //!    - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
       |                                          ^^^^
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
2023-12-02 18:25:35 -08:00
David Tolnay 44613c7d01 Release 1.0.193 2023-11-20 17:34:20 -08:00
David Tolnay c706281df3 Merge pull request #2655 from dtolnay/rangestartend
Add RangeFrom and RangeTo tests
2023-11-20 17:33:42 -08:00
David Tolnay 65d75b8fe3 Add RangeFrom and RangeTo tests 2023-11-20 17:28:38 -08:00
David Tolnay 332b0cba40 Merge pull request #2654 from dtolnay/rangestartend
Fix more RangeFrom / RangeEnd mixups
2023-11-20 17:27:31 -08:00
David Tolnay 8c4af41296 Fix more RangeFrom / RangeEnd mixups 2023-11-20 17:21:59 -08:00
David Tolnay 24a78f071b Merge pull request #2653 from emilbonnek/fix/range-to-from-de-mixup
Fix Range{From,To} deserialize mixup
2023-11-20 17:20:04 -08:00
Emil Bonne Kristiansen c91c33436d Fix Range{From,To} deserialize mixup 2023-11-21 02:13:18 +01:00
David Tolnay 2083f43a28 Update ui test suite to nightly-2023-11-19 2023-11-18 18:13:57 -08:00
David Tolnay 4676abdc9e Release 1.0.192 2023-11-06 18:49:17 -08:00
David Tolnay 35700eb23e Merge pull request #2646 from robsdedude/fix/2643/allow-tag-field-in-untagged
Allow internal tag field in untagged variant
2023-11-06 18:48:46 -08:00
David Tolnay 59892e7b58 Release 1.0.191 2023-11-06 11:30:27 -08:00
David Tolnay 97dd07a7d1 Merge pull request #2647 from dtolnay/doccfg
Render `doc(cfg(...))` on feature gated APIs in docs.rs
2023-11-06 11:29:38 -08:00
David Tolnay c8bc97c81b Document "rc" and "unstable" features on docs.rs 2023-11-06 11:22:25 -08:00
David Tolnay 9dacfbbd69 Fill in more doc(cfg) attributes 2023-11-06 11:20:29 -08:00
David Tolnay 05c2509d07 Relocate cfg attrs into deref_impl 2023-11-06 11:15:27 -08:00
David Tolnay 64f949b37b Relocate cfg attrs into parse_ip_impl and parse_socket_impl 2023-11-06 11:15:08 -08:00
David Tolnay 3f339de36a Relocate cfg attrs into seq_impl and map_impl 2023-11-06 11:15:08 -08:00
David Tolnay 215c2b71ef Relocate cfg attrs into forwarded_impl macro
This will allow adding #[doc(cfg(feature = "..."))] attributes to the
impl in an upcoming commit.
2023-11-06 08:55:14 -08:00
David Tolnay ce8fef7e0b Show that derives are specific to feature="derive" in documentation 2023-11-06 08:55:14 -08:00
David Tolnay 0726b2c479 Enable feature(doc_cfg) during docs.rs documentation build 2023-11-06 08:55:14 -08:00
Robsdedude 589549d7e6 Allow internal tag field in untagged variant 2023-11-06 12:14:49 +01:00
David Tolnay edb1a586d8 Release 1.0.190 2023-10-25 20:05:13 -07:00
David Tolnay 11c2917040 Merge pull request #2637 from dtolnay/nansign
Ensure f32 deserialized from f64 and vice versa preserve NaN sign
2023-10-25 20:03:05 -07:00
David Tolnay 6ba9c12ff6 Float copysign does not exist in libcore yet 2023-10-25 19:55:14 -07:00
David Tolnay d2fcc346b9 Ensure f32 deserialized from f64 and vice versa preserve NaN sign 2023-10-25 19:45:53 -07:00
David Tolnay a091a07aa2 Add float NaN tests 2023-10-25 19:45:53 -07:00
David Tolnay bb4135cae8 Fix unused imports
warning: unused imports: `cmp`, `mem`, `slice`
       --> serde/src/lib.rs:171:26
        |
    171 |     pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
        |                          ^^^        ^^^            ^^^^^
        |
        = note: `#[warn(unused_imports)]` on by default
2023-10-24 22:32:42 -07:00
David Tolnay 8de84b7ca3 Resolve get_first clippy lint
warning: accessing first element with `variant.fields.get(0)`
        --> serde_derive/src/de.rs:1843:27
         |
    1843 |             let default = variant.fields.get(0).map(|field| {
         |                           ^^^^^^^^^^^^^^^^^^^^^ help: try: `variant.fields.first()`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first
         = note: `-W clippy::get-first` implied by `-W clippy::all`
         = help: to override `-W clippy::all` add `#[allow(clippy::get_first)]`

    warning: accessing first element with `variant.fields.get(0)`
        --> serde_derive/src/de.rs:1888:27
         |
    1888 |             let default = variant.fields.get(0).map(|field| {
         |                           ^^^^^^^^^^^^^^^^^^^^^ help: try: `variant.fields.first()`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first
2023-10-21 22:01:10 -07:00
David Tolnay 9cdf332029 Remove 'remember to update' reminder from Cargo.toml 2023-10-17 21:05:31 -07:00
David Tolnay e94fc65f01 Release 1.0.189 2023-10-12 19:20:43 -07:00
David Tolnay b908487476 Remove double nesting of first_attempt
`expr` is of type serde_derive::fragment::Expr, which can be
interpolated directly in any expression position. It does not
need to be nested in another set of braces.
2023-10-12 19:18:42 -07:00
David Tolnay 2a7c7faeb4 Merge pull request #2613 from ahl/fix-untagged-plus-simple
"cannot infer type" from Deserialize derive macro with simple variants and untagged variants
2023-10-12 19:15:32 -07:00
David Tolnay e302e15eea Merge pull request #2625 from marcospb19/add-csv-to-the-list
Add CSV to the formats list
2023-10-09 19:23:12 -07:00
João Marcos P. Bezerra 1cbea892cf Add CSV to the formats list 2023-10-09 22:59:56 -03:00
David Tolnay 37a32857a2 Update ui test suite to nightly-2023-10-06 2023-10-05 23:24:34 -04:00
David Tolnay 8c4aad3a59 Clean up unneeded raw strings in test 2023-09-26 19:09:30 -07:00
David Tolnay 1774794b19 Resolve needless_raw_string_hashes clippy lint in test
warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2722:9
         |
    2722 |         r#"invalid type: unit value, expected variant identifier"#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
         = note: `-W clippy::needless-raw-string-hashes` implied by `-W clippy::all`
         = help: to override `-W clippy::all` add `#[allow(clippy::needless_raw_string_hashes)]`
    help: remove all the hashes around the literal
         |
    2722 -         r#"invalid type: unit value, expected variant identifier"#,
    2722 +         r"invalid type: unit value, expected variant identifier",
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2743:9
         |
    2743 |         r#"invalid type: unit value, expected variant identifier"#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2743 -         r#"invalid type: unit value, expected variant identifier"#,
    2743 +         r"invalid type: unit value, expected variant identifier",
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2769:9
         |
    2769 |         r#"invalid type: unit value, expected variant of enum Enum"#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2769 -         r#"invalid type: unit value, expected variant of enum Enum"#,
    2769 +         r"invalid type: unit value, expected variant of enum Enum",
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2782:63
         |
    2782 |     assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
         |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2782 -     assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
    2782 +     assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r"something strange...");
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2803:9
         |
    2803 |         r#"invalid type: unit value, expected something strange..."#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2803 -         r#"invalid type: unit value, expected something strange..."#,
    2803 +         r"invalid type: unit value, expected something strange...",
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2812:9
         |
    2812 |         r#"invalid type: map, expected something strange..."#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2812 -         r#"invalid type: map, expected something strange..."#,
    2812 +         r"invalid type: map, expected something strange...",
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2817:9
         |
    2817 |         r#"invalid type: unit value, expected something strange..."#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2817 -         r#"invalid type: unit value, expected something strange..."#,
    2817 +         r"invalid type: unit value, expected something strange...",
         |

    warning: unnecessary hashes around raw string literal
        --> test_suite/tests/test_annotations.rs:2828:9
         |
    2828 |         r#"invalid type: map, expected something strange..."#,
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
    help: remove all the hashes around the literal
         |
    2828 -         r#"invalid type: map, expected something strange..."#,
    2828 +         r"invalid type: map, expected something strange...",
         |
2023-09-26 19:05:18 -07:00
David Tolnay 1af23f1f2d Test docs.rs documentation build in CI 2023-09-24 10:53:44 -07:00
Adam H. Leventhal 94fbc3d388 fix clippy 2023-09-07 22:17:22 -07:00
Adam H. Leventhal 8da2058e2a fix deserialization of untagged variants within internally or adjacently
tagged enums
2023-09-07 17:19:27 -07:00
Adam H. Leventhal 09993a904a Fix for "cannot infer type" from Deserialize derive macro with simple
variants and untagged variants
2023-09-06 15:33:28 -07:00
Adam H. Leventhal 5d1403461c add failing test 2023-09-06 15:31:16 -07:00
David Tolnay ddc1ee564b Release serde_derive_internals 0.29.0 2023-09-06 14:02:05 -07:00
David Tolnay 00a54b848a Update actions/checkout@v3 -> v4 2023-09-04 22:35:02 -07:00
David Tolnay dad15b9fd0 Release 1.0.188 2023-08-25 19:16:10 -07:00
David Tolnay d89c19f903 Revert "Adopt new Cargo feature resolver"
This reverts commit e1c27243b2.

Closes https://github.com/serde-rs/serde/issues/2603.
2023-08-25 19:15:26 -07:00
David Tolnay 146dc0fad5 Release 1.0.187 2023-08-25 10:53:36 -07:00
David Tolnay d26852deef Merge pull request #2602 from dtolnay/resolver
Adopt new Cargo feature resolver
2023-08-25 10:52:42 -07:00
David Tolnay e1c27243b2 Adopt new Cargo feature resolver 2023-08-25 10:35:02 -07:00
David Tolnay dbbfe7abe2 Merge pull request #2600 from dtolnay/oldemscripten
Remove support for emscripten targets on rustc older than 1.40
2023-08-23 22:18:20 -07:00
David Tolnay dc24d12ce0 Clean up all usage of serde_if_integer128 2023-08-23 22:14:23 -07:00
David Tolnay 4e7533e872 Remove support for emscripten targets on rustc older than 1.40 2023-08-23 22:07:21 -07:00
David Tolnay 5d036515ed Release 1.0.186 2023-08-23 17:08:06 -07:00
David Tolnay a741293886 Merge pull request #2599 from dtolnay/encodeutf8
Remove custom encode_utf8 implementation in favor of standard one
2023-08-23 17:06:39 -07:00
David Tolnay f8d0b26d2f Remove custom encode_utf8 implementation in favor of standard one 2023-08-23 17:01:58 -07:00
David Tolnay 7007c1bea5 Merge pull request #2598 from dtolnay/lockstepversion
Duplicate the serde_derive dependency version in one fewer place
2023-08-23 16:34:27 -07:00
David Tolnay 0d8ebac7e1 Duplicate the serde_derive dependency version in one fewer place 2023-08-23 16:29:29 -07:00
David Tolnay 212c42c74f Merge pull request #2597 from dtolnay/lockstepcomment
Reword PR 2588 comment
2023-08-23 16:29:21 -07:00
David Tolnay 919f6be887 Reword PR 2588 comment 2023-08-23 16:24:14 -07:00
David Tolnay c0f70428ba Merge pull request 2588 from soqb:use-impossible-cfg-to-lockstep-serde-derive 2023-08-23 16:17:23 -07:00
David Tolnay e797c90ebd Merge pull request #2594 from Uzaaft/master
Fix: Use `&[T]` instead of `&Vec<T>` wherever possible
2023-08-23 16:09:22 -07:00
David Tolnay fc04d1219a Remove useless discard of function argument that is used 2023-08-23 16:05:07 -07:00
Uzair Aftab df4ad5884d Fix: Use &[T] instead of &Vec<T> 2023-08-21 09:44:03 +02:00
David Tolnay 3c7dd6fc1e Release 1.0.185 2023-08-20 21:41:21 -07:00
David Tolnay 8b196ea1c8 Merge pull request #2592 from dtolnay/remotenonexhaustive
Fix "cannot move out of *self which is behind a shared reference"
2023-08-20 21:40:37 -07:00
David Tolnay 1f8c8ad5a3 Fix "cannot move out of *self which is behind a shared reference" 2023-08-20 21:37:14 -07:00
David Tolnay 870925d503 Add repro of issue 2591
error[E0507]: cannot move out of `*__self` which is behind a shared reference
       --> test_suite/tests/test_remote.rs:210:10
        |
    210 | #[derive(Serialize, Deserialize)]
        |          ^^^^^^^^^
        |          |
        |          data moved here
        |          move occurs because `unrecognized` has type `ErrorKind`, which does not implement the `Copy` trait
        |
        = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)
    help: consider borrowing here
        |
    210 | #[derive(&Serialize, Deserialize)]
        |          +
2023-08-20 21:36:30 -07:00
David Tolnay d593215ef7 No need for slow macOS CI if there is no platform-specific code 2023-08-20 21:27:07 -07:00
David Tolnay 110af31b48 Merge pull request #2590 from pinkforest/phase-out-precompiled
Phase out precompiled
2023-08-20 21:00:39 -07:00
pinkforest 360606b9a6 Following consensus on: #2580 (review)
This PR phases out the precompiled per final consensus made in #2580
i#
Fix a cfg
2023-08-21 13:53:48 +10:00
David Tolnay 151b45ae36 Release 1.0.184 2023-08-20 19:49:55 -07:00
soqb 2ea7e1300f guarantee serde is in lockstep with serde_derive 2023-08-21 00:53:22 +01:00
Oli Scherer 4617c957b9 Merge pull request #2587 from wucke13/master
fix shebang in build.sh
2023-08-21 00:22:31 +02:00
wucke13 2547ed83ca fix shebang in build.sh
This fixes #2583.
2023-08-20 23:51:47 +02:00
David Tolnay bfcd44704f Discard the possibility of upx compressing binary
This adds too much decompression overhead per invocation.

It could work if the subprocess were reused across multiple macro
expansions (https://github.com/serde-rs/serde/pull/2523).
2023-08-17 19:07:42 -07:00
David Tolnay 7b548db91e Merge pull request #2572 from serde-rs/cargorm
Adopt `cargo rm` after Cargo bugfix
2023-08-14 04:21:23 -07:00
David Tolnay d39dea85ad Adopt 'cargo rm' after Cargo bugfix 2023-08-14 04:12:55 -07:00
David Tolnay 5e56c9fba8 Merge pull request #2570 from dtolnay/remotenonexhaustive
Treat unmatched non-exhaustive remote variant as serde(skip)
2023-08-13 21:20:42 -07:00
David Tolnay 8d3a03288b Treat unmatched non-exhaustive remote variant as serde(skip) 2023-08-13 21:14:33 -07:00
David Tolnay cb490ec16d Add test of remote enum with non_exhaustive 2023-08-13 21:14:12 -07:00
David Tolnay 45271c3676 Resolve ignored_unit_patterns pedantic clippy lint
warning: matching over `()` is more explicit
       --> serde_derive/src/internals/attr.rs:710:33
        |
    710 |         (Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => {
        |                                 ^ help: use `()` instead of `_`: `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns
        = note: `-W clippy::ignored-unit-patterns` implied by `-W clippy::pedantic`

    warning: matching over `()` is more explicit
       --> serde_derive/src/internals/attr.rs:721:33
        |
    721 |         (Some((untagged_tokens, _)), None, Some((content_tokens, _))) => {
        |                                 ^ help: use `()` instead of `_`: `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns

    warning: matching over `()` is more explicit
       --> serde_derive/src/internals/attr.rs:728:33
        |
    728 |         (Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => {
        |                                 ^ help: use `()` instead of `_`: `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns

    warning: matching over `()` is more explicit
       --> serde_derive/src/internals/attr.rs:750:44
        |
    750 |         (_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
        |                                            ^ help: use `()` instead of `_`: `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns

    warning: matching over `()` is more explicit
       --> serde_derive/src/internals/attr.rs:750:82
        |
    750 |         (_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
        |                                                                                  ^ help: use `()` instead of `_`: `()`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns
2023-08-11 20:27:21 -07:00
Mingun 6a097eca93 Add canary test to ensure that we use adequate enum representation 2023-08-07 20:33:12 +05:00
Mingun 84d1c5385d Use correct tokens in test to represent an enum variant
Unit variant of externally tagged enum cannot be deserialized from the string
token by itself. It is ContentDeserializer + serde_test::Deserializer that makes
this possible, because serde_test::Deserializer produces Content::Str() from
Token::BorrowedStr() and ContentDeserializer produces unit variant from Content::Str().

The following tokens all produces Content::String(variant):
- Token::String(variant)
- Token::Str(variant)
- Token::UnitVariant { variant, .. }

Token::BorrowedStr(variant) produces Content::Str(variant) that was the real purpose to
use it in test in #933. This actually makes this test testing `Content` rather than type itself.

Correct way to represent enum one of:
- [xxxVariant { .. }]
- [Enum { .. }, xxxVariant { variant, .. }]
- [Enum { .. }, String(variant), <variant content>]
- [Enum { .. }, Str(variant), <variant content>]
- [Enum { .. }, BorrowedStr(variant), <variant content>]
2023-08-07 19:19:00 +05:00
David Tolnay 05a5b7e3c6 Release 1.0.183 2023-08-06 21:00:14 -07:00
David Tolnay 3bff326fb3 Merge pull request #2555 from Mingun/field
Refactor code that generates `__Field` enums
2023-08-06 18:23:52 -07:00
David Tolnay aaadd93878 Merge pull request #2556 from DBLouis/master
Add forward impl for OsStr
2023-08-06 18:02:21 -07:00
Louis Dupré Bertoni 9c864f0b02 Add forward impl for OsStr 2023-08-06 19:41:19 +03:00
Mingun 070cce0d9c Get rid of temporary variable 2023-08-06 19:55:48 +05:00
Mingun b58e8bac12 Replace if let Some(...) = ... to Option::map 2023-08-06 19:53:39 +05:00
Mingun ada50b077e ignore_variant variable is always None, let's take this into account 2023-08-06 19:36:48 +05:00
Mingun 5e313a7330 Move generiс code out-of-function, create more specialized and simple code 2023-08-06 19:35:27 +05:00
Mingun 2a36d11238 Introduce a dedicated function for generating Field enum
(the enum that represents all fields of a struct)
2023-08-06 19:32:53 +05:00
David Tolnay b6685cf9dd Release 1.0.182 2023-08-05 22:16:46 -07:00
David Tolnay fc273c6763 Resolve needless_return clippy lint in PR 2553
warning: unneeded `return` statement
        --> serde_derive/src/de.rs:2986:13
         |
    2986 |             return quote!(#assign_to __default.#member);
         |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
         = note: `-W clippy::needless-return` implied by `-W clippy::all`
    help: remove `return`
         |
    2986 -             return quote!(#assign_to __default.#member);
    2986 +             quote!(#assign_to __default.#member)
         |
2023-08-05 22:16:19 -07:00
David Tolnay bd7b0e257e Touch up PR 2553 2023-08-05 22:13:09 -07:00
David Tolnay 73931692b2 Merge pull request #2553 from Mingun/default-on-tuples
Allow `#[serde(default)]` on tuple structs
2023-08-05 22:12:10 -07:00
David Tolnay 4d93e9f44c Keep deserialize aliases as a sorted set 2023-08-05 17:06:11 -07:00
David Tolnay da55ed7e8d Remove some clones of names of things 2023-08-05 17:01:34 -07:00
David Tolnay e3617e1f28 Update explanation of correct_aliases 2023-08-05 16:39:38 -07:00
David Tolnay 431636af0d Merge pull request #2458 from Mingun/identifier
Keep aliases always sorted and include aliases in expecting message for field/variant_identifier
2023-08-05 16:39:14 -07:00
David Tolnay 891ced598a Update test suite to nightly-2023-08-05
error: the feature `lang_items` is internal to the compiler or standard library
     --> src/main.rs:1:12
      |
    1 | #![feature(lang_items, start)]
      |            ^^^^^^^^^^
      |
      = note: using it is strongly discouraged
      = note: `#[deny(internal_features)]` on by default
2023-08-04 19:09:00 -07:00
David Tolnay 57dc0ee769 Release 1.0.181 2023-08-03 16:58:45 -07:00
David Tolnay 5e102c4da1 Relocate private size_hint module
Let's keep crate::__private for only things that *need* to be accessible
to the macro-generated code. Size_hint can be pub(crate).
2023-08-03 16:53:44 -07:00
Mingun 5c33931422 Allow #[serde(default)] on tuple structs 2023-08-03 22:32:34 +05:00
David Tolnay 4aa54222f4 Delete double reference when setting up adjacently tagged variant seed 2023-08-01 22:54:47 -07:00
David Tolnay ef4f860384 Improve "expecting" message of adjacently tagged enum variant 2023-08-01 22:49:44 -07:00
David Tolnay 9bd52ec5c1 Inline AdjacentlyTaggedEnumVariant::new 2023-08-01 22:38:47 -07:00
David Tolnay 5cdd82d41e Remove Serializer from name of private type that is not a Serializer 2023-08-01 22:26:04 -07:00
David Tolnay 110bf10481 Condense AdjacentlyTaggedEnummVariantVisitor implementation 2023-08-01 22:26:03 -07:00
David Tolnay 43035f6f37 Merge pull request #2505 from Baptistemontan/rework_adjacently_tagged_enum
Revisit of the representation of adjacently tagged enums tag
2023-08-01 22:25:31 -07:00
David Tolnay 83b1a3d5dc Merge pull request #2443 from Mingun/deserialize-in-place
Simplify code in deserialize_in_place_struct and implement #2387 for in-place case
2023-08-01 21:51:22 -07:00
Mingun 878110a4bc Simplify code after dead code elimination 2023-08-01 19:03:21 +05:00
Mingun 59ec8b7db2 Remove dead code - variant_ident and deserializer are always None 2023-08-01 19:03:20 +05:00
Mingun cae1b43829 Inline deserialize_newtype_struct_in_place 2023-08-01 19:03:19 +05:00
Mingun 99fde4ee3e Implement #2387 also for deserialize_in_place method 2023-08-01 19:03:19 +05:00
Mingun afe3872810 Simplify check for missing fields 2023-08-01 19:03:18 +05:00
Mingun 3a3e6bf103 Reorder variables to match order in final quote! 2023-08-01 19:03:18 +05:00
Mingun 935f0bd70f Merge some quote! blocks 2023-08-01 19:03:17 +05:00
Mingun 5c18bfeda6 Inline deserialize_struct_as_struct_in_place_visitor 2023-08-01 19:03:17 +05:00
Baptiste de Montangon 957ef206d1 Revisit of the representation of adjacently tagged enums tag 2023-07-31 20:53:02 +02:00
David Tolnay 0c367838cc Merge pull request #2548 from dtolnay/toolattr
Adopt tool attrs for clippy lint level attributes
2023-07-31 11:48:33 -07:00
David Tolnay 2023cf345f Adopt tool attrs for clippy lint level attributes
Requires rustc 1.31+.
2023-07-31 11:39:31 -07:00
David Tolnay 033d05f70b Release 1.0.180 2023-07-31 11:16:12 -07:00
David Tolnay fe4e3fd3b0 Merge pull request #2547 from dtolnay/tombstone
Delete tombstones of the `__private` module
2023-07-30 22:48:34 -07:00
David Tolnay 8a8a8a70ee Delete tombstones of the __private module
These are previous names of the `__private` module -- first
`serde::export` then `serde::private` then `serde::__private` -- in all
cases marked `doc(hidden)` and documented as not public API. Leaving a
tombstone made rustc give a better diagnostic "module is private" rather
than "unresolved import". But the rename to `__private` was 2.5 years
ago in dd1f4b483e so it's unlikely anyone
is still benefiting from the tombstone at this point.
2023-07-30 22:44:59 -07:00
David Tolnay 339dca828d Merge pull request #2546 from dtolnay/edition
Update to 2018 edition
2023-07-30 22:11:44 -07:00
David Tolnay 0d7349fa4e Resolve ambiguous core import on rustc 1.64 through 1.71
In 1.72+, this is fixed by https://github.com/rust-lang/rust/pull/112086.

    error[E0659]: `core` is ambiguous
       --> serde/src/lib.rs:227:13
        |
    227 |     pub use core::ffi::CStr;
        |             ^^^^ ambiguous name
        |
        = note: ambiguous because of multiple potential import sources
        = note: `core` could refer to a built-in crate
        = help: use `::core` to refer to this crate unambiguously
    note: `core` could also refer to the module defined here
       --> serde/src/lib.rs:166:5
        |
    166 | /     mod core {
    167 | |         #[cfg(not(feature = "std"))]
    168 | |         pub use core::*;
    169 | |         #[cfg(feature = "std")]
    170 | |         pub use std::*;
    171 | |     }
        | |_____^
        = help: use `self::core` to refer to this module unambiguously
2023-07-30 22:06:18 -07:00
David Tolnay 830528d5b1 Update to 2018 edition 2023-07-30 21:45:35 -07:00
David Tolnay ab90fbc7c9 Apply 'cargo fix --edition' 2023-07-30 21:42:57 -07:00
David Tolnay 3eec111e8f Delete support for compilers without crate::-based module system 2023-07-30 21:42:57 -07:00
David Tolnay 9388433642 Rename 'try!' macro to 'tri!' in preparation for 2018 edition
Because 'try' is a keyword in 2018+.
2023-07-30 21:29:53 -07:00
David Tolnay ba12070665 Merge pull request #2545 from dtolnay/up
Delete support for rustc versions 1.19 through 1.27
2023-07-30 21:25:58 -07:00
David Tolnay a57a324d72 Delete support for compilers without NonZero integer types 2023-07-30 21:14:32 -07:00
David Tolnay 92e91b3557 Delete support for compilers without Iterator::try_for_each 2023-07-30 21:14:31 -07:00
David Tolnay 4dcf791706 Delete support for compilers without inclusive range accessors 2023-07-30 21:11:43 -07:00
David Tolnay e77900fb94 Update integer128 case in build script 2023-07-30 21:11:09 -07:00
David Tolnay 1b14cadf20 Delete support for compilers without core::ops::Bound 2023-07-30 21:11:02 -07:00
David Tolnay 4f59cd217a Delete support for compilers without core::time 2023-07-30 21:10:49 -07:00
David Tolnay 27c8b2d66a Delete support for compilers without dynamically sized Rc construction 2023-07-30 20:48:27 -07:00
David Tolnay 89976c2712 Delete support for compilers without PathBuf::into_boxed_path 2023-07-30 20:48:27 -07:00
David Tolnay c91737fef1 Delete support for compilers without CString::into_boxed_c_str 2023-07-30 20:48:27 -07:00
David Tolnay a100719bc6 Delete support for compilers without core::cmp::Reverse 2023-07-30 20:48:27 -07:00
David Tolnay 9a0e149225 Sort version checks in build.rs 2023-07-30 20:48:27 -07:00
David Tolnay 9350927903 Delete support for compilers without std::collections::Bound 2023-07-30 20:48:27 -07:00
David Tolnay 677c13a4ec Merge pull request #2544 from dtolnay/testprecompiled
Add CI job to run test suite against precompiled serde_derive
2023-07-30 18:58:13 -07:00
David Tolnay ee8e1ee7ff Add CI job to run test suite against precompiled serde_derive 2023-07-30 18:50:16 -07:00
David Tolnay f969080b9f Pull in syn fix that makes serde test suite independent of "full" feature
See https://github.com/dtolnay/syn/pull/1491.
2023-07-30 17:39:44 -07:00
David Tolnay c2b16bfbb0 Release 1.0.179 2023-07-30 17:20:10 -07:00
David Tolnay e7df53701c Resolve doc_markdown clippy lint from PR 2448
warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2870:25
         |
    2870 |             /// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
         = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic`
    help: try
         |
    2870 |             /// Reaches `crate::private::de::content::VariantDeserializer::tuple_variant`
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2871:17
         |
    2871 |             /// Content::Seq case
         |                 ^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2871 |             /// `Content::Seq` case
         |                 ~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2872:21
         |
    2872 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2872 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2894:25
         |
    2894 |             /// Reaches crate::private::de::content::VariantDeserializer::struct_variant
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2894 |             /// Reaches `crate::private::de::content::VariantDeserializer::struct_variant`
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2895:17
         |
    2895 |             /// Content::Seq case
         |                 ^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2895 |             /// `Content::Seq` case
         |                 ~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2896:21
         |
    2896 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2896 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2921:25
         |
    2921 |             /// Reaches crate::private::de::content::VariantDeserializer::struct_variant
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2921 |             /// Reaches `crate::private::de::content::VariantDeserializer::struct_variant`
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2922:17
         |
    2922 |             /// Content::Map case
         |                 ^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2922 |             /// `Content::Map` case
         |                 ~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2923:21
         |
    2923 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2923 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-07-30 16:15:29 -07:00
David Tolnay 02c34e490b Resolve redundant_field_names clippy lint from PR 2448
warning: redundant field names in struct initialization
        --> serde/src/private/ser.rs:1278:13
         |
    1278 |             map: map,
         |             ^^^^^^^^ help: replace it with: `map`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
         = note: `-W clippy::redundant-field-names` implied by `-W clippy::all`
2023-07-30 16:07:27 -07:00
David Tolnay 427c839b3d Merge pull request #2448 from Mingun/ser-flatten-enums
Implement serialization of tuple variants of flatten enums
2023-07-30 16:02:37 -07:00
David Tolnay 48aa054f53 Release 1.0.178 2023-07-28 16:09:39 -07:00
David Tolnay 3616860203 Delete broken symlink from precompiled derive sources 2023-07-28 16:09:22 -07:00
David Tolnay 861b0dfea2 Consistently list StdError under 'Re-exports' heading of rustdoc 2023-07-28 16:06:49 -07:00
David Tolnay 8b3d71ae2d Merge pull request #2541 from dtolnay/de-core-error
Fix `serde::de::StdError` in no-std unstable build
2023-07-28 16:05:14 -07:00
David Tolnay ff5442cd9e Add no-std unstable build in CI 2023-07-28 16:00:07 -07:00
David Tolnay 92d686f9a5 Fix serde::de::StdError in no-std unstable build 2023-07-28 15:58:57 -07:00
David Tolnay 7b09cccd77 Merge pull request #2539 from dtolnay/questionmark
Replace `try!` with `?` in serde_derive
2023-07-27 19:20:15 -07:00
David Tolnay 6f1f38d046 Replace 'try!' with '?' in serde_derive 2023-07-27 19:16:11 -07:00
David Tolnay db8f06467b Eliminate workaround for pre-1.17 rustc in serde_derive
The oldest compiler supported by serde_derive by this point is 1.56.
2023-07-27 19:05:57 -07:00
David Tolnay 91ec1c290f Enforce question mark not used in serde crate yet
Question mark regresses compile time by 6.5–7.5%.
2023-07-27 19:02:11 -07:00
Mingun f709fc05b0 Do not run the code when results are not used 2023-07-23 15:23:39 +05:00
Mingun 089aae1292 Eliminate even more allocations 2023-07-23 15:23:39 +05:00
Mingun 855acaf112 Eliminate additional allocations for flattening aliases 2023-07-23 15:23:38 +05:00
Mingun 7ca7720262 Slightly reduced number of allocations 2023-07-23 15:23:37 +05:00
Mingun 78fea3aa4a Show possible aliases in the expected message
Fixes tests
2023-07-23 15:23:37 +05:00
Mingun 1efb8b6a53 Add tests for aliases
failures (2):
    field_identifier::unknown
    variant_identifier::unknown
2023-07-23 15:23:36 +05:00
Mingun bc1960b106 Add tests for unknown field / variant 2023-07-23 15:23:33 +05:00
Mingun 967023b755 Group field_identifier and variant_identifier tests in sub-modules
(review this commit with "ignore whitespace changes" option on)
2023-07-23 15:21:22 +05:00
Mingun bb51e68f16 Keep aliases sorted 2023-07-23 15:21:21 +05:00
Mingun 4e5e55bf1c Remove custom implementations of SeqDeserializer and MapDeserializer for enums
Those deserializers are used to deserialize tuple or struct variants from Content
which is used by internally tagged enums and by flatten

FlatMapDeserializer is reached in the following tests:
    flatten::enum_::externally_tagged::newtype
    flatten::enum_::externally_tagged::struct_from_map
    flatten::enum_::externally_tagged::struct_from_seq
    flatten::enum_::externally_tagged::tuple

ContentDeserializer is reached in the following tests:
    test_enum_in_internally_tagged_enum
    test_internally_tagged_struct_variant_containing_unit_variant
2023-07-11 22:01:48 +05:00
Mingun 4513a9e6a7 Move test_flatten_enum_newtype into new group of flatten tests - flatten::enum_::externally_tagged::newtype 2023-07-11 22:00:38 +05:00
Mingun 4f922e4e5b Implement serialization of flattened tuple variants of externally tagged enums
The Container struct

  struct Container {
    #[serde(flatten)]
    enum_field: Enum,
  }
  enum Enum {
    Tuple(u32, u32),
  }

now can be serialized to JSON as

  { "enum_field": [1, 2] }

Deserialization already works

Fixes (1):
    flatten::enum_::externally_tagged::tuple
2023-07-11 22:00:10 +05:00
Mingun 993966600e Implement tests for crate::private::de::content::VariantDeserializer
failures (1):
    flatten::enum_::externally_tagged::tuple
2023-07-11 21:59:22 +05:00
Mingun 5b96cf1bde Use traditional order for enum variants (Unit, Newtype, Tuple, Struct) and names for tag and content fields 2023-07-11 21:58:43 +05:00
Mingun f3d50e5209 Use FromIterator to fill HashMap 2023-07-11 21:58:14 +05:00
Mingun ab21d4d017 Merge assert_de_tokens and assert_ser_tokens into assert_tokens 2023-07-11 21:57:49 +05:00
Mingun f7c5d93e6a Pull up types from function into module, unify style 2023-07-11 21:57:22 +05:00
Mingun 52a7d40e6e Rename test types so their names reflects, what's tested 2023-07-11 21:56:53 +05:00
Mingun 348bc6b257 Move flatten enum tests to a dedicated module
(review with "ignore whitespace" option on and editor that shows line moves,
for example, TortoiseGitMerge)
2023-07-11 21:56:22 +05:00
107 changed files with 3637 additions and 4052 deletions
+31 -40
View File
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable
@@ -27,7 +27,7 @@ jobs:
runs-on: windows-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
@@ -40,7 +40,7 @@ jobs:
rust: [stable, beta]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
@@ -56,12 +56,13 @@ jobs:
os: [ubuntu, windows]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cd serde && cargo build
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build --no-default-features --features alloc
- run: cd serde && cargo build --no-default-features --features rc,alloc
- run: cd serde && cargo build --no-default-features --features unstable
- run: cd serde && cargo test --features derive,rc,unstable
- run: cd test_suite/no_std && cargo build
if: matrix.os != 'windows'
@@ -76,82 +77,71 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
rust: [1.31.0, 1.34.0]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- run: sed -i '/"test_suite"/d' Cargo.toml
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build
more:
name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [1.27.0, 1.28.0]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
# Work around failing to parse manifest because editions are unstable.
- run: sed -i /test_suite/d Cargo.toml
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build
derive:
name: Rust 1.56.0
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.56.0
- run: sed -i '/"test_suite"/d' Cargo.toml
- run: cd serde && cargo check --no-default-features
- run: cd serde && cargo check
- run: cd serde_derive && cargo check
- run: cd precompiled/serde_derive && cargo check
alloc:
name: Rust 1.36.0
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.36.0
- run: sed -i '/"test_suite"/d' Cargo.toml
- run: cd serde && cargo build --no-default-features --features alloc
macos:
name: macOS
runs-on: macos-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- run: cd precompiled/serde_derive && cargo check
minimal:
name: Minimal versions
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cargo generate-lockfile -Z minimal-versions
- run: cargo check --locked --workspace
doc:
name: Documentation
runs-on: ubuntu-latest
timeout-minutes: 45
env:
RUSTDOCFLAGS: -Dwarnings
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/install@cargo-docs-rs
- run: cargo docs-rs -p serde
- run: cargo docs-rs -p serde_derive
- run: cargo docs-rs -p serde_derive_internals
clippy:
name: Clippy
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@clippy
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
@@ -164,7 +154,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@miri
- run: cargo miri setup
- run: cd serde && cargo miri test --features derive,rc,unstable
@@ -180,6 +170,7 @@ jobs:
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/install@cargo-outdated
- run: cargo outdated --workspace --exit-code 1
+5
View File
@@ -8,3 +8,8 @@ members = [
[patch.crates-io]
serde = { path = "serde" }
[workspace.dependencies]
proc-macro2 = { version = "1.0.74", default-features = false }
quote = { version = "1.0.35", default-features = false }
syn = { version = "2.0.46", default-features = false }
+4 -4
View File
@@ -1,12 +1,12 @@
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.19+]][Rust 1.19] [![serde_derive: rustc 1.56+]][Rust 1.56]
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56]
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
[serde: rustc 1.19+]: https://img.shields.io/badge/serde-rustc_1.19+-lightgray.svg
[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg
[Rust 1.19]: https://blog.rust-lang.org/2017/07/20/Rust-1.19.html
[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray
[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
+2 -2
View File
@@ -46,8 +46,8 @@ fn main() {
Serde is one of the most widely used Rust libraries so any place that Rustaceans
congregate will be able to help you out. For chat, consider trying the
[#rust-questions] or [#rust-beginners] channels of the unofficial community
Discord (invite: <https://discord.gg/rust-lang-community>, the [#rust-usage] or
[#beginners] channels of the official Rust Project Discord (invite:
Discord (invite: <https://discord.gg/rust-lang-community>), the [#rust-usage]
or [#beginners] channels of the official Rust Project Discord (invite:
<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
-1
View File
@@ -1 +0,0 @@
/serde_derive/serde_derive-x86_64-unknown-linux-gnu
-14
View File
@@ -1,14 +0,0 @@
[workspace]
members = ["bin", "proc-macro2"]
resolver = "2"
[patch.crates-io]
proc-macro2 = { path = "proc-macro2" }
[profile.precompiled]
inherits = "release"
codegen-units = 1
lto = true
opt-level = "z"
panic = "abort"
strip = true
-17
View File
@@ -1,17 +0,0 @@
[package]
name = "serde_derive"
version = "1.0.177"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[lib]
doctest = false
[[bin]]
name = "serde_derive"
path = "main.rs"
[dependencies]
proc-macro2 = "1"
quote = { version = "1", default-features = false }
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "full", "parsing", "printing"] }
-4
View File
@@ -1,4 +0,0 @@
fn main() {
println!("cargo:rustc-cfg=precompiled");
println!("cargo:rustc-cfg=feature=\"deserialize_in_place\"");
}
-45
View File
@@ -1,45 +0,0 @@
extern crate proc_macro2;
use proc_macro2::watt;
use proc_macro2::watt::buffer::InputBuffer;
use std::alloc::{GlobalAlloc, Layout, System};
use std::io::{self, Read, Write};
use std::sync::atomic::Ordering;
struct MonotonicAllocator;
#[global_allocator]
static ALLOCATOR: MonotonicAllocator = MonotonicAllocator;
unsafe impl GlobalAlloc for MonotonicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
System.alloc(layout)
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
// Leak: this cuts 3% of code size from the precompiled macro binary.
// There is no way that serde_derive would fill up all memory on the
// host. When the subprocess exits, operating system will clean this up.
}
}
fn main() {
let mut buf = Vec::new();
io::stdin().read_to_end(&mut buf).unwrap();
let mut buf = InputBuffer::new(&buf);
let derive = match buf.read_u8() {
0 => serde_derive::derive_serialize,
1 => serde_derive::derive_deserialize,
2 => {
serde_derive::DESERIALIZE_IN_PLACE.store(true, Ordering::Relaxed);
serde_derive::derive_deserialize
}
_ => unreachable!(),
};
let input = watt::load(&mut buf);
let output = derive(input);
let bytes = watt::linearize(output);
io::stdout().write_all(&bytes).unwrap();
}
-1
View File
@@ -1 +0,0 @@
../../serde_derive/src
-21
View File
@@ -1,21 +0,0 @@
#!/bin/bash
cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null
set -e -x
# TODO: Sanitize host filesystem paths. https://github.com/rust-lang/cargo/issues/12137
cargo +nightly build \
--manifest-path bin/Cargo.toml \
--bin serde_derive \
--profile precompiled \
-Z unstable-options \
-Z build-std=std,panic_abort \
-Z build-std-features=panic_immediate_abort \
--target x86_64-unknown-linux-musl \
--out-dir serde_derive
rm -f serde_derive/serde_derive-x86_64-unknown-linux-gnu
mv serde_derive/serde_derive{,-x86_64-unknown-linux-gnu}
#upx --best --lzma serde_derive/serde_derive-x86_64-unknown-linux-gnu
-8
View File
@@ -1,8 +0,0 @@
[package]
name = "proc-macro2"
version = "1.0.66"
edition = "2021"
publish = false
[dependencies]
proc-macro2 = { package = "proc-macro2-fallback", version = "1" }
-815
View File
@@ -1,815 +0,0 @@
#[doc(hidden)]
pub mod watt;
use crate::extra::DelimSpan;
use crate::watt::Identity;
use std::cmp::Ordering;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::ops::RangeBounds;
use std::str::FromStr;
pub use proc_macro2::{Delimiter, Spacing};
#[derive(Copy, Clone)]
pub struct Span {
lo: u32,
hi: u32,
}
impl Span {
pub fn call_site() -> Self {
Span { lo: 0, hi: 0 }
}
pub fn join(&self, other: Self) -> Option<Self> {
Some(Span {
lo: self.lo,
hi: other.hi,
})
}
}
#[derive(Clone)]
pub enum TokenTree {
Group(Group),
Ident(Ident),
Punct(Punct),
Literal(Literal),
}
impl TokenTree {
pub fn span(&self) -> Span {
match self {
TokenTree::Group(group) => group.span(),
TokenTree::Ident(ident) => ident.span(),
TokenTree::Punct(punct) => punct.span(),
TokenTree::Literal(literal) => literal.span(),
}
}
pub fn set_span(&mut self, span: Span) {
match self {
TokenTree::Group(group) => group.set_span(span),
TokenTree::Ident(ident) => ident.set_span(span),
TokenTree::Punct(punct) => punct.set_span(span),
TokenTree::Literal(literal) => literal.set_span(span),
}
}
}
impl From<Group> for TokenTree {
fn from(group: Group) -> Self {
TokenTree::Group(group)
}
}
impl From<Ident> for TokenTree {
fn from(ident: Ident) -> Self {
TokenTree::Ident(ident)
}
}
impl From<Punct> for TokenTree {
fn from(punct: Punct) -> Self {
TokenTree::Punct(punct)
}
}
impl From<Literal> for TokenTree {
fn from(literal: Literal) -> Self {
TokenTree::Literal(literal)
}
}
impl Debug for TokenTree {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
TokenTree::Group(group) => Debug::fmt(group, formatter),
TokenTree::Ident(ident) => {
let mut debug = formatter.debug_struct("Ident");
debug.field("sym", &format_args!("{}", ident));
debug.finish()
}
TokenTree::Punct(punct) => Debug::fmt(punct, formatter),
TokenTree::Literal(literal) => Debug::fmt(literal, formatter),
}
}
}
#[derive(Clone)]
pub struct Group {
delimiter: Delimiter,
stream: Vec<TokenTree>,
span: Span,
span_open: Span,
span_close: Span,
identity: u32,
}
impl Group {
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
Group {
delimiter,
stream: stream.content,
span: Span::call_site(),
span_open: Span::call_site(),
span_close: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn stream(&self) -> TokenStream {
TokenStream {
content: self.stream.clone(),
}
}
pub fn delimiter(&self) -> Delimiter {
self.delimiter
}
pub fn span(&self) -> Span {
self.span
}
pub fn span_open(&self) -> Span {
self.span_open
}
pub fn span_close(&self) -> Span {
self.span_close
}
pub fn delim_span(&self) -> DelimSpan {
DelimSpan {
join: self.span,
open: self.span_open,
close: self.span_close,
}
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
}
impl Display for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let (open, close) = match self.delimiter {
Delimiter::Parenthesis => ("(", ")"),
Delimiter::Brace => ("{ ", "}"),
Delimiter::Bracket => ("[", "]"),
Delimiter::None => ("", ""),
};
formatter.write_str(open)?;
display_tokens(&self.stream, formatter)?;
if self.delimiter == Delimiter::Brace && !self.stream.is_empty() {
formatter.write_str(" ")?;
}
formatter.write_str(close)?;
Ok(())
}
}
impl Debug for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let mut debug = formatter.debug_struct("Group");
debug.field("delimiter", &self.delimiter);
debug.field("stream", &self.stream);
debug.finish()
}
}
#[derive(Clone)]
pub struct Ident {
fallback: proc_macro2::Ident,
span: Span,
identity: u32,
}
impl Ident {
pub fn new(string: &str, span: Span) -> Self {
Ident {
fallback: proc_macro2::Ident::new(string, proc_macro2::Span::call_site()),
span,
identity: Identity::NOVEL,
}
}
pub fn new_raw(string: &str, span: Span) -> Self {
Ident {
fallback: proc_macro2::Ident::new_raw(string, proc_macro2::Span::call_site()),
span,
identity: Identity::NOVEL,
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
}
impl Display for Ident {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.fallback, formatter)
}
}
impl Debug for Ident {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
impl Eq for Ident {}
impl PartialEq for Ident {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.fallback, &other.fallback)
}
}
impl<T> PartialEq<T> for Ident
where
T: ?Sized + AsRef<str>,
{
fn eq(&self, other: &T) -> bool {
PartialEq::eq(&self.fallback, other)
}
}
impl Ord for Ident {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.fallback, &other.fallback)
}
}
impl PartialOrd for Ident {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.fallback, &other.fallback)
}
}
impl Hash for Ident {
fn hash<H: Hasher>(&self, hasher: &mut H) {
Hash::hash(&self.fallback, hasher);
}
}
#[derive(Clone)]
pub struct Punct {
fallback: proc_macro2::Punct,
span: Span,
identity: u32,
}
impl Punct {
pub fn new(ch: char, spacing: Spacing) -> Self {
Punct {
fallback: proc_macro2::Punct::new(ch, spacing),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn as_char(&self) -> char {
self.fallback.as_char()
}
pub fn spacing(&self) -> Spacing {
self.fallback.spacing()
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
}
impl Display for Punct {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.fallback, formatter)
}
}
impl Debug for Punct {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
#[derive(Clone)]
pub struct Literal {
fallback: proc_macro2::Literal,
span: Span,
identity: u32,
}
impl Literal {
pub fn u8_suffixed(n: u8) -> Self {
Literal {
fallback: proc_macro2::Literal::u8_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u16_suffixed(n: u16) -> Self {
Literal {
fallback: proc_macro2::Literal::u16_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u32_suffixed(n: u32) -> Self {
Literal {
fallback: proc_macro2::Literal::u32_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u64_suffixed(n: u64) -> Self {
Literal {
fallback: proc_macro2::Literal::u64_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u128_suffixed(n: u128) -> Self {
Literal {
fallback: proc_macro2::Literal::u128_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn usize_suffixed(n: usize) -> Self {
Literal {
fallback: proc_macro2::Literal::usize_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i8_suffixed(n: i8) -> Self {
Literal {
fallback: proc_macro2::Literal::i8_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i16_suffixed(n: i16) -> Self {
Literal {
fallback: proc_macro2::Literal::i16_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i32_suffixed(n: i32) -> Self {
Literal {
fallback: proc_macro2::Literal::i32_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i64_suffixed(n: i64) -> Self {
Literal {
fallback: proc_macro2::Literal::i64_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i128_suffixed(n: i128) -> Self {
Literal {
fallback: proc_macro2::Literal::i128_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn isize_suffixed(n: isize) -> Self {
Literal {
fallback: proc_macro2::Literal::isize_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u8_unsuffixed(n: u8) -> Self {
Literal {
fallback: proc_macro2::Literal::u8_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u16_unsuffixed(n: u16) -> Self {
Literal {
fallback: proc_macro2::Literal::u16_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u32_unsuffixed(n: u32) -> Self {
Literal {
fallback: proc_macro2::Literal::u32_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u64_unsuffixed(n: u64) -> Self {
Literal {
fallback: proc_macro2::Literal::u64_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u128_unsuffixed(n: u128) -> Self {
Literal {
fallback: proc_macro2::Literal::u128_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn usize_unsuffixed(n: usize) -> Self {
Literal {
fallback: proc_macro2::Literal::usize_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i8_unsuffixed(n: i8) -> Self {
Literal {
fallback: proc_macro2::Literal::i8_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i16_unsuffixed(n: i16) -> Self {
Literal {
fallback: proc_macro2::Literal::i16_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i32_unsuffixed(n: i32) -> Self {
Literal {
fallback: proc_macro2::Literal::i32_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i64_unsuffixed(n: i64) -> Self {
Literal {
fallback: proc_macro2::Literal::i64_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i128_unsuffixed(n: i128) -> Self {
Literal {
fallback: proc_macro2::Literal::i128_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn isize_unsuffixed(n: isize) -> Self {
Literal {
fallback: proc_macro2::Literal::isize_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f64_unsuffixed(f: f64) -> Self {
Literal {
fallback: proc_macro2::Literal::f64_unsuffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f64_suffixed(f: f64) -> Self {
Literal {
fallback: proc_macro2::Literal::f64_suffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f32_unsuffixed(f: f32) -> Self {
Literal {
fallback: proc_macro2::Literal::f32_unsuffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f32_suffixed(f: f32) -> Self {
Literal {
fallback: proc_macro2::Literal::f32_suffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn string(string: &str) -> Self {
Literal {
fallback: proc_macro2::Literal::string(string),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn character(ch: char) -> Self {
Literal {
fallback: proc_macro2::Literal::character(ch),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn byte_string(s: &[u8]) -> Self {
Literal {
fallback: proc_macro2::Literal::byte_string(s),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
let _ = range;
None
}
}
impl FromStr for Literal {
type Err = LexError;
fn from_str(repr: &str) -> Result<Self, Self::Err> {
let fallback = match proc_macro2::Literal::from_str(repr) {
Ok(literal) => literal,
Err(error) => {
return Err(LexError {
fallback: error,
span: Span::call_site(),
});
}
};
Ok(Literal {
fallback,
span: Span::call_site(),
identity: Identity::NOVEL,
})
}
}
impl Display for Literal {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.fallback, formatter)
}
}
impl Debug for Literal {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
#[derive(Clone)]
pub struct TokenStream {
content: Vec<TokenTree>,
}
impl TokenStream {
pub fn new() -> Self {
TokenStream {
content: Vec::new(),
}
}
pub fn is_empty(&self) -> bool {
self.content.is_empty()
}
}
impl IntoIterator for TokenStream {
type Item = TokenTree;
type IntoIter = token_stream::IntoIter;
fn into_iter(self) -> Self::IntoIter {
token_stream::IntoIter {
iter: self.content.into_iter(),
}
}
}
impl Extend<TokenStream> for TokenStream {
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
self.content.extend(streams.into_iter().flatten());
}
}
impl Extend<TokenTree> for TokenStream {
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
self.content.extend(streams);
}
}
impl FromIterator<TokenStream> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
let content = streams.into_iter().flatten().collect();
TokenStream { content }
}
}
impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
let content = streams.into_iter().collect();
TokenStream { content }
}
}
impl FromStr for TokenStream {
type Err = LexError;
fn from_str(string: &str) -> Result<Self, Self::Err> {
let fallback = match proc_macro2::TokenStream::from_str(string) {
Ok(token_stream) => token_stream,
Err(error) => {
return Err(LexError {
fallback: error,
span: Span::call_site(),
});
}
};
fn convert_token_stream(stream: proc_macro2::TokenStream) -> TokenStream {
TokenStream {
content: stream.into_iter().map(convert_token_tree).collect(),
}
}
fn convert_token_tree(token: proc_macro2::TokenTree) -> TokenTree {
match token {
proc_macro2::TokenTree::Group(group) => TokenTree::Group(Group::new(
group.delimiter(),
convert_token_stream(group.stream()),
)),
proc_macro2::TokenTree::Ident(ident) => TokenTree::Ident(Ident {
fallback: ident,
span: Span::call_site(),
identity: Identity::NOVEL,
}),
proc_macro2::TokenTree::Punct(punct) => TokenTree::Punct(Punct {
fallback: punct,
span: Span::call_site(),
identity: Identity::NOVEL,
}),
proc_macro2::TokenTree::Literal(literal) => TokenTree::Literal(Literal {
fallback: literal,
span: Span::call_site(),
identity: Identity::NOVEL,
}),
}
}
Ok(convert_token_stream(fallback))
}
}
fn display_tokens(tokens: &[TokenTree], formatter: &mut fmt::Formatter) -> fmt::Result {
let mut joint = false;
for (i, token) in tokens.iter().enumerate() {
if i != 0 && !joint {
write!(formatter, " ")?;
}
joint = false;
match token {
TokenTree::Group(group) => Display::fmt(group, formatter),
TokenTree::Ident(ident) => Display::fmt(ident, formatter),
TokenTree::Punct(punct) => {
joint = punct.spacing() == Spacing::Joint;
Display::fmt(punct, formatter)
}
TokenTree::Literal(literal) => Display::fmt(literal, formatter),
}?;
}
Ok(())
}
impl Display for TokenStream {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
display_tokens(&self.content, formatter)
}
}
impl Debug for TokenStream {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("TokenStream ")?;
formatter.debug_list().entries(&self.content).finish()
}
}
pub struct LexError {
fallback: proc_macro2::LexError,
span: Span,
}
impl LexError {
pub fn span(&self) -> Span {
self.span
}
}
impl Debug for LexError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
pub mod token_stream {
use super::*;
#[derive(Clone)]
pub struct IntoIter {
pub(crate) iter: <Vec<TokenTree> as IntoIterator>::IntoIter,
}
impl Iterator for IntoIter {
type Item = TokenTree;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
}
pub mod extra {
use crate::Span;
#[derive(Copy, Clone)]
pub struct DelimSpan {
pub(crate) join: Span,
pub(crate) open: Span,
pub(crate) close: Span,
}
impl DelimSpan {
pub fn join(&self) -> Span {
self.join
}
pub fn open(&self) -> Span {
self.open
}
pub fn close(&self) -> Span {
self.close
}
}
}
@@ -1,69 +0,0 @@
use std::str;
pub struct OutputBuffer {
bytes: Vec<u8>,
}
impl OutputBuffer {
pub fn new() -> Self {
OutputBuffer { bytes: Vec::new() }
}
pub fn write_u8(&mut self, value: u8) {
self.bytes.push(value);
}
pub fn write_u16(&mut self, value: u16) {
self.bytes.extend_from_slice(&value.to_le_bytes());
}
pub fn write_u32(&mut self, value: u32) {
self.bytes.extend_from_slice(&value.to_le_bytes());
}
pub fn write_str(&mut self, value: &str) {
self.bytes.extend_from_slice(value.as_bytes());
}
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
}
pub struct InputBuffer<'a> {
bytes: &'a [u8],
}
impl<'a> InputBuffer<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
InputBuffer { bytes }
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
pub fn read_u8(&mut self) -> u8 {
let (first, rest) = self.bytes.split_first().unwrap();
self.bytes = rest;
*first
}
pub fn read_u16(&mut self) -> u16 {
let (value, rest) = self.bytes.split_at(2);
self.bytes = rest;
u16::from_le_bytes([value[0], value[1]])
}
pub fn read_u32(&mut self) -> u32 {
let (value, rest) = self.bytes.split_at(4);
self.bytes = rest;
u32::from_le_bytes([value[0], value[1], value[2], value[3]])
}
pub fn read_str(&mut self, len: usize) -> &'a str {
let (string, rest) = self.bytes.split_at(len);
self.bytes = rest;
str::from_utf8(string).unwrap()
}
}
@@ -1,17 +0,0 @@
pub enum Bytecode {}
impl Bytecode {
pub const GROUP_PARENTHESIS: u8 = 0;
pub const GROUP_BRACE: u8 = 1;
pub const GROUP_BRACKET: u8 = 2;
pub const GROUP_NONE: u8 = 3;
pub const IDENT: u8 = 4;
pub const PUNCT_ALONE: u8 = 5;
pub const PUNCT_JOINT: u8 = 6;
pub const LITERAL: u8 = 7;
pub const LOAD_GROUP: u8 = 8;
pub const LOAD_IDENT: u8 = 9;
pub const LOAD_PUNCT: u8 = 10;
pub const LOAD_LITERAL: u8 = 11;
pub const SET_SPAN: u8 = 12;
}
-205
View File
@@ -1,205 +0,0 @@
pub mod buffer;
pub mod bytecode;
use crate::watt::buffer::{InputBuffer, OutputBuffer};
use crate::watt::bytecode::Bytecode;
use crate::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::str::FromStr;
pub enum Kind {
Group(Delimiter),
Ident,
Punct(Spacing),
Literal,
}
pub enum Identity {}
impl Identity {
pub const RESPANNED: u32 = 1 << 31;
pub const NOVEL: u32 = u32::MAX;
}
impl Span {
fn is_call_site(&self) -> bool {
self.lo == 0 && self.hi == 0
}
}
fn post_increment(counter: &mut u32) -> impl FnMut() -> u32 + '_ {
|| {
let value = *counter;
*counter += 1;
value
}
}
pub fn load(buf: &mut InputBuffer) -> TokenStream {
let mut span_counter = 1;
let mut next_span = post_increment(&mut span_counter);
let mut next_span = || {
let next = next_span();
Span { lo: next, hi: next }
};
let [mut group_counter, mut ident_counter, mut punct_counter, mut literal_counter] = [0; 4];
let mut next_group = post_increment(&mut group_counter);
let mut next_ident = post_increment(&mut ident_counter);
let mut next_punct = post_increment(&mut punct_counter);
let mut next_literal = post_increment(&mut literal_counter);
let mut trees = Vec::new();
while !buf.is_empty() {
match match buf.read_u8() {
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
Bytecode::IDENT => Kind::Ident,
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
Bytecode::LITERAL => Kind::Literal,
_ => unreachable!(),
} {
Kind::Group(delimiter) => {
let len = buf.read_u32();
let stream = trees.drain(trees.len() - len as usize..).collect();
trees.push(TokenTree::Group(Group {
delimiter,
stream,
span: next_span(),
span_open: next_span(),
span_close: next_span(),
identity: next_group(),
}));
}
Kind::Ident => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let ident = if let Some(repr) = repr.strip_prefix("r#") {
proc_macro2::Ident::new_raw(repr, proc_macro2::Span::call_site())
} else if repr == "$crate" {
proc_macro2::Ident::new("crate", proc_macro2::Span::call_site())
} else {
proc_macro2::Ident::new(repr, proc_macro2::Span::call_site())
};
trees.push(TokenTree::Ident(Ident {
fallback: ident,
span: next_span(),
identity: next_ident(),
}));
}
Kind::Punct(spacing) => {
let ch = buf.read_u8();
assert!(ch.is_ascii());
let punct = proc_macro2::Punct::new(ch as char, spacing);
trees.push(TokenTree::Punct(Punct {
fallback: punct,
span: next_span(),
identity: next_punct(),
}));
}
Kind::Literal => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let literal = proc_macro2::Literal::from_str(repr).unwrap();
trees.push(TokenTree::Literal(Literal {
fallback: literal,
span: next_span(),
identity: next_literal(),
}));
}
}
}
TokenStream { content: trees }
}
pub fn linearize(tokens: TokenStream) -> Vec<u8> {
let mut buf = OutputBuffer::new();
for token in &tokens.content {
linearize_token(token, &mut buf);
}
buf.into_bytes()
}
fn linearize_token(token: &TokenTree, buf: &mut OutputBuffer) {
let needs_span;
match token {
TokenTree::Group(group) => {
if group.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_GROUP);
buf.write_u32(group.identity & !Identity::RESPANNED);
needs_span = group.identity >= Identity::RESPANNED;
} else {
let len = group.stream.len();
assert!(len <= u32::MAX as usize);
for token in &group.stream {
linearize_token(token, buf);
}
buf.write_u8(match group.delimiter {
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
Delimiter::Brace => Bytecode::GROUP_BRACE,
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
Delimiter::None => Bytecode::GROUP_NONE,
});
buf.write_u32(len as u32);
needs_span = !group.span.is_call_site();
}
}
TokenTree::Ident(ident) => {
if ident.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_IDENT);
buf.write_u32(ident.identity & !Identity::RESPANNED);
needs_span = ident.identity >= Identity::RESPANNED;
} else {
buf.write_u8(Bytecode::IDENT);
let repr = ident.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
linearize_span(ident.span, buf);
needs_span = false;
}
}
TokenTree::Punct(punct) => {
if punct.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_PUNCT);
buf.write_u32(punct.identity & !Identity::RESPANNED);
needs_span = punct.identity >= Identity::RESPANNED;
} else {
buf.write_u8(match punct.spacing() {
Spacing::Alone => Bytecode::PUNCT_ALONE,
Spacing::Joint => Bytecode::PUNCT_JOINT,
});
let ch = punct.as_char();
assert!(ch.is_ascii());
buf.write_u8(ch as u8);
needs_span = !punct.span.is_call_site();
}
}
TokenTree::Literal(literal) => {
if literal.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_LITERAL);
buf.write_u32(literal.identity & !Identity::RESPANNED);
needs_span = literal.identity >= Identity::RESPANNED;
} else {
buf.write_u8(Bytecode::LITERAL);
let repr = literal.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
needs_span = !literal.span.is_call_site();
}
}
}
if needs_span {
buf.write_u8(Bytecode::SET_SPAN);
linearize_span(token.span(), buf);
}
}
fn linearize_span(span: Span, buf: &mut OutputBuffer) {
buf.write_u32(span.lo);
buf.write_u32(span.hi);
}
-36
View File
@@ -1,36 +0,0 @@
[package]
name = "serde_derive"
version = "1.0.177"
authors = ["David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"]
description = "Implementation of #[derive(Serialize, Deserialize)]"
documentation = "https://serde.rs/derive.html"
edition = "2015"
homepage = "https://serde.rs"
include = ["serde_derive-x86_64-unknown-linux-gnu", "src", "LICENSE-APACHE", "LICENSE-MIT"]
keywords = ["serde", "serialization", "no_std", "derive"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
repository = "https://github.com/serde-rs/serde"
rust-version = "1.56"
[features]
default = []
deserialize_in_place = []
[lib]
proc-macro = true
[target.'cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))'.dependencies]
proc-macro2 = "1"
quote = "1"
syn = "2.0.25"
[dev-dependencies]
serde = { version = "1", path = "../../serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
[workspace]
-1
View File
@@ -1 +0,0 @@
../../LICENSE-APACHE
-1
View File
@@ -1 +0,0 @@
../../LICENSE-MIT
-1
View File
@@ -1 +0,0 @@
../../README.md
-1
View File
@@ -1 +0,0 @@
../../crates-io.md
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/bound.rs
-1
View File
@@ -1 +0,0 @@
../../proc-macro2/src/watt/buffer.rs
-1
View File
@@ -1 +0,0 @@
../../proc-macro2/src/watt/bytecode.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/de.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/dummy.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/fragment.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/internals/
-22
View File
@@ -1,22 +0,0 @@
//! This crate provides Serde's two derive macros.
//!
//! ```edition2021
//! # use serde_derive::{Deserialize, Serialize};
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.177")]
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
include!("lib_from_source.rs");
#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))]
include!("lib_precompiled.rs");
@@ -1,36 +0,0 @@
extern crate proc_macro;
extern crate proc_macro2;
extern crate quote;
extern crate syn;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod de;
mod dummy;
mod internals;
mod pretend;
mod ser;
mod this;
mod try;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&mut input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&mut input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
@@ -1,234 +0,0 @@
extern crate proc_macro;
mod buffer;
mod bytecode;
use crate::buffer::{InputBuffer, OutputBuffer};
use crate::bytecode::Bytecode;
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::io::{ErrorKind, Read, Write};
use std::iter::FromIterator;
use std::path::Path;
use std::process::{Command, ExitStatus, Stdio};
use std::str::FromStr;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
derive(0, input)
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
derive(1 + cfg!(feature = "deserialize_in_place") as u8, input)
}
fn derive(select: u8, input: TokenStream) -> TokenStream {
let mut memory = TokenMemory::default();
let mut buf = OutputBuffer::new();
buf.write_u8(select);
memory.spans.push(Span::call_site());
for token in input {
memory.linearize_token(token, &mut buf);
}
let exe_path = Path::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/serde_derive-x86_64-unknown-linux-gnu",
));
let mut child = match Command::new(exe_path)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
{
Ok(child) => child,
Err(io_error) => {
if io_error.kind() == ErrorKind::NotFound {
panic!(
"file missing from serde_derive manifest directory during macro expansion: {}",
exe_path.display(),
);
} else {
panic!("failed to spawn process: {}", io_error);
}
}
};
let mut stdin = child.stdin.take().unwrap();
let mut buf = buf.into_bytes();
stdin.write_all(&buf).unwrap();
drop(stdin);
let mut stdout = child.stdout.take().unwrap();
buf.clear();
stdout.read_to_end(&mut buf).unwrap();
let success = child.wait().as_ref().map_or(true, ExitStatus::success);
if !success || buf.is_empty() {
panic!();
}
let mut buf = InputBuffer::new(&buf);
memory.receive(&mut buf)
}
#[derive(Default)]
struct TokenMemory {
spans: Vec<Span>,
groups: Vec<Group>,
idents: Vec<Ident>,
puncts: Vec<Punct>,
literals: Vec<Literal>,
}
enum Kind {
Group(Delimiter),
Ident,
Punct(Spacing),
Literal,
}
impl TokenMemory {
// Depth-first post-order traversal.
fn linearize_token(&mut self, token: TokenTree, buf: &mut OutputBuffer) {
match token {
TokenTree::Group(group) => {
let mut len = 0usize;
for token in group.stream() {
self.linearize_token(token, buf);
len += 1;
}
assert!(len <= u32::MAX as usize);
buf.write_u8(match group.delimiter() {
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
Delimiter::Brace => Bytecode::GROUP_BRACE,
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
Delimiter::None => Bytecode::GROUP_NONE,
});
buf.write_u32(len as u32);
self.spans
.extend([group.span(), group.span_open(), group.span_close()]);
self.groups.push(group);
}
TokenTree::Ident(ident) => {
buf.write_u8(Bytecode::IDENT);
let repr = ident.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
self.spans.push(ident.span());
self.idents.push(ident);
}
TokenTree::Punct(punct) => {
buf.write_u8(match punct.spacing() {
Spacing::Alone => Bytecode::PUNCT_ALONE,
Spacing::Joint => Bytecode::PUNCT_JOINT,
});
let ch = punct.as_char();
assert!(ch.is_ascii());
buf.write_u8(ch as u8);
self.spans.push(punct.span());
self.puncts.push(punct);
}
TokenTree::Literal(literal) => {
buf.write_u8(Bytecode::LITERAL);
let repr = literal.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
self.spans.push(literal.span());
self.literals.push(literal);
}
}
}
fn receive(&self, buf: &mut InputBuffer) -> TokenStream {
let mut trees = Vec::new();
while !buf.is_empty() {
match match buf.read_u8() {
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
Bytecode::IDENT => Kind::Ident,
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
Bytecode::LITERAL => Kind::Literal,
Bytecode::LOAD_GROUP => {
let identity = buf.read_u32();
let group = self.groups[identity as usize].clone();
trees.push(TokenTree::Group(group));
continue;
}
Bytecode::LOAD_IDENT => {
let identity = buf.read_u32();
let ident = self.idents[identity as usize].clone();
trees.push(TokenTree::Ident(ident));
continue;
}
Bytecode::LOAD_PUNCT => {
let identity = buf.read_u32();
let punct = self.puncts[identity as usize].clone();
trees.push(TokenTree::Punct(punct));
continue;
}
Bytecode::LOAD_LITERAL => {
let identity = buf.read_u32();
let literal = self.literals[identity as usize].clone();
trees.push(TokenTree::Literal(literal));
continue;
}
Bytecode::SET_SPAN => {
trees.last_mut().unwrap().set_span(self.read_span(buf));
continue;
}
_ => unreachable!(),
} {
Kind::Group(delimiter) => {
let len = buf.read_u32();
let stream = trees.drain(trees.len() - len as usize..).collect();
let group = Group::new(delimiter, stream);
trees.push(TokenTree::Group(group));
}
Kind::Ident => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let span = self.read_span(buf);
let ident = if let Some(repr) = repr.strip_prefix("r#") {
Ident::new_raw(repr, span)
} else {
Ident::new(repr, span)
};
trees.push(TokenTree::Ident(ident));
}
Kind::Punct(spacing) => {
let ch = buf.read_u8();
assert!(ch.is_ascii());
let punct = Punct::new(ch as char, spacing);
trees.push(TokenTree::Punct(punct));
}
Kind::Literal => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let literal = Literal::from_str(repr).unwrap();
trees.push(TokenTree::Literal(literal));
}
}
}
TokenStream::from_iter(trees)
}
fn read_span(&self, buf: &mut InputBuffer) -> Span {
let lo = buf.read_u32();
let hi = buf.read_u32();
let span = self.spans[lo as usize];
if lo == hi {
span
} else {
#[cfg(any())] // FIXME
return span.join(self.spans[hi as usize]).unwrap_or(span);
span
}
}
}
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/pretend.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/ser.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/this.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/try.rs
+13 -4
View File
@@ -1,20 +1,21 @@
[package]
name = "serde"
version = "1.0.177" # remember to update html_root_url and serde_derive dependency
version = "1.0.206"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
categories = ["encoding", "no-std", "no-std::no-alloc"]
description = "A generic serialization/deserialization framework"
documentation = "https://docs.rs/serde"
edition = "2018"
homepage = "https://serde.rs"
keywords = ["serde", "serialization", "no_std"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
repository = "https://github.com/serde-rs/serde"
rust-version = "1.19"
rust-version = "1.31"
[dependencies]
serde_derive = { version = "=1.0.177", optional = true, path = "../serde_derive" }
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1", path = "../serde_derive" }
@@ -26,10 +27,18 @@ doc-scrape-examples = false
features = ["derive", "rc"]
[package.metadata.docs.rs]
features = ["derive"]
features = ["derive", "rc", "unstable"]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
# This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's
# version in lockstep with serde's, even if someone depends on the two crates
# separately with serde's "derive" feature disabled. Every serde_derive release
# is compatible with exactly one serde release because the generated code
# involves nonpublic APIs which are not bound by semver.
[target.'cfg(any())'.dependencies]
serde_derive = { version = "=1.0.206", path = "../serde_derive" }
### FEATURES #################################################################
+33 -62
View File
@@ -13,71 +13,24 @@ fn main() {
None => return,
};
if minor >= 77 {
println!("cargo:rustc-check-cfg=cfg(no_core_cstr)");
println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)");
println!("cargo:rustc-check-cfg=cfg(no_core_try_from)");
println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)");
println!("cargo:rustc-check-cfg=cfg(no_float_copysign)");
println!("cargo:rustc-check-cfg=cfg(no_num_nonzero_signed)");
println!("cargo:rustc-check-cfg=cfg(no_relaxed_trait_bounds)");
println!("cargo:rustc-check-cfg=cfg(no_serde_derive)");
println!("cargo:rustc-check-cfg=cfg(no_std_atomic)");
println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)");
println!("cargo:rustc-check-cfg=cfg(no_systemtime_checked_add)");
println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)");
}
let target = env::var("TARGET").unwrap();
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
// std::collections::Bound was stabilized in Rust 1.17
// but it was moved to core::ops later in Rust 1.26:
// https://doc.rust-lang.org/core/ops/enum.Bound.html
if minor < 26 {
println!("cargo:rustc-cfg=no_ops_bound");
if minor < 17 {
println!("cargo:rustc-cfg=no_collections_bound");
}
}
// core::cmp::Reverse stabilized in Rust 1.19:
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
if minor < 19 {
println!("cargo:rustc-cfg=no_core_reverse");
}
// CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20:
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
// https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path
if minor < 20 {
println!("cargo:rustc-cfg=no_de_boxed_c_str");
println!("cargo:rustc-cfg=no_de_boxed_path");
}
// 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=no_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=no_core_duration");
}
// 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
//
// Disabled on Emscripten targets before Rust 1.40 since
// Emscripten did not support 128-bit integers until Rust 1.40
// (https://github.com/rust-lang/rust/pull/65251)
if minor < 26 || emscripten && minor < 40 {
println!("cargo:rustc-cfg=no_integer128");
}
// Inclusive ranges methods stabilized in Rust 1.27:
// https://github.com/rust-lang/rust/pull/50758
// Also Iterator::try_for_each:
// https://blog.rust-lang.org/2018/06/21/Rust-1.27.html#library-stabilizations
if minor < 27 {
println!("cargo:rustc-cfg=no_range_inclusive");
println!("cargo:rustc-cfg=no_iterator_try_fold");
}
// Non-zero integers stabilized in Rust 1.28:
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
if minor < 28 {
println!("cargo:rustc-cfg=no_num_nonzero");
}
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
// stabilized in Rust 1.34:
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
@@ -89,6 +42,12 @@ fn main() {
println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
}
// f32::copysign and f64::copysign stabilized in Rust 1.35.
// https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html#copy-the-sign-of-a-floating-point-number-onto-another
if minor < 35 {
println!("cargo:rustc-cfg=no_float_copysign");
}
// Current minimum supported version of serde_derive crate is Rust 1.56.
if minor < 56 {
println!("cargo:rustc-cfg=no_serde_derive");
@@ -120,6 +79,18 @@ fn main() {
if minor < 64 {
println!("cargo:rustc-cfg=no_core_cstr");
}
// Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74
// https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis
if minor < 74 {
println!("cargo:rustc-cfg=no_core_num_saturating");
}
// Support for the `#[diagnostic]` tool attribute namespace
// https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes
if minor < 78 {
println!("cargo:rustc-cfg=no_diagnostic_namespace");
}
}
fn rustc_minor_version() -> Option<u32> {
+2 -2
View File
@@ -1,5 +1,5 @@
use lib::fmt::{self, Write};
use lib::str;
use crate::lib::fmt::{self, Write};
use crate::lib::str;
pub(super) struct Buf<'a> {
bytes: &'a mut [u8],
+13 -17
View File
@@ -1,6 +1,6 @@
use lib::*;
use crate::lib::*;
use de::{
use crate::de::{
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};
@@ -129,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
Ok(IgnoredAny)
}
serde_if_integer128! {
#[inline]
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
@@ -143,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
Ok(IgnoredAny)
}
serde_if_integer128! {
#[inline]
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
@@ -197,7 +193,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: SeqAccess<'de>,
{
while let Some(IgnoredAny) = try!(seq.next_element()) {
while let Some(IgnoredAny) = tri!(seq.next_element()) {
// Gobble
}
Ok(IgnoredAny)
@@ -208,7 +204,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: MapAccess<'de>,
{
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) {
// Gobble
}
Ok(IgnoredAny)
@@ -227,7 +223,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: EnumAccess<'de>,
{
try!(data.variant::<IgnoredAny>()).1.newtype_variant()
tri!(data.variant::<IgnoredAny>()).1.newtype_variant()
}
}
+612 -425
View File
File diff suppressed because it is too large Load Diff
+128 -87
View File
@@ -64,8 +64,8 @@
//! - RefCell\<T\>
//! - Mutex\<T\>
//! - RwLock\<T\>
//! - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Rc\<T\>&emsp;*(if* features = \["rc"\] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = \["rc"\] *is enabled)*
//! - **Collection types**:
//! - BTreeMap\<K, V\>
//! - BTreeSet\<T\>
@@ -112,26 +112,28 @@
//! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats
use lib::*;
use crate::lib::*;
////////////////////////////////////////////////////////////////////////////////
pub mod value;
#[cfg(not(no_integer128))]
mod format;
mod ignored_any;
mod impls;
mod utf8;
pub(crate) mod size_hint;
pub use self::ignored_any::IgnoredAny;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use crate::std_error::Error as StdError;
#[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(no_inline)]
pub use core::error::Error as StdError;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
////////////////////////////////////////////////////////////////////////////////
@@ -400,20 +402,20 @@ impl<'a> fmt::Display for Unexpected<'a> {
Bool(b) => write!(formatter, "boolean `{}`", b),
Unsigned(i) => write!(formatter, "integer `{}`", i),
Signed(i) => write!(formatter, "integer `{}`", i),
Float(f) => write!(formatter, "floating point `{}`", f),
Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)),
Char(c) => write!(formatter, "character `{}`", c),
Str(s) => write!(formatter, "string {:?}", s),
Bytes(_) => write!(formatter, "byte array"),
Unit => write!(formatter, "unit value"),
Option => write!(formatter, "Option value"),
NewtypeStruct => write!(formatter, "newtype struct"),
Seq => write!(formatter, "sequence"),
Map => write!(formatter, "map"),
Enum => write!(formatter, "enum"),
UnitVariant => write!(formatter, "unit variant"),
NewtypeVariant => write!(formatter, "newtype variant"),
TupleVariant => write!(formatter, "tuple variant"),
StructVariant => write!(formatter, "struct variant"),
Bytes(_) => formatter.write_str("byte array"),
Unit => formatter.write_str("unit value"),
Option => formatter.write_str("Option value"),
NewtypeStruct => formatter.write_str("newtype struct"),
Seq => formatter.write_str("sequence"),
Map => formatter.write_str("map"),
Enum => formatter.write_str("enum"),
UnitVariant => formatter.write_str("unit variant"),
NewtypeVariant => formatter.write_str("newtype variant"),
TupleVariant => formatter.write_str("tuple variant"),
StructVariant => formatter.write_str("struct variant"),
Other(other) => formatter.write_str(other),
}
}
@@ -530,6 +532,13 @@ impl<'a> Display for Expected + 'a {
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
#[cfg_attr(
not(no_diagnostic_namespace),
diagnostic::on_unimplemented(
note = "for local types consider adding `#[derive(serde::Deserialize)]` to your `{Self}` type",
note = "for types from other crates check whether the crate offers a `serde` feature flag",
)
)]
pub trait Deserialize<'de>: Sized {
/// Deserialize this value from the given Serde deserializer.
///
@@ -566,7 +575,7 @@ pub trait Deserialize<'de>: Sized {
D: Deserializer<'de>,
{
// Default implementation just delegates to `deserialize` impl.
*place = try!(Deserialize::deserialize(deserializer));
*place = tri!(Deserialize::deserialize(deserializer));
Ok(())
}
}
@@ -946,18 +955,15 @@ 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 an `i128` value.
///
/// 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.
@@ -980,18 +986,15 @@ 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 an `u128` value.
///
/// 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.
@@ -1226,11 +1229,11 @@ pub trait Deserializer<'de>: Sized {
#[doc(hidden)]
fn __deserialize_content<V>(
self,
_: ::actually_private::T,
_: crate::actually_private::T,
visitor: V,
) -> Result<::private::de::Content<'de>, Self::Error>
) -> Result<crate::__private::de::Content<'de>, Self::Error>
where
V: Visitor<'de, Value = ::private::de::Content<'de>>,
V: Visitor<'de, Value = crate::__private::de::Content<'de>>,
{
self.deserialize_any(visitor)
}
@@ -1363,20 +1366,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 mut buf = [0u8; 58];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
}
/// The input contains a `i128`.
///
/// The default implementation fails with a type error.
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
let mut buf = [0u8; 58];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
Err(Error::invalid_type(
Unexpected::Other(writer.as_str()),
&self,
))
}
/// The input contains a `u8`.
@@ -1425,20 +1428,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 mut buf = [0u8; 57];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
}
/// The input contains a `u128`.
///
/// The default implementation fails with a type error.
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
let mut buf = [0u8; 57];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
Err(Error::invalid_type(
Unexpected::Other(writer.as_str()),
&self,
))
}
/// The input contains an `f32`.
@@ -1474,7 +1477,7 @@ pub trait Visitor<'de>: Sized {
where
E: Error,
{
self.visit_str(utf8::encode(v).as_str())
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
}
/// The input contains a string. The lifetime of the string is ephemeral and
@@ -1529,6 +1532,7 @@ pub trait Visitor<'de>: Sized {
/// `String`.
#[inline]
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
@@ -1551,7 +1555,6 @@ pub trait Visitor<'de>: Sized {
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
}
@@ -1588,6 +1591,7 @@ pub trait Visitor<'de>: Sized {
/// The default implementation forwards to `visit_bytes` and then drops the
/// `Vec<u8>`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
@@ -1738,9 +1742,9 @@ pub trait SeqAccess<'de> {
}
}
impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A
impl<'de, 'a, A> SeqAccess<'de> for &'a mut A
where
A: SeqAccess<'de>,
A: ?Sized + SeqAccess<'de>,
{
type Error = A::Error;
@@ -1831,9 +1835,9 @@ pub trait MapAccess<'de> {
K: DeserializeSeed<'de>,
V: DeserializeSeed<'de>,
{
match try!(self.next_key_seed(kseed)) {
match tri!(self.next_key_seed(kseed)) {
Some(key) => {
let value = try!(self.next_value_seed(vseed));
let value = tri!(self.next_value_seed(vseed));
Ok(Some((key, value)))
}
None => Ok(None),
@@ -1891,9 +1895,9 @@ pub trait MapAccess<'de> {
}
}
impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A
impl<'de, 'a, A> MapAccess<'de> for &'a mut A
where
A: MapAccess<'de>,
A: ?Sized + MapAccess<'de>,
{
type Error = A::Error;
@@ -2281,15 +2285,52 @@ impl Display for OneOf {
1 => write!(formatter, "`{}`", self.names[0]),
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
_ => {
try!(write!(formatter, "one of "));
tri!(formatter.write_str("one of "));
for (i, alt) in self.names.iter().enumerate() {
if i > 0 {
try!(write!(formatter, ", "));
tri!(formatter.write_str(", "));
}
try!(write!(formatter, "`{}`", alt));
tri!(write!(formatter, "`{}`", alt));
}
Ok(())
}
}
}
}
struct WithDecimalPoint(f64);
impl Display for WithDecimalPoint {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
struct LookForDecimalPoint<'f, 'a> {
formatter: &'f mut fmt::Formatter<'a>,
has_decimal_point: bool,
}
impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> {
fn write_str(&mut self, fragment: &str) -> fmt::Result {
self.has_decimal_point |= fragment.contains('.');
self.formatter.write_str(fragment)
}
fn write_char(&mut self, ch: char) -> fmt::Result {
self.has_decimal_point |= ch == '.';
self.formatter.write_char(ch)
}
}
if self.0.is_finite() {
let mut writer = LookForDecimalPoint {
formatter,
has_decimal_point: false,
};
tri!(write!(writer, "{}", self.0));
if !writer.has_decimal_point {
tri!(formatter.write_str(".0"));
}
} else {
tri!(write!(formatter, "{}", self.0));
}
Ok(())
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
use de::{Deserialize, DeserializeSeed, Deserializer};
use crate::de::{Deserialize, DeserializeSeed, Deserializer};
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
///
@@ -1,4 +1,4 @@
use lib::*;
use crate::lib::*;
pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
-46
View File
@@ -1,46 +0,0 @@
use lib::*;
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode(c: char) -> Encode {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
Encode { buf, pos }
}
pub struct Encode {
buf: [u8; 4],
pos: usize,
}
impl Encode {
pub fn as_str(&self) -> &str {
str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
+33 -23
View File
@@ -21,12 +21,11 @@
//! }
//! ```
use lib::*;
use crate::lib::*;
use self::private::{First, Second};
use __private::size_hint;
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use ser;
use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use crate::ser;
////////////////////////////////////////////////////////////////////////////////
@@ -113,6 +112,7 @@ impl Debug for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for Error {
fn description(&self) -> &str {
&self.err
@@ -185,12 +185,14 @@ impl<E> Debug for UnitDeserializer<E> {
/// A deserializer that cannot be instantiated.
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
pub struct NeverDeserializer<E> {
never: !,
marker: PhantomData<E>,
}
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
impl<'de, E> IntoDeserializer<'de, E> for !
where
E: de::Error,
@@ -293,20 +295,17 @@ primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8);
primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16);
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64);
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64);
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64);
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64);
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`.
pub struct U32Deserializer<E> {
value: u32,
@@ -566,6 +565,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> {
/// A deserializer holding a `String`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
pub struct StringDeserializer<E> {
value: String,
marker: PhantomData<E>,
@@ -582,6 +582,7 @@ impl<E> Clone for StringDeserializer<E> {
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<'de, E> IntoDeserializer<'de, E> for String
where
E: de::Error,
@@ -669,6 +670,7 @@ impl<E> Debug for StringDeserializer<E> {
/// A deserializer holding a `Cow<str>`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>,
marker: PhantomData<E>,
@@ -685,6 +687,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> {
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
where
E: de::Error,
@@ -937,8 +940,8 @@ where
where
V: de::Visitor<'de>,
{
let v = try!(visitor.visit_seq(&mut self));
try!(self.end());
let v = tri!(visitor.visit_seq(&mut self));
tri!(self.end());
Ok(v)
}
@@ -980,7 +983,7 @@ struct ExpectedInSeq(usize);
impl Expected for ExpectedInSeq {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if self.0 == 1 {
write!(formatter, "1 element in sequence")
formatter.write_str("1 element in sequence")
} else {
write!(formatter, "{} elements in sequence", self.0)
}
@@ -1003,6 +1006,7 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
where
T: IntoDeserializer<'de, E>,
@@ -1016,6 +1020,7 @@ where
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
where
T: IntoDeserializer<'de, E> + Eq + Ord,
@@ -1029,6 +1034,7 @@ where
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
where
T: IntoDeserializer<'de, E> + Eq + Hash,
@@ -1162,8 +1168,8 @@ where
where
V: de::Visitor<'de>,
{
let value = try!(visitor.visit_map(&mut self));
try!(self.end());
let value = tri!(visitor.visit_map(&mut self));
tri!(self.end());
Ok(value)
}
@@ -1171,8 +1177,8 @@ where
where
V: de::Visitor<'de>,
{
let value = try!(visitor.visit_seq(&mut self));
try!(self.end());
let value = tri!(visitor.visit_seq(&mut self));
tri!(self.end());
Ok(value)
}
@@ -1236,8 +1242,8 @@ where
{
match self.next_pair() {
Some((key, value)) => {
let key = try!(kseed.deserialize(key.into_deserializer()));
let value = try!(vseed.deserialize(value.into_deserializer()));
let key = tri!(kseed.deserialize(key.into_deserializer()));
let value = tri!(vseed.deserialize(value.into_deserializer()));
Ok(Some((key, value)))
}
None => Ok(None),
@@ -1341,7 +1347,7 @@ where
V: de::Visitor<'de>,
{
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
let pair = try!(visitor.visit_seq(&mut pair_visitor));
let pair = tri!(visitor.visit_seq(&mut pair_visitor));
if pair_visitor.1.is_none() {
Ok(pair)
} else {
@@ -1405,7 +1411,7 @@ struct ExpectedInMap(usize);
impl Expected for ExpectedInMap {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if self.0 == 1 {
write!(formatter, "1 element in map")
formatter.write_str("1 element in map")
} else {
write!(formatter, "{} elements in map", self.0)
}
@@ -1415,6 +1421,7 @@ impl Expected for ExpectedInMap {
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
where
K: IntoDeserializer<'de, E> + Eq + Ord,
@@ -1429,6 +1436,7 @@ where
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
where
K: IntoDeserializer<'de, E> + Eq + Hash,
@@ -1501,7 +1509,7 @@ where
where
T: de::DeserializeSeed<'de>,
{
match try!(self.map.next_key_seed(seed)) {
match tri!(self.map.next_key_seed(seed)) {
Some(key) => Ok((key, private::map_as_enum(self.map))),
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
}
@@ -1546,9 +1554,11 @@ where
////////////////////////////////////////////////////////////////////////////////
mod private {
use lib::*;
use crate::lib::*;
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
use crate::de::{
self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor,
};
pub struct UnitOnly<E> {
marker: PhantomData<E>,
+3 -76
View File
@@ -1,82 +1,9 @@
/// 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
/// (or targets that lack 128-bit integers) 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,
/// or do not target platforms that lack 128-bit integers, do not need to
/// bother with this macro and may assume support for 128-bit integers.
///
/// ```edition2021
/// # use serde::__private::doc::Error;
/// #
/// # struct MySerializer;
/// #
/// use serde::{serde_if_integer128, Serializer};
///
/// 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!()
/// }
/// }
/// #
/// # serde::__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
/// # }
/// }
/// ```
///
/// When Serde is built with support for 128-bit integers, this macro expands
/// transparently into just the input tokens.
///
/// ```edition2021
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {
/// $($tt)*
/// };
/// }
/// ```
///
/// When built without support for 128-bit integers, this macro expands to
/// nothing.
///
/// ```edition2021
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {};
/// }
/// ```
#[cfg(not(no_integer128))]
// No longer used. Old versions of serde used this macro for supporting targets
// that did not yet have 128-bit integer support.
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {
$($tt)*
};
}
#[cfg(no_integer128)]
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {};
}
+71 -78
View File
@@ -63,6 +63,7 @@
//! and from DynamoDB.
//! - [Hjson], a syntax extension to JSON designed around human reading and
//! editing. *(deserialization only)*
//! - [CSV], Comma-separated values is a tabular text file format.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Postcard]: https://github.com/jamesmunns/postcard
@@ -89,66 +90,69 @@
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
//! [Hjson]: https://github.com/Canop/deser-hjson
//! [CSV]: https://docs.rs/csv
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.177")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.206")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Show which crate feature enables conditionally compiled APIs in documentation.
#![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))]
#![cfg_attr(docsrs, allow(internal_features))]
// 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(error_in_core, never_type))]
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
unnested_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
semicolon_if_nothing_returned,
// not available in our oldest supported compiler
empty_enum,
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_sign_loss,
// things are often more readable this way
cast_lossless,
module_name_repetitions,
option_if_let_else,
single_match_else,
type_complexity,
use_self,
zero_prefixed_literal,
// correctly used
derive_partial_eq_without_eq,
enum_glob_use,
explicit_auto_deref,
let_underscore_untyped,
map_err_ignore,
new_without_default,
result_unit_err,
wildcard_imports,
// not practical
needless_pass_by_value,
similar_names,
too_many_lines,
// preference
doc_markdown,
unseparated_literal_suffix,
// false positive
needless_doctest_main,
// noisy
missing_errors_doc,
must_use_candidate,
)
#![allow(
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
clippy::unnested_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
clippy::semicolon_if_nothing_returned,
// not available in our oldest supported compiler
clippy::empty_enum,
clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
// integer and float ser/de requires these sorts of casts
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
// things are often more readable this way
clippy::cast_lossless,
clippy::module_name_repetitions,
clippy::single_match_else,
clippy::type_complexity,
clippy::use_self,
clippy::zero_prefixed_literal,
// correctly used
clippy::derive_partial_eq_without_eq,
clippy::enum_glob_use,
clippy::explicit_auto_deref,
clippy::incompatible_msrv,
clippy::let_underscore_untyped,
clippy::map_err_ignore,
clippy::new_without_default,
clippy::result_unit_err,
clippy::wildcard_imports,
// not practical
clippy::needless_pass_by_value,
clippy::similar_names,
clippy::too_many_lines,
// preference
clippy::doc_markdown,
clippy::unseparated_literal_suffix,
// false positive
clippy::needless_doctest_main,
// noisy
clippy::missing_errors_doc,
clippy::must_use_candidate,
)]
// Restrictions
#![deny(clippy::question_mark_used)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]
@@ -168,21 +172,26 @@ mod lib {
pub use std::*;
}
pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
pub use self::core::{f32, f64};
pub use self::core::{i16, i32, i64, i8, isize};
pub use self::core::{iter, num, ptr, str};
pub use self::core::{u16, u32, u64, u8, usize};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::core::{cmp, mem, slice};
pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone};
pub use self::core::convert::{self, From, Into};
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::clone;
pub use self::core::cmp::Reverse;
pub use self::core::convert;
pub use self::core::default;
pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite};
pub use self::core::marker::{self, PhantomData};
pub use self::core::num::Wrapping;
pub use self::core::ops::{Range, RangeFrom, RangeTo};
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo};
pub use self::core::option;
pub use self::core::result;
pub use self::core::time::Duration;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::borrow::{Cow, ToOwned};
@@ -220,7 +229,7 @@ mod lib {
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(all(not(no_core_cstr), not(feature = "std")))]
pub use core::ffi::CStr;
pub use self::core::ffi::CStr;
#[cfg(feature = "std")]
pub use std::ffi::CStr;
@@ -247,18 +256,6 @@ mod lib {
#[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
pub use std::collections::Bound;
#[cfg(not(no_core_reverse))]
pub use self::core::cmp::Reverse;
#[cfg(not(no_ops_bound))]
pub use self::core::ops::Bound;
#[cfg(not(no_range_inclusive))]
pub use self::core::ops::RangeInclusive;
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
@@ -280,15 +277,15 @@ mod lib {
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
#[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration;
#[cfg(not(no_core_num_saturating))]
pub use self::core::num::Saturating;
}
// None of this crate's error handling needs the `From::from` error conversion
// performed implicitly by the `?` operator or the standard library's `try!`
// macro. This simplified macro gives a 5.5% improvement in compile time
// compared to standard `try!`, and 9% improvement compared to `?`.
macro_rules! try {
macro_rules! tri {
($expr:expr) => {
match $expr {
Ok(val) => val,
@@ -309,20 +306,15 @@ pub mod de;
pub mod ser;
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
pub use crate::de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};
pub use crate::ser::{Serialize, Serializer};
// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;
#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;
#[path = "de/seed.rs"]
mod seed;
@@ -339,6 +331,7 @@ extern crate serde_derive;
/// Derive macro available if serde is built with `features = ["derive"]`.
#[cfg(feature = "serde_derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub use serde_derive::{Deserialize, Serialize};
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
+3 -7
View File
@@ -123,7 +123,7 @@ macro_rules! forward_to_deserialize_any {
macro_rules! forward_to_deserialize_any_method {
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
#[inline]
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error>
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, <Self as $crate::de::Deserializer<$l>>::Error>
where
$v: $crate::de::Visitor<$l>,
{
@@ -154,9 +154,7 @@ macro_rules! forward_to_deserialize_any_helper {
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>()}
}
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
};
(u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
@@ -171,9 +169,7 @@ macro_rules! forward_to_deserialize_any_helper {
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>()}
}
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
};
(f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
+108 -185
View File
@@ -1,10 +1,13 @@
use lib::*;
use crate::lib::*;
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor};
use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use crate::de::{
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess,
Visitor,
};
#[cfg(any(feature = "std", feature = "alloc"))]
use de::{DeserializeSeed, MapAccess, Unexpected};
use crate::de::{MapAccess, Unexpected};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{
@@ -13,7 +16,7 @@ pub use self::content::{
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
};
pub use seed::InPlaceSeed;
pub use crate::seed::InPlaceSeed;
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
@@ -203,13 +206,13 @@ mod content {
// This issue is tracking making some of this stuff public:
// https://github.com/serde-rs/serde/issues/741
use lib::*;
use crate::lib::*;
use __private::size_hint;
use actually_private;
use de::{
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
MapAccess, SeqAccess, Unexpected, Visitor,
use crate::actually_private;
use crate::de::value::{MapDeserializer, SeqDeserializer};
use crate::de::{
self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected,
IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor,
};
/// Used from generated code to buffer the contents of the Deserializer when
@@ -299,6 +302,19 @@ mod content {
}
}
impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de>
where
E: de::Error,
{
type Deserializer = ContentDeserializer<'de, E>;
fn into_deserializer(self) -> Self::Deserializer {
ContentDeserializer::new(self)
}
}
/// Used to capture data in [`Content`] from other deserializers.
/// Cannot capture externally tagged enums, `i128` and `u128`.
struct ContentVisitor<'de> {
value: PhantomData<Content<'de>>,
}
@@ -476,7 +492,7 @@ mod content {
{
let mut vec =
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
while let Some(e) = try!(visitor.next_element()) {
while let Some(e) = tri!(visitor.next_element()) {
vec.push(e);
}
Ok(Content::Seq(vec))
@@ -490,7 +506,7 @@ mod content {
Vec::<(Content, Content)>::with_capacity(
size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
);
while let Some(kv) = try!(visitor.next_entry()) {
while let Some(kv) = tri!(visitor.next_entry()) {
vec.push(kv);
}
Ok(Content::Map(vec))
@@ -514,6 +530,8 @@ mod content {
Content(Content<'de>),
}
/// Serves as a seed for deserializing a key of internally tagged enum.
/// Cannot capture externally tagged enums, `i128` and `u128`.
struct TagOrContentVisitor<'de> {
name: &'static str,
value: PhantomData<TagOrContent<'de>>,
@@ -800,6 +818,9 @@ mod content {
/// Used by generated code to deserialize an internally tagged enum.
///
/// Captures map or sequence from the original deserializer and searches
/// a tag in it (in case of sequence, tag is the first element of sequence).
///
/// Not public API.
pub struct TaggedContentVisitor<T> {
tag_name: &'static str,
@@ -833,14 +854,14 @@ mod content {
where
S: SeqAccess<'de>,
{
let tag = match try!(seq.next_element()) {
let tag = match tri!(seq.next_element()) {
Some(tag) => tag,
None => {
return Err(de::Error::missing_field(self.tag_name));
}
};
let rest = de::value::SeqAccessDeserializer::new(seq);
Ok((tag, try!(Content::deserialize(rest))))
Ok((tag, tri!(Content::deserialize(rest))))
}
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
@@ -852,16 +873,16 @@ mod content {
Content,
Content,
)>(map.size_hint()));
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k {
TagOrContent::Tag => {
if tag.is_some() {
return Err(de::Error::duplicate_field(self.tag_name));
}
tag = Some(try!(map.next_value()));
tag = Some(tri!(map.next_value()));
}
TagOrContent::Content(k) => {
let v = try!(map.next_value());
let v = tri!(map.next_value());
vec.push((k, v));
}
}
@@ -1074,9 +1095,9 @@ mod content {
E: de::Error,
{
let seq = content.into_iter().map(ContentDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end());
let mut seq_visitor = SeqDeserializer::new(seq);
let value = tri!(visitor.visit_seq(&mut seq_visitor));
tri!(seq_visitor.end());
Ok(value)
}
@@ -1091,9 +1112,9 @@ mod content {
let map = content
.into_iter()
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
let mut map_visitor = MapDeserializer::new(map);
let value = tri!(visitor.visit_map(&mut map_visitor));
tri!(map_visitor.end());
Ok(value)
}
@@ -1569,7 +1590,7 @@ mod content {
{
match self.value {
Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
}
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
@@ -1592,10 +1613,10 @@ mod content {
{
match self.value {
Some(Content::Map(v)) => {
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor)
}
Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
}
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
@@ -1609,156 +1630,6 @@ mod content {
}
}
struct SeqDeserializer<'de, E>
where
E: de::Error,
{
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
err: PhantomData<E>,
}
impl<'de, E> SeqDeserializer<'de, E>
where
E: de::Error,
{
fn new(vec: Vec<Content<'de>>) -> Self {
SeqDeserializer {
iter: vec.into_iter(),
err: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
#[inline]
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
let len = self.iter.len();
if len == 0 {
visitor.visit_unit()
} else {
let ret = try!(visitor.visit_seq(&mut self));
let remaining = self.iter.len();
if remaining == 0 {
Ok(ret)
} else {
Err(de::Error::invalid_length(len, &"fewer elements in array"))
}
}
}
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
}
}
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
None => Ok(None),
}
}
fn size_hint(&self) -> Option<usize> {
size_hint::from_bounds(&self.iter)
}
}
struct MapDeserializer<'de, E>
where
E: de::Error,
{
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
value: Option<Content<'de>>,
err: PhantomData<E>,
}
impl<'de, E> MapDeserializer<'de, E>
where
E: de::Error,
{
fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
MapDeserializer {
iter: map.into_iter(),
value: None,
err: PhantomData,
}
}
}
impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some((key, value)) => {
self.value = Some(value);
seed.deserialize(ContentDeserializer::new(key)).map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.value.take() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
None => Err(de::Error::custom("value is missing")),
}
}
fn size_hint(&self) -> Option<usize> {
size_hint::from_bounds(&self.iter)
}
}
impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_map(self)
}
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
}
}
/// Not public API.
pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
content: &'a Content<'de>,
@@ -1820,9 +1691,9 @@ mod content {
E: de::Error,
{
let seq = content.iter().map(ContentRefDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end());
let mut seq_visitor = SeqDeserializer::new(seq);
let value = tri!(visitor.visit_seq(&mut seq_visitor));
tri!(seq_visitor.end());
Ok(value)
}
@@ -1840,9 +1711,9 @@ mod content {
ContentRefDeserializer::new(v),
)
});
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
let mut map_visitor = MapDeserializer::new(map);
let value = tri!(visitor.visit_map(&mut map_visitor));
tri!(map_visitor.end());
Ok(value)
}
@@ -2362,7 +2233,7 @@ mod content {
if len == 0 {
visitor.visit_unit()
} else {
let ret = try!(visitor.visit_seq(&mut self));
let ret = tri!(visitor.visit_seq(&mut self));
let remaining = self.iter.len();
if remaining == 0 {
Ok(ret)
@@ -2541,7 +2412,7 @@ mod content {
where
M: MapAccess<'de>,
{
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
while tri!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
Ok(())
}
}
@@ -2974,3 +2845,55 @@ fn flat_map_take_entry<'de>(
None
}
}
pub struct AdjacentlyTaggedEnumVariantSeed<F> {
pub enum_name: &'static str,
pub variants: &'static [&'static str],
pub fields_enum: PhantomData<F>,
}
pub struct AdjacentlyTaggedEnumVariantVisitor<F> {
enum_name: &'static str,
fields_enum: PhantomData<F>,
}
impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor<F>
where
F: Deserialize<'de>,
{
type Value = F;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "variant of enum {}", self.enum_name)
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (variant, variant_access) = tri!(data.variant());
tri!(variant_access.unit_variant());
Ok(variant)
}
}
impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed<F>
where
F: Deserialize<'de>,
{
type Value = F;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_enum(
self.enum_name,
self.variants,
AdjacentlyTaggedEnumVariantVisitor {
enum_name: self.enum_name,
fields_enum: PhantomData,
},
)
}
}
+6 -3
View File
@@ -1,8 +1,8 @@
// Used only by Serde doc tests. Not public API.
use lib::*;
use crate::lib::*;
use ser;
use crate::ser;
#[doc(hidden)]
#[derive(Debug)]
@@ -56,7 +56,10 @@ macro_rules! __serialize_unimplemented {
#[macro_export]
macro_rules! __serialize_unimplemented_method {
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error> {
fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error>
where
$($t: ?Sized + $crate::Serialize,)*
{
unimplemented!()
}
};
+11 -13
View File
@@ -3,30 +3,28 @@ pub mod de;
#[cfg(not(no_serde_derive))]
pub mod ser;
pub mod size_hint;
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
pub mod doc;
pub use lib::clone::Clone;
pub use lib::convert::{From, Into};
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::ptr;
pub use lib::result::Result::{self, Err, Ok};
pub use crate::lib::clone::Clone;
pub use crate::lib::convert::{From, Into};
pub use crate::lib::default::Default;
pub use crate::lib::fmt::{self, Formatter};
pub use crate::lib::marker::PhantomData;
pub use crate::lib::option::Option::{self, None, Some};
pub use crate::lib::ptr;
pub use crate::lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::{ToString, Vec};
pub use crate::lib::{ToString, Vec};
#[cfg(not(no_core_try_from))]
pub use lib::convert::TryFrom;
pub use crate::lib::convert::TryFrom;
mod string {
use lib::*;
use crate::lib::*;
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
+195 -141
View File
@@ -1,6 +1,6 @@
use lib::*;
use crate::lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{
@@ -174,22 +174,22 @@ where
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name));
let mut map = tri!(self.delegate.serialize_map(Some(1)));
tri!(map.serialize_entry(self.tag, self.variant_name));
map.end()
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name));
let mut map = tri!(self.delegate.serialize_map(Some(1)));
tri!(map.serialize_entry(self.tag, self.variant_name));
map.end()
}
@@ -199,24 +199,24 @@ where
_: u32,
inner_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, &()));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_entry(inner_variant, &()));
map.end()
}
fn serialize_newtype_struct<T: ?Sized>(
fn serialize_newtype_struct<T>(
self,
_: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
fn serialize_newtype_variant<T>(
self,
_: &'static str,
_: u32,
@@ -224,11 +224,11 @@ where
inner_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, inner_value));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_entry(inner_variant, inner_value));
map.end()
}
@@ -269,9 +269,9 @@ where
inner_variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
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));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(
map,
inner_variant,
@@ -280,8 +280,8 @@ where
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name));
let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1)));
tri!(map.serialize_entry(self.tag, self.variant_name));
Ok(map)
}
@@ -290,8 +290,8 @@ where
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
let mut state = tri!(self.delegate.serialize_struct(name, len + 1));
tri!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
@@ -316,9 +316,9 @@ where
inner_variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
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));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(
map,
inner_variant,
@@ -327,9 +327,9 @@ where
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
fn collect_str<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
T: Display,
T: ?Sized + Display,
{
Err(self.bad_type(Unsupported::String))
}
@@ -337,9 +337,9 @@ where
#[cfg(any(feature = "std", feature = "alloc"))]
mod content {
use lib::*;
use crate::lib::*;
use ser::{self, Serialize, Serializer};
use crate::ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> {
map: M,
@@ -364,17 +364,17 @@ mod content {
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), M::Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), M::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self
tri!(self
.map
.serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end()
@@ -404,21 +404,17 @@ mod content {
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), M::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), M::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self
tri!(self
.map
.serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end()
@@ -499,50 +495,50 @@ mod content {
}
Content::Seq(ref elements) => elements.serialize(serializer),
Content::Tuple(ref elements) => {
use ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
use crate::ser::SerializeTuple;
let mut tuple = tri!(serializer.serialize_tuple(elements.len()));
for e in elements {
try!(tuple.serialize_element(e));
tri!(tuple.serialize_element(e));
}
tuple.end()
}
Content::TupleStruct(n, ref fields) => {
use ser::SerializeTupleStruct;
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
use crate::ser::SerializeTupleStruct;
let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len()));
for f in fields {
try!(ts.serialize_field(f));
tri!(ts.serialize_field(f));
}
ts.end()
}
Content::TupleVariant(n, i, v, ref fields) => {
use ser::SerializeTupleVariant;
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
use crate::ser::SerializeTupleVariant;
let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
for f in fields {
try!(tv.serialize_field(f));
tri!(tv.serialize_field(f));
}
tv.end()
}
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
use crate::ser::SerializeMap;
let mut map = tri!(serializer.serialize_map(Some(entries.len())));
for (k, v) in entries {
try!(map.serialize_entry(k, v));
tri!(map.serialize_entry(k, v));
}
map.end()
}
Content::Struct(n, ref fields) => {
use ser::SerializeStruct;
let mut s = try!(serializer.serialize_struct(n, fields.len()));
use crate::ser::SerializeStruct;
let mut s = tri!(serializer.serialize_struct(n, fields.len()));
for &(k, ref v) in fields {
try!(s.serialize_field(k, v));
tri!(s.serialize_field(k, v));
}
s.end()
}
Content::StructVariant(n, i, v, ref fields) => {
use ser::SerializeStructVariant;
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
use crate::ser::SerializeStructVariant;
let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len()));
for &(k, ref v) in fields {
try!(sv.serialize_field(k, v));
tri!(sv.serialize_field(k, v));
}
sv.end()
}
@@ -635,11 +631,11 @@ mod content {
Ok(Content::None)
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Content, E>
fn serialize_some<T>(self, value: &T) -> Result<Content, E>
where
T: Serialize,
T: ?Sized + Serialize,
{
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
}
fn serialize_unit(self) -> Result<Content, E> {
@@ -659,21 +655,17 @@ mod content {
Ok(Content::UnitVariant(name, variant_index, variant))
}
fn serialize_newtype_struct<T: ?Sized>(
self,
name: &'static str,
value: &T,
) -> Result<Content, E>
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Content, E>
where
T: Serialize,
T: ?Sized + Serialize,
{
Ok(Content::NewtypeStruct(
name,
Box::new(try!(value.serialize(self))),
Box::new(tri!(value.serialize(self))),
))
}
fn serialize_newtype_variant<T: ?Sized>(
fn serialize_newtype_variant<T>(
self,
name: &'static str,
variant_index: u32,
@@ -681,13 +673,13 @@ mod content {
value: &T,
) -> Result<Content, E>
where
T: Serialize,
T: ?Sized + Serialize,
{
Ok(Content::NewtypeVariant(
name,
variant_index,
variant,
Box::new(try!(value.serialize(self))),
Box::new(tri!(value.serialize(self))),
))
}
@@ -782,11 +774,11 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
@@ -808,11 +800,11 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
@@ -835,11 +827,11 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
@@ -864,11 +856,11 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
@@ -896,24 +888,24 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), E>
fn serialize_key<T>(&mut self, key: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
fn serialize_value<T>(&mut self, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let key = self
.key
.take()
.expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
@@ -922,13 +914,13 @@ mod content {
Ok(Content::Map(self.entries))
}
fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E>
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), E>
where
K: Serialize,
V: Serialize,
K: ?Sized + Serialize,
V: ?Sized + Serialize,
{
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
@@ -947,11 +939,11 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
@@ -976,11 +968,11 @@ mod content {
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
@@ -1025,7 +1017,7 @@ where
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 SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
@@ -1088,9 +1080,9 @@ where
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(self)
}
@@ -1112,18 +1104,18 @@ where
Err(Self::bad_type(Unsupported::Enum))
}
fn serialize_newtype_struct<T: ?Sized>(
fn serialize_newtype_struct<T>(
self,
_: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
fn serialize_newtype_variant<T>(
self,
_: &'static str,
_: u32,
@@ -1131,10 +1123,9 @@ where
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
try!(self.0.serialize_key(variant));
self.0.serialize_value(value)
self.0.serialize_entry(variant, value)
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
@@ -1157,10 +1148,11 @@ where
self,
_: &'static str,
_: u32,
_: &'static str,
variant: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(Self::bad_type(Unsupported::Enum))
tri!(self.0.serialize_key(variant));
Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0))
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -1182,7 +1174,7 @@ where
inner_variant: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
try!(self.0.serialize_key(inner_variant));
tri!(self.0.serialize_key(inner_variant));
Ok(FlatMapSerializeStructVariantAsMapValue::new(
self.0,
inner_variant,
@@ -1201,28 +1193,24 @@ where
type Ok = ();
type Error = M::Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
self.0.serialize_key(key)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
self.0.serialize_value(value)
}
fn serialize_entry<K: ?Sized, V: ?Sized>(
&mut self,
key: &K,
value: &V,
) -> Result<(), Self::Error>
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
where
K: Serialize,
V: Serialize,
K: ?Sized + Serialize,
V: ?Sized + Serialize,
{
self.0.serialize_entry(key, value)
}
@@ -1243,13 +1231,9 @@ where
type Ok = ();
type Error = M::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
self.0.serialize_entry(key, value)
}
@@ -1259,6 +1243,52 @@ where
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> {
map: &'a mut M,
fields: Vec<Content>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> FlatMapSerializeTupleVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
fn new(map: &'a mut M) -> Self {
FlatMapSerializeTupleVariantAsMapValue {
map,
fields: Vec::new(),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<(), Self::Error> {
tri!(self.map.serialize_value(&Content::Seq(self.fields)));
Ok(())
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
map: &'a mut M,
@@ -1288,23 +1318,47 @@ where
type Ok = ();
type Error = M::Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<(), Self::Error> {
try!(self
tri!(self
.map
.serialize_value(&Content::Struct(self.name, self.fields)));
Ok(())
}
}
pub struct AdjacentlyTaggedEnumVariant {
pub enum_name: &'static str,
pub variant_index: u32,
pub variant_name: &'static str,
}
impl Serialize for AdjacentlyTaggedEnumVariant {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name)
}
}
// Error when Serialize for a non_exhaustive remote enum encounters a variant
// that is not recognized.
pub struct CannotSerializeVariant<T>(pub T);
impl<T> Display for CannotSerializeVariant<T>
where
T: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "enum variant cannot be serialized: {:?}", self.0)
}
}
+12 -17
View File
@@ -1,5 +1,5 @@
use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};
use crate::lib::*;
use crate::ser::{Error, Impossible, Serialize, Serializer};
impl Error for fmt::Error {
fn custom<T: Display>(_msg: T) -> Self {
@@ -52,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
serialize_i16: i16,
serialize_i32: i32,
serialize_i64: i64,
serialize_i128: i128,
serialize_u8: u8,
serialize_u16: u16,
serialize_u32: u32,
serialize_u64: u64,
serialize_u128: u128,
serialize_f32: f32,
serialize_f64: f64,
serialize_char: char,
@@ -63,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
serialize_unit_struct: &'static str,
}
serde_if_integer128! {
fmt_primitives! {
serialize_i128: i128,
serialize_u128: u128,
}
}
fn serialize_unit_variant(
self,
_name: &'static str,
@@ -79,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Display::fmt(variant, self)
}
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> fmt::Result
where
T: Serialize,
T: ?Sized + Serialize,
{
Serialize::serialize(value, self)
}
@@ -94,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Err(fmt::Error)
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
fn serialize_some<T>(self, _value: &T) -> fmt::Result
where
T: Serialize,
T: ?Sized + Serialize,
{
Err(fmt::Error)
}
@@ -105,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Err(fmt::Error)
}
fn serialize_newtype_variant<T: ?Sized>(
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
@@ -113,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
_value: &T,
) -> fmt::Result
where
T: Serialize,
T: ?Sized + Serialize,
{
Err(fmt::Error)
}
@@ -166,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
Err(fmt::Error)
}
fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
fn collect_str<T>(self, value: &T) -> fmt::Result
where
T: Display,
T: ?Sized + Display,
{
Display::fmt(value, self)
}
+199 -104
View File
@@ -1,6 +1,6 @@
use lib::*;
use crate::lib::*;
use ser::{Error, Serialize, SerializeTuple, Serializer};
use crate::ser::{Error, Serialize, SerializeTuple, Serializer};
////////////////////////////////////////////////////////////////////////////////
@@ -24,20 +24,17 @@ primitive_impl!(i8, serialize_i8);
primitive_impl!(i16, serialize_i16);
primitive_impl!(i32, serialize_i32);
primitive_impl!(i64, serialize_i64);
primitive_impl!(i128, serialize_i128);
primitive_impl!(usize, serialize_u64 as u64);
primitive_impl!(u8, serialize_u8);
primitive_impl!(u16, serialize_u16);
primitive_impl!(u32, serialize_u32);
primitive_impl!(u64, serialize_u64);
primitive_impl!(u128, serialize_u128);
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 {
@@ -51,6 +48,7 @@ impl Serialize for str {
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl Serialize for String {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -73,6 +71,7 @@ impl<'a> Serialize for fmt::Arguments<'a> {
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", not(no_core_cstr)))]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for CStr {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -84,6 +83,7 @@ impl Serialize for CStr {
}
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
impl Serialize for CString {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -114,7 +114,10 @@ where
////////////////////////////////////////////////////////////////////////////////
impl<T: ?Sized> Serialize for PhantomData<T> {
impl<T> Serialize for PhantomData<T>
where
T: ?Sized,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -133,7 +136,7 @@ impl<T> Serialize for [T; 0] {
where
S: Serializer,
{
try!(serializer.serialize_tuple(0)).end()
tri!(serializer.serialize_tuple(0)).end()
}
}
@@ -149,9 +152,9 @@ macro_rules! array_impls {
where
S: Serializer,
{
let mut seq = try!(serializer.serialize_tuple($len));
let mut seq = tri!(serializer.serialize_tuple($len));
for e in self {
try!(seq.serialize_element(e));
tri!(seq.serialize_element(e));
}
seq.end()
}
@@ -182,9 +185,13 @@ where
}
}
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
#[cfg(not(no_relaxed_trait_bounds))]
macro_rules! seq_impl {
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
(
$(#[$attr:meta])*
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
) => {
$(#[$attr])*
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
where
T: Serialize,
@@ -200,9 +207,13 @@ macro_rules! seq_impl {
}
}
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
#[cfg(no_relaxed_trait_bounds)]
macro_rules! seq_impl {
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
(
$(#[$attr:meta])*
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
) => {
$(#[$attr])*
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
where
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
@@ -219,23 +230,41 @@ macro_rules! seq_impl {
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(BinaryHeap<T: Ord>);
seq_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
BinaryHeap<T: Ord>
}
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(BTreeSet<T: Ord>);
seq_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
BTreeSet<T: Ord>
}
#[cfg(feature = "std")]
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
seq_impl! {
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
HashSet<T: Eq + Hash, H: BuildHasher>
}
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(LinkedList<T>);
seq_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
LinkedList<T>
}
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(Vec<T>);
seq_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
Vec<T>
}
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(VecDeque<T>);
seq_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
VecDeque<T>
}
////////////////////////////////////////////////////////////////////////////////
@@ -248,9 +277,9 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Range", 2));
try!(state.serialize_field("start", &self.start));
try!(state.serialize_field("end", &self.end));
let mut state = tri!(serializer.serialize_struct("Range", 2));
tri!(state.serialize_field("start", &self.start));
tri!(state.serialize_field("end", &self.end));
state.end()
}
}
@@ -266,15 +295,14 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeFrom", 1));
try!(state.serialize_field("start", &self.start));
let mut state = tri!(serializer.serialize_struct("RangeFrom", 1));
tri!(state.serialize_field("start", &self.start));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(not(no_range_inclusive))]
impl<Idx> Serialize for RangeInclusive<Idx>
where
Idx: Serialize,
@@ -284,9 +312,9 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
try!(state.serialize_field("start", &self.start()));
try!(state.serialize_field("end", &self.end()));
let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2));
tri!(state.serialize_field("start", &self.start()));
tri!(state.serialize_field("end", &self.end()));
state.end()
}
}
@@ -302,15 +330,14 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeTo", 1));
try!(state.serialize_field("end", &self.end));
let mut state = tri!(serializer.serialize_struct("RangeTo", 1));
tri!(state.serialize_field("end", &self.end));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<T> Serialize for Bound<T>
where
T: Serialize,
@@ -344,6 +371,7 @@ impl Serialize for () {
}
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
impl Serialize for ! {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
@@ -358,28 +386,46 @@ impl Serialize for ! {
macro_rules! tuple_impls {
($($len:expr => ($($n:tt $name:ident)+))+) => {
$(
#[cfg_attr(docsrs, doc(hidden))]
impl<$($name),+> Serialize for ($($name,)+)
where
$($name: Serialize,)+
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut tuple = try!(serializer.serialize_tuple($len));
$(
try!(tuple.serialize_element(&self.$n));
)+
tuple.end()
}
tuple_impl_body!($len => ($($n)+));
}
)+
}
};
}
macro_rules! tuple_impl_body {
($len:expr => ($($n:tt)+)) => {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut tuple = tri!(serializer.serialize_tuple($len));
$(
tri!(tuple.serialize_element(&self.$n));
)+
tuple.end()
}
};
}
#[cfg_attr(docsrs, doc(fake_variadic))]
#[cfg_attr(
docsrs,
doc = "This trait is implemented for tuples up to 16 items long."
)]
impl<T> Serialize for (T,)
where
T: Serialize,
{
tuple_impl_body!(1 => (0));
}
tuple_impls! {
1 => (0 T0)
2 => (0 T0 1 T1)
3 => (0 T0 1 T1 2 T2)
4 => (0 T0 1 T1 2 T2 3 T3)
@@ -399,9 +445,13 @@ tuple_impls! {
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
#[cfg(not(no_relaxed_trait_bounds))]
macro_rules! map_impl {
($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
(
$(#[$attr:meta])*
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>
) => {
$(#[$attr])*
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
where
K: Serialize,
@@ -418,9 +468,13 @@ macro_rules! map_impl {
}
}
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
#[cfg(no_relaxed_trait_bounds)]
macro_rules! map_impl {
($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
(
$(#[$attr:meta])*
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>
) => {
$(#[$attr])*
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
where
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
@@ -438,20 +492,26 @@ macro_rules! map_impl {
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
map_impl!(BTreeMap<K: Ord, V>);
map_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
BTreeMap<K: Ord, V>
}
#[cfg(feature = "std")]
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
map_impl! {
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
HashMap<K: Eq + Hash, V, H: BuildHasher>
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! deref_impl {
(
$(#[doc = $doc:tt])*
$(#[$attr:meta])*
<$($desc:tt)+
) => {
$(#[doc = $doc])*
$(#[$attr])*
impl <$($desc)+ {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -464,13 +524,20 @@ macro_rules! deref_impl {
};
}
deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize);
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
deref_impl! {
<'a, T> Serialize for &'a T where T: ?Sized + Serialize
}
#[cfg(any(feature = "std", feature = "alloc"))]
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
deref_impl! {
<'a, T> Serialize for &'a mut T where T: ?Sized + Serialize
}
deref_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
<T> Serialize for Box<T> where T: ?Sized + Serialize
}
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
@@ -480,10 +547,11 @@ deref_impl! {
/// repeated data.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
<T: ?Sized> Serialize for Rc<T> where T: Serialize
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
<T> Serialize for Rc<T> where T: ?Sized + Serialize
}
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
@@ -493,11 +561,16 @@ deref_impl! {
/// repeated data.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
<T: ?Sized> Serialize for Arc<T> where T: Serialize
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
<T> Serialize for Arc<T> where T: ?Sized + Serialize
}
#[cfg(any(feature = "std", feature = "alloc"))]
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
deref_impl! {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
<'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned
}
////////////////////////////////////////////////////////////////////////////////
@@ -505,9 +578,13 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
///
/// [`"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>
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
)]
impl<T> Serialize for RcWeak<T>
where
T: Serialize,
T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -521,9 +598,13 @@ where
///
/// [`"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>
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
)]
impl<T> Serialize for ArcWeak<T>
where
T: Serialize,
T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -538,7 +619,6 @@ where
macro_rules! nonzero_integers {
($($T:ident,)+) => {
$(
#[cfg(not(no_num_nonzero))]
impl Serialize for num::$T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -556,6 +636,7 @@ nonzero_integers! {
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroU128,
NonZeroUsize,
}
@@ -565,22 +646,10 @@ nonzero_integers! {
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroI128,
NonZeroIsize,
}
// Currently 128-bit integers do not work on Emscripten targets so we need an
// additional `#[cfg]`
serde_if_integer128! {
nonzero_integers! {
NonZeroU128,
}
#[cfg(not(no_num_nonzero_signed))]
nonzero_integers! {
NonZeroI128,
}
}
impl<T> Serialize for Cell<T>
where
T: Serialize + Copy,
@@ -593,9 +662,9 @@ where
}
}
impl<T: ?Sized> Serialize for RefCell<T>
impl<T> Serialize for RefCell<T>
where
T: Serialize,
T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -609,9 +678,10 @@ where
}
#[cfg(feature = "std")]
impl<T: ?Sized> Serialize for Mutex<T>
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T> Serialize for Mutex<T>
where
T: Serialize,
T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -625,9 +695,10 @@ where
}
#[cfg(feature = "std")]
impl<T: ?Sized> Serialize for RwLock<T>
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T> Serialize for RwLock<T>
where
T: Serialize,
T: ?Sized + Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -662,16 +733,15 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", not(no_core_duration)))]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Duration", 2));
try!(state.serialize_field("secs", &self.as_secs()));
try!(state.serialize_field("nanos", &self.subsec_nanos()));
let mut state = tri!(serializer.serialize_struct("Duration", 2));
tri!(state.serialize_field("secs", &self.as_secs()));
tri!(state.serialize_field("nanos", &self.subsec_nanos()));
state.end()
}
}
@@ -679,6 +749,7 @@ impl Serialize for Duration {
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for SystemTime {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -689,9 +760,9 @@ impl Serialize for SystemTime {
Ok(duration_since_epoch) => duration_since_epoch,
Err(_) => return Err(S::Error::custom("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()));
let mut state = tri!(serializer.serialize_struct("SystemTime", 2));
tri!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
tri!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
state.end()
}
}
@@ -723,6 +794,7 @@ macro_rules! serialize_display_bounded_length {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -793,6 +865,7 @@ fn test_format_u8() {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -817,6 +890,7 @@ impl Serialize for net::Ipv4Addr {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for net::Ipv6Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -833,6 +907,7 @@ impl Serialize for net::Ipv6Addr {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for net::SocketAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -857,6 +932,7 @@ impl Serialize for net::SocketAddr {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for net::SocketAddrV4 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -873,6 +949,7 @@ impl Serialize for net::SocketAddrV4 {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for net::SocketAddrV6 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -894,6 +971,7 @@ impl Serialize for net::SocketAddrV6 {
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for Path {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -907,6 +985,7 @@ impl Serialize for Path {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Serialize for PathBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -917,6 +996,7 @@ impl Serialize for PathBuf {
}
#[cfg(all(feature = "std", any(unix, windows)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
impl Serialize for OsStr {
#[cfg(unix)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -939,6 +1019,7 @@ impl Serialize for OsStr {
}
#[cfg(all(feature = "std", any(unix, windows)))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
impl Serialize for OsString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -963,7 +1044,20 @@ where
}
}
#[cfg(not(no_core_reverse))]
#[cfg(not(no_core_num_saturating))]
impl<T> Serialize for Saturating<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl<T> Serialize for Reverse<T>
where
T: Serialize,
@@ -984,6 +1078,7 @@ macro_rules! atomic_impl {
($($ty:ident $size:expr)*) => {
$(
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", target_has_atomic = $size))))]
impl Serialize for $ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
+18 -18
View File
@@ -1,8 +1,8 @@
//! This module contains `Impossible` serializer and its implementations.
use lib::*;
use crate::lib::*;
use ser::{
use crate::ser::{
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
};
@@ -72,9 +72,9 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -92,9 +92,9 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -112,9 +112,9 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -132,9 +132,9 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -152,17 +152,17 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = key;
match self.void {}
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = value;
match self.void {}
@@ -180,9 +180,9 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = key;
let _ = value;
@@ -201,9 +201,9 @@ where
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
T: ?Sized + Serialize,
{
let _ = key;
let _ = value;
+100 -130
View File
@@ -61,8 +61,8 @@
//! - RefCell\<T\>
//! - Mutex\<T\>
//! - RwLock\<T\>
//! - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Rc\<T\>&emsp;*(if* features = \["rc"\] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = \["rc"\] *is enabled)*
//! - **Collection types**:
//! - BTreeMap\<K, V\>
//! - BTreeSet\<T\>
@@ -107,7 +107,7 @@
//! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats
use lib::*;
use crate::lib::*;
mod fmt;
mod impls;
@@ -115,15 +115,15 @@ mod impossible;
pub use self::impossible::Impossible;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use crate::std_error::Error as StdError;
#[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(inline)]
#[doc(no_inline)]
pub use core::error::Error as StdError;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
////////////////////////////////////////////////////////////////////////////////
@@ -215,6 +215,13 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
/// [`serde_derive`]: https://crates.io/crates/serde_derive
/// [derive section of the manual]: https://serde.rs/derive.html
#[cfg_attr(
not(no_diagnostic_namespace),
diagnostic::on_unimplemented(
note = "for local types consider adding `#[derive(serde::Serialize)]` to your `{Self}` type",
note = "for types from other crates check whether the crate offers a `serde` feature flag",
)
)]
pub trait Serialize {
/// Serialize this value into the given Serde serializer.
///
@@ -488,30 +495,27 @@ pub trait Serializer: Sized {
/// ```
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize an `i128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i128(*self)
/// }
/// }
/// ```
///
/// 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 an `i128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i128(*self)
/// }
/// }
/// ```
///
/// 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.
@@ -598,30 +602,27 @@ pub trait Serializer: Sized {
/// ```
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize a `u128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u128(*self)
/// }
/// }
/// ```
///
/// 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 a `u128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u128(*self)
/// }
/// }
/// ```
///
/// 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.
@@ -802,9 +803,9 @@ pub trait Serializer: Sized {
/// ```
///
/// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Serialize a `()` value.
///
@@ -897,13 +898,13 @@ pub trait Serializer: Sized {
/// }
/// }
/// ```
fn serialize_newtype_struct<T: ?Sized>(
fn serialize_newtype_struct<T>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
///
@@ -931,7 +932,7 @@ pub trait Serializer: Sized {
/// }
/// }
/// ```
fn serialize_newtype_variant<T: ?Sized>(
fn serialize_newtype_variant<T>(
self,
name: &'static str,
variant_index: u32,
@@ -939,7 +940,7 @@ pub trait Serializer: Sized {
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Begin to serialize a variably sized sequence. This call must be
/// followed by zero or more calls to `serialize_element`, then a call to
@@ -1176,7 +1177,8 @@ pub trait Serializer: Sized {
/// then a call to `end`.
///
/// The `name` is the name of the struct and the `len` is the number of
/// data fields that will be serialized.
/// data fields that will be serialized. `len` does not include fields
/// which are skipped with [`SerializeStruct::skip_field`].
///
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
@@ -1213,6 +1215,8 @@ pub trait Serializer: Sized {
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
/// `len` does not include fields which are skipped with
/// [`SerializeStructVariant::skip_field`].
///
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
@@ -1279,22 +1283,9 @@ pub trait Serializer: Sized {
I: IntoIterator,
<I as IntoIterator>::Item: Serialize,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter)));
#[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|item| serializer.serialize_element(&item)));
}
#[cfg(no_iterator_try_fold)]
{
for item in iter {
try!(serializer.serialize_element(&item));
}
}
let mut iter = iter.into_iter();
let mut serializer = tri!(self.serialize_seq(iterator_len_hint(&iter)));
tri!(iter.try_for_each(|item| serializer.serialize_element(&item)));
serializer.end()
}
@@ -1330,22 +1321,9 @@ pub trait Serializer: Sized {
V: Serialize,
I: IntoIterator<Item = (K, V)>,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter)));
#[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
}
#[cfg(no_iterator_try_fold)]
{
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
}
let mut iter = iter.into_iter();
let mut serializer = tri!(self.serialize_map(iterator_len_hint(&iter)));
tri!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
serializer.end()
}
@@ -1378,9 +1356,9 @@ pub trait Serializer: Sized {
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
/// [`serialize_str`]: #tymethod.serialize_str
#[cfg(any(feature = "std", feature = "alloc"))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Display,
T: ?Sized + Display,
{
self.serialize_str(&value.to_string())
}
@@ -1411,9 +1389,9 @@ pub trait Serializer: Sized {
/// }
/// ```
#[cfg(not(any(feature = "std", feature = "alloc")))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: Display;
T: ?Sized + Display;
/// Determine whether `Serialize` implementations should serialize in
/// human-readable form.
@@ -1525,9 +1503,9 @@ pub trait SerializeSeq {
type Error: Error;
/// Serialize a sequence element.
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Finish serializing a sequence.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1625,9 +1603,9 @@ pub trait SerializeTuple {
type Error: Error;
/// Serialize a tuple element.
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Finish serializing a tuple.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1670,9 +1648,9 @@ pub trait SerializeTupleStruct {
type Error: Error;
/// Serialize a tuple struct field.
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Finish serializing a tuple struct.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1728,9 +1706,9 @@ pub trait SerializeTupleVariant {
type Error: Error;
/// Serialize a tuple variant field.
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Finish serializing a tuple variant.
fn end(self) -> Result<Self::Ok, Self::Error>;
@@ -1799,9 +1777,9 @@ pub trait SerializeMap {
/// `serialize_entry` instead as it may be implemented more efficiently in
/// some formats compared to a pair of calls to `serialize_key` and
/// `serialize_value`.
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Serialize a map value.
///
@@ -1809,9 +1787,9 @@ pub trait SerializeMap {
///
/// Calling `serialize_value` before `serialize_key` is incorrect and is
/// allowed to panic or produce bogus results.
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Serialize a map entry consisting of a key and a value.
///
@@ -1830,16 +1808,12 @@ pub trait SerializeMap {
/// [`Serialize`]: ../trait.Serialize.html
/// [`serialize_key`]: #tymethod.serialize_key
/// [`serialize_value`]: #tymethod.serialize_value
fn serialize_entry<K: ?Sized, V: ?Sized>(
&mut self,
key: &K,
value: &V,
) -> Result<(), Self::Error>
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
where
K: Serialize,
V: Serialize,
K: ?Sized + Serialize,
V: ?Sized + Serialize,
{
try!(self.serialize_key(key));
tri!(self.serialize_key(key));
self.serialize_value(value)
}
@@ -1888,15 +1862,13 @@ pub trait SerializeStruct {
type Error: Error;
/// Serialize a struct field.
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Indicate that a struct field has been skipped.
///
/// The default implementation does nothing.
#[inline]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
let _ = key;
@@ -1954,15 +1926,13 @@ pub trait SerializeStructVariant {
type Error: Error;
/// Serialize a struct variant field.
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
where
T: Serialize;
T: ?Sized + Serialize;
/// Indicate that a struct variant field has been skipped.
///
/// The default implementation does nothing.
#[inline]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
let _ = key;
+1 -1
View File
@@ -1,4 +1,4 @@
use lib::{Debug, Display};
use crate::lib::{Debug, Display};
/// Either a re-export of std::error::Error or a new identical trait, depending
/// on whether Serde's "std" feature is enabled.
+6 -4
View File
@@ -1,10 +1,12 @@
[package]
name = "serde_derive"
version = "1.0.177" # remember to update html_root_url
version = "1.0.206"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
documentation = "https://serde.rs/derive.html"
edition = "2015"
exclude = ["build.rs"]
homepage = "https://serde.rs"
keywords = ["serde", "serialization", "no_std", "derive"]
license = "MIT OR Apache-2.0"
@@ -21,9 +23,9 @@ name = "serde_derive"
proc-macro = true
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = "2.0.25"
proc-macro2 = { workspace = true, features = ["proc-macro"] }
quote = { workspace = true, features = ["proc-macro"] }
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] }
[dev-dependencies]
serde = { version = "1", path = "../serde" }
+8
View File
@@ -0,0 +1,8 @@
fn main() {
// Warning: build.rs is not published to crates.io.
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-cfg=check_cfg");
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
}
+3 -6
View File
@@ -144,6 +144,7 @@ pub fn with_bound(
fn visit_type(&mut self, ty: &'ast syn::Type) {
match ty {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::Type::Array(ty) => self.visit_type(&ty.elem),
syn::Type::BareFn(ty) => {
for arg in &ty.inputs {
@@ -181,7 +182,6 @@ pub fn with_bound(
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
@@ -196,16 +196,13 @@ pub fn with_bound(
syn::PathArguments::AngleBracketed(arguments) => {
for arg in &arguments.args {
match arg {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::GenericArgument::Type(arg) => self.visit_type(arg),
syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty),
syn::GenericArgument::Lifetime(_)
| syn::GenericArgument::Const(_)
| syn::GenericArgument::AssocConst(_)
| syn::GenericArgument::Constraint(_) => {}
#[cfg_attr(
all(test, exhaustive),
deny(non_exhaustive_omitted_patterns)
)]
_ => {}
}
}
@@ -228,9 +225,9 @@ pub fn with_bound(
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
match bound {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
+295 -306
View File
File diff suppressed because it is too large Load Diff
-4
View File
@@ -1,10 +1,7 @@
use crate::try;
use proc_macro2::TokenStream;
use quote::quote;
pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream {
let try_replacement = try::replacement();
let use_serde = match serde_path {
Some(path) => quote! {
use #path as _serde;
@@ -20,7 +17,6 @@ pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> Token
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#use_serde
#try_replacement
#code
};
}
+1
View File
@@ -85,6 +85,7 @@ impl<'a> Container<'a> {
for field in &mut variant.fields {
if field.attrs.flatten() {
has_flatten = true;
variant.attrs.mark_has_flatten();
}
field.attrs.rename_by_rules(
variant
+88 -42
View File
@@ -134,7 +134,7 @@ pub struct Name {
serialize_renamed: bool,
deserialize: String,
deserialize_renamed: bool,
deserialize_aliases: Vec<String>,
deserialize_aliases: BTreeSet<String>,
}
fn unraw(ident: &Ident) -> String {
@@ -148,16 +148,12 @@ impl Name {
de_name: Attr<String>,
de_aliases: Option<VecAttr<String>>,
) -> Name {
let deserialize_aliases = match de_aliases {
Some(de_aliases) => {
let mut alias_list = BTreeSet::new();
for alias_name in de_aliases.get() {
alias_list.insert(alias_name);
}
alias_list.into_iter().collect()
let mut alias_set = BTreeSet::new();
if let Some(de_aliases) = de_aliases {
for alias_name in de_aliases.get() {
alias_set.insert(alias_name);
}
None => Vec::new(),
};
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
@@ -168,34 +164,29 @@ impl Name {
serialize_renamed: ser_renamed,
deserialize: de_name.unwrap_or(source_name),
deserialize_renamed: de_renamed,
deserialize_aliases,
deserialize_aliases: alias_set,
}
}
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String {
self.serialize.clone()
pub fn serialize_name(&self) -> &str {
&self.serialize
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
pub fn deserialize_name(&self) -> &str {
&self.deserialize
}
fn deserialize_aliases(&self) -> Vec<String> {
let mut aliases = self.deserialize_aliases.clone();
let main_name = self.deserialize_name();
if !aliases.contains(&main_name) {
aliases.push(main_name);
}
aliases
fn deserialize_aliases(&self) -> &BTreeSet<String> {
&self.deserialize_aliases
}
}
#[derive(Copy, Clone)]
pub struct RenameAllRules {
serialize: RenameRule,
deserialize: RenameRule,
pub serialize: RenameRule,
pub deserialize: RenameRule,
}
impl RenameAllRules {
@@ -225,11 +216,28 @@ pub struct Container {
type_into: Option<syn::Type>,
remote: Option<syn::Path>,
identifier: Identifier,
/// True if container is a struct and has a field with `#[serde(flatten)]`,
/// or is an enum with a struct variant which has a field with
/// `#[serde(flatten)]`.
///
/// ```ignore
/// struct Container {
/// #[serde(flatten)]
/// some_field: (),
/// }
/// enum Container {
/// Variant {
/// #[serde(flatten)]
/// some_field: (),
/// },
/// }
/// ```
has_flatten: bool,
serde_path: Option<syn::Path>,
is_packed: bool,
/// Error message generated when type can't be deserialized
expecting: Option<String>,
non_exhaustive: bool,
}
/// Styles of representing an enum.
@@ -315,9 +323,12 @@ impl Container {
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
let mut serde_path = Attr::none(cx, CRATE);
let mut expecting = Attr::none(cx, EXPECTING);
let mut non_exhaustive = false;
for attr in &item.attrs {
if attr.path() != SERDE {
non_exhaustive |=
matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE);
continue;
}
@@ -405,20 +416,20 @@ impl Container {
if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
match &item.data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => {
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
default.set(&meta.path, Default::Path(path));
}
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
syn::Fields::Unit => {
let msg = "#[serde(default = \"...\")] can only be used on structs that have fields";
cx.syn_error(meta.error(msg));
}
},
syn::Data::Enum(_) => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
let msg = "#[serde(default = \"...\")] can only be used on structs";
cx.syn_error(meta.error(msg));
}
syn::Data::Union(_) => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
let msg = "#[serde(default = \"...\")] can only be used on structs";
cx.syn_error(meta.error(msg));
}
}
@@ -427,20 +438,20 @@ impl Container {
// #[serde(default)]
match &item.data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => {
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
default.set(meta.path, Default::Default);
}
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
let msg = "#[serde(default)] can only be used on structs with named fields";
syn::Fields::Unit => {
let msg = "#[serde(default)] can only be used on structs that have fields";
cx.error_spanned_by(fields, msg);
}
},
syn::Data::Enum(_) => {
let msg = "#[serde(default)] can only be used on structs with named fields";
let msg = "#[serde(default)] can only be used on structs";
cx.syn_error(meta.error(msg));
}
syn::Data::Union(_) => {
let msg = "#[serde(default)] can only be used on structs with named fields";
let msg = "#[serde(default)] can only be used on structs";
cx.syn_error(meta.error(msg));
}
}
@@ -596,6 +607,7 @@ impl Container {
serde_path: serde_path.get(),
is_packed,
expecting: expecting.get(),
non_exhaustive,
}
}
@@ -681,6 +693,10 @@ impl Container {
pub fn expecting(&self) -> Option<&str> {
self.expecting.as_ref().map(String::as_ref)
}
pub fn non_exhaustive(&self) -> bool {
self.non_exhaustive
}
}
fn decide_tag(
@@ -716,7 +732,7 @@ fn decide_tag(
}
TagType::Internal { tag }
}
(Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => {
(Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => {
let msg = "enum cannot be both untagged and internally tagged";
cx.error_spanned_by(untagged_tokens, msg);
cx.error_spanned_by(tag_tokens, msg);
@@ -727,14 +743,14 @@ fn decide_tag(
cx.error_spanned_by(content_tokens, msg);
TagType::External
}
(Some((untagged_tokens, _)), None, Some((content_tokens, _))) => {
(Some((untagged_tokens, ())), None, Some((content_tokens, _))) => {
let msg = "untagged enum cannot have #[serde(content = \"...\")]";
cx.error_spanned_by(untagged_tokens, msg);
cx.error_spanned_by(content_tokens, msg);
TagType::External
}
(None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content },
(Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => {
(Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => {
let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]";
cx.error_spanned_by(untagged_tokens, msg);
cx.error_spanned_by(tag_tokens, msg);
@@ -756,7 +772,7 @@ fn decide_identifier(
variant_identifier.0.get_with_tokens(),
) {
(_, None, None) => Identifier::No,
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
(_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => {
let msg =
"#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
cx.error_spanned_by(field_identifier_tokens, msg);
@@ -794,6 +810,18 @@ pub struct Variant {
rename_all_rules: RenameAllRules,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
/// True if variant is a struct variant which contains a field with
/// `#[serde(flatten)]`.
///
/// ```ignore
/// enum Enum {
/// Variant {
/// #[serde(flatten)]
/// some_field: (),
/// },
/// }
/// ```
has_flatten: bool,
skip_deserializing: bool,
skip_serializing: bool,
other: bool,
@@ -963,6 +991,7 @@ impl Variant {
},
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
has_flatten: false,
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
other: other.get(),
@@ -977,7 +1006,7 @@ impl Variant {
&self.name
}
pub fn aliases(&self) -> Vec<String> {
pub fn aliases(&self) -> &BTreeSet<String> {
self.name.deserialize_aliases()
}
@@ -988,6 +1017,9 @@ impl Variant {
if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
}
self.name
.deserialize_aliases
.insert(self.name.deserialize.clone());
}
pub fn rename_all_rules(&self) -> RenameAllRules {
@@ -1002,6 +1034,14 @@ impl Variant {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn has_flatten(&self) -> bool {
self.has_flatten
}
pub fn mark_has_flatten(&mut self) {
self.has_flatten = true;
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
@@ -1316,7 +1356,7 @@ impl Field {
&self.name
}
pub fn aliases(&self) -> Vec<String> {
pub fn aliases(&self) -> &BTreeSet<String> {
self.name.deserialize_aliases()
}
@@ -1327,6 +1367,9 @@ impl Field {
if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
}
self.name
.deserialize_aliases
.insert(self.name.deserialize.clone());
}
pub fn skip_serializing(&self) -> bool {
@@ -1788,6 +1831,7 @@ fn borrowable_lifetimes(
fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
match ty {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::Type::Slice(ty) => {
collect_lifetimes(&ty.elem, out);
}
@@ -1823,7 +1867,10 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
syn::GenericArgument::AssocType(binding) => {
collect_lifetimes(&binding.ty, out);
}
_ => {}
syn::GenericArgument::Const(_)
| syn::GenericArgument::AssocConst(_)
| syn::GenericArgument::Constraint(_)
| _ => {}
}
}
}
@@ -1845,7 +1892,6 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
| syn::Type::Infer(_)
| syn::Type::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
+38 -1
View File
@@ -1,11 +1,12 @@
use crate::internals::ast::{Container, Data, Field, Style};
use crate::internals::attr::{Identifier, TagType};
use crate::internals::attr::{Default, Identifier, TagType};
use crate::internals::{ungroup, 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_default_on_tuple(cx, cont);
check_remote_generic(cx, cont);
check_getter(cx, cont);
check_flatten(cx, cont);
@@ -17,6 +18,39 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_from_and_try_from(cx, cont);
}
// If some field of a tuple struct is marked #[serde(default)] then all fields
// after it must also be marked with that attribute, or the struct must have a
// container-level serde(default) attribute. A field's default value is only
// used for tuple fields if the sequence is exhausted at that point; that means
// all subsequent fields will fail to deserialize if they don't have their own
// default.
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
if let Default::None = cont.attrs.default() {
if let Data::Struct(Style::Tuple, fields) = &cont.data {
let mut first_default_index = None;
for (i, field) in fields.iter().enumerate() {
// Skipped fields automatically get the #[serde(default)]
// attribute. We are interested only on non-skipped fields here.
if field.attrs.skip_deserializing() {
continue;
}
if let Default::None = field.attrs.default() {
if let Some(first) = first_default_index {
cx.error_spanned_by(
field.ty,
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
);
}
continue;
}
if first_default_index.is_none() {
first_default_index = Some(i);
}
}
}
}
}
// Remote derive definition type must have either all of the generics of the
// remote type:
//
@@ -284,6 +318,9 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
for variant in variants {
match variant.style {
Style::Struct => {
if variant.attrs.untagged() {
continue;
}
for field in &variant.fields {
let check_ser =
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
+5 -5
View File
@@ -84,7 +84,7 @@ impl ReplaceReceiver<'_> {
self.visit_type_mut_impl(ty);
return;
};
*ty = self.self_ty(span).into();
*ty = Type::Path(self.self_ty(span));
}
// `Self::Assoc` -> `<Receiver>::Assoc`
@@ -107,6 +107,7 @@ impl ReplaceReceiver<'_> {
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
match ty {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
Type::Array(ty) => {
self.visit_type_mut(&mut ty.elem);
self.visit_expr_mut(&mut ty.len);
@@ -147,7 +148,6 @@ impl ReplaceReceiver<'_> {
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
@@ -178,13 +178,13 @@ impl ReplaceReceiver<'_> {
PathArguments::AngleBracketed(arguments) => {
for arg in &mut arguments.args {
match arg {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
GenericArgument::Type(arg) => self.visit_type_mut(arg),
GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
GenericArgument::Lifetime(_)
| GenericArgument::Const(_)
| GenericArgument::AssocConst(_)
| GenericArgument::Constraint(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
@@ -207,9 +207,9 @@ impl ReplaceReceiver<'_> {
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
match bound {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
@@ -228,6 +228,7 @@ impl ReplaceReceiver<'_> {
if let Some(where_clause) = &mut generics.where_clause {
for predicate in &mut where_clause.predicates {
match predicate {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
WherePredicate::Type(predicate) => {
self.visit_type_mut(&mut predicate.bounded_ty);
for bound in &mut predicate.bounds {
@@ -235,7 +236,6 @@ impl ReplaceReceiver<'_> {
}
}
WherePredicate::Lifetime(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
+1
View File
@@ -19,6 +19,7 @@ pub const FLATTEN: Symbol = Symbol("flatten");
pub const FROM: Symbol = Symbol("from");
pub const GETTER: Symbol = Symbol("getter");
pub const INTO: Symbol = Symbol("into");
pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive");
pub const OTHER: Symbol = Symbol("other");
pub const REMOTE: Symbol = Symbol("remote");
pub const RENAME: Symbol = Symbol("rename");
+4 -24
View File
@@ -13,7 +13,8 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.177")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.206")]
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
// Ignored clippy lints
#![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
@@ -50,7 +51,6 @@
clippy::match_wildcard_for_single_variants,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::option_if_let_else,
clippy::similar_names,
clippy::single_match_else,
clippy::struct_excessive_bools,
@@ -66,17 +66,11 @@ extern crate proc_macro2;
extern crate quote;
extern crate syn;
#[cfg(not(precompiled))]
extern crate proc_macro;
#[cfg(precompiled)]
extern crate proc_macro2 as proc_macro;
mod internals;
use proc_macro::TokenStream;
#[cfg(precompiled)]
use std::sync::atomic::AtomicBool;
#[cfg(not(precompiled))]
use syn::parse_macro_input;
use syn::DeriveInput;
@@ -90,22 +84,8 @@ mod dummy;
mod pretend;
mod ser;
mod this;
mod try;
#[cfg(precompiled)]
macro_rules! parse_macro_input {
($tokenstream:ident as $ty:ty) => {
match syn::parse2::<$ty>($tokenstream) {
Ok(data) => data,
Err(err) => return err.to_compile_error(),
}
};
}
#[cfg(precompiled)]
pub static DESERIALIZE_IN_PLACE: AtomicBool = AtomicBool::new(false);
#[cfg_attr(not(precompiled), proc_macro_derive(Serialize, attributes(serde)))]
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&mut input)
@@ -113,7 +93,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
.into()
}
#[cfg_attr(not(precompiled), proc_macro_derive(Deserialize, attributes(serde)))]
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&mut input)
+4 -4
View File
@@ -64,14 +64,14 @@ pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
match &cont.data {
Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
Data::Struct(Style::Struct, fields) => {
Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => {
if is_packed {
pretend_fields_used_struct_packed(cont, fields)
} else {
pretend_fields_used_struct(cont, fields)
}
}
Data::Struct(_, _) => quote!(),
Data::Struct(Style::Unit, _) => quote!(),
}
}
@@ -115,13 +115,13 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre
let patterns = variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
Style::Struct | Style::Tuple | Style::Newtype => {
let variant_ident = &variant.ident;
let members = variant.fields.iter().map(|field| &field.member);
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
}
_ => None,
Style::Unit => None,
})
.collect::<Vec<_>>();
+84 -63
View File
@@ -282,14 +282,14 @@ fn serialize_tuple_struct(
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?;
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
}
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
assert!(fields.len() as u64 <= u64::from(u32::max_value()));
assert!(fields.len() as u64 <= u64::from(u32::MAX));
if cattrs.has_flatten() {
serialize_struct_as_map(params, fields, cattrs)
@@ -304,7 +304,7 @@ fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTra
let type_name = cattrs.name().serialize_name();
let func = struct_trait.serialize_field(Span::call_site());
quote! {
try!(#func(&mut __serde_state, #tag, #type_name));
#func(&mut __serde_state, #tag, #type_name)?;
}
}
_ => quote! {},
@@ -345,7 +345,7 @@ fn serialize_struct_as_struct(
);
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
#tag_field
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
@@ -389,7 +389,7 @@ fn serialize_struct_as_map(
};
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?;
#tag_field
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
@@ -397,11 +397,11 @@ fn serialize_struct_as_map(
}
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
assert!(variants.len() as u64 <= u64::from(u32::max_value()));
assert!(variants.len() as u64 <= u64::from(u32::MAX));
let self_var = &params.self_var;
let arms: Vec<_> = variants
let mut arms: Vec<_> = variants
.iter()
.enumerate()
.map(|(variant_index, variant)| {
@@ -409,6 +409,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
})
.collect();
if cattrs.remote().is_some() && cattrs.non_exhaustive() {
arms.push(quote! {
ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))),
});
}
quote_expr! {
match *#self_var {
#(#arms)*
@@ -478,7 +484,14 @@ fn serialize_variant(
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
(attr::TagType::Adjacent { tag, content }, false) => {
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
serialize_adjacently_tagged_variant(
params,
variant,
cattrs,
variant_index,
tag,
content,
)
}
(attr::TagType::None, _) | (_, true) => {
serialize_untagged_variant(params, variant, cattrs)
@@ -559,7 +572,7 @@ fn serialize_externally_tagged_variant(
},
params,
&variant.fields,
&type_name,
type_name,
),
}
}
@@ -593,10 +606,10 @@ fn serialize_internally_tagged_variant(
match effective_style(variant) {
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 1)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name)?;
_serde::ser::SerializeStruct::end(__struct)
}
}
@@ -624,7 +637,7 @@ fn serialize_internally_tagged_variant(
StructVariant::InternallyTagged { tag, variant_name },
params,
&variant.fields,
&type_name,
type_name,
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
@@ -634,12 +647,20 @@ fn serialize_adjacently_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
variant_index: u32,
tag: &str,
content: &str,
) -> Fragment {
let this_type = &params.this_type;
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let serialize_variant = quote! {
&_serde::__private::ser::AdjacentlyTaggedEnumVariant {
enum_name: #type_name,
variant_index: #variant_index,
variant_name: #variant_name,
}
};
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, variant);
@@ -650,10 +671,10 @@ fn serialize_adjacently_tagged_variant(
match effective_style(variant) {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 1)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #serialize_variant)?;
_serde::ser::SerializeStruct::end(__struct)
};
}
@@ -667,12 +688,12 @@ fn serialize_adjacently_tagged_variant(
let span = field.original.span();
let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(#func(
&mut __struct, #content, #field_expr));
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 2)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #serialize_variant)?;
#func(
&mut __struct, #content, #field_expr)?;
_serde::ser::SerializeStruct::end(__struct)
};
}
@@ -683,13 +704,13 @@ fn serialize_adjacently_tagged_variant(
StructVariant::Untagged,
params,
&variant.fields,
&variant_name,
variant_name,
),
}
});
let fields_ty = variant.fields.iter().map(|f| &f.ty);
let fields_ident: &Vec<_> = &match variant.style {
let fields_ident: &[_] = &match variant.style {
Style::Unit => {
if variant.attrs.serialize_with().is_some() {
vec![]
@@ -732,15 +753,15 @@ fn serialize_adjacently_tagged_variant(
}
}
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 2)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #serialize_variant)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*),
phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
}));
})?;
_serde::ser::SerializeStruct::end(__struct)
}
}
@@ -779,16 +800,16 @@ fn serialize_untagged_variant(
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
Style::Struct => {
let type_name = cattrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
}
}
}
enum TupleVariant {
enum TupleVariant<'a> {
ExternallyTagged {
type_name: String,
type_name: &'a str,
variant_index: u32,
variant_name: String,
variant_name: &'a str,
},
Untagged,
}
@@ -830,21 +851,21 @@ fn serialize_tuple_variant(
variant_name,
} => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
__serializer,
#type_name,
#variant_index,
#variant_name,
#len));
#len)?;
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
TupleVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
__serializer,
#len));
#len)?;
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
}
@@ -855,11 +876,11 @@ fn serialize_tuple_variant(
enum StructVariant<'a> {
ExternallyTagged {
variant_index: u32,
variant_name: String,
variant_name: &'a str,
},
InternallyTagged {
tag: &'a str,
variant_name: String,
variant_name: &'a str,
},
Untagged,
}
@@ -907,40 +928,40 @@ fn serialize_struct_variant(
variant_name,
} => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
__serializer,
#name,
#variant_index,
#variant_name,
#len,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
let mut __serde_state = _serde::Serializer::serialize_struct(
__serializer,
#name,
#len + 1,
));
try!(_serde::ser::SerializeStruct::serialize_field(
)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
#tag,
#variant_name,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
let #let_mut __serde_state = _serde::Serializer::serialize_struct(
__serializer,
#name,
#len,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
@@ -990,9 +1011,9 @@ fn serialize_struct_variant_with_flatten(
__S: _serde::Serializer,
{
let (#(#members,)*) = self.data;
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
let #let_mut __serde_state = _serde::Serializer::serialize_map(
__serializer,
_serde::__private::None));
_serde::__private::None)?;
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -1011,23 +1032,23 @@ fn serialize_struct_variant_with_flatten(
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
let #let_mut __serde_state = _serde::Serializer::serialize_map(
__serializer,
_serde::__private::None));
try!(_serde::ser::SerializeMap::serialize_entry(
_serde::__private::None)?;
_serde::ser::SerializeMap::serialize_entry(
&mut __serde_state,
#tag,
#variant_name,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
let #let_mut __serde_state = _serde::Serializer::serialize_map(
__serializer,
_serde::__private::None));
_serde::__private::None)?;
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -1072,7 +1093,7 @@ fn serialize_tuple_struct_visitor(
let span = field.original.span();
let func = tuple_trait.serialize_element(span);
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
#func(&mut __serde_state, #field_expr)?;
};
match skip {
@@ -1116,12 +1137,12 @@ fn serialize_struct_visitor(
let ser = if field.attrs.flatten() {
let func = quote_spanned!(span=> _serde::Serialize::serialize);
quote! {
try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state)));
#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
}
} else {
let func = struct_trait.serialize_field(span);
quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
#func(&mut __serde_state, #key_expr, #field_expr)?;
}
};
@@ -1133,7 +1154,7 @@ fn serialize_struct_visitor(
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
#skip_func(&mut __serde_state, #key_expr)?;
}
}
} else {
@@ -1233,7 +1254,7 @@ fn wrap_serialize_with(
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// let mut __serde_state = serializer.serialize_struct("S", 0)?;
// _serde::ser::SerializeStruct::end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
-25
View File
@@ -1,25 +0,0 @@
use proc_macro2::{Punct, Spacing, TokenStream};
use quote::quote;
// 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::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
}
}
}
+5 -4
View File
@@ -1,9 +1,10 @@
[package]
name = "serde_derive_internals"
version = "0.28.0" # remember to update html_root_url
version = "0.29.1"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
description = "AST representation used by Serde derive macros. Unstable."
documentation = "https://docs.rs/serde_derive_internals"
edition = "2015"
exclude = ["build.rs"]
homepage = "https://serde.rs"
keywords = ["serde", "serialization"]
@@ -15,9 +16,9 @@ rust-version = "1.56"
path = "lib.rs"
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
proc-macro2 = { workspace = true }
quote = { workspace = true }
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+8
View File
@@ -1,9 +1,17 @@
use std::path::Path;
fn main() {
// Warning: build.rs is not published to crates.io.
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/mod.rs");
println!("cargo:rustc-cfg=check_cfg");
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
println!("cargo:rustc-check-cfg=cfg(serde_build_from_git)");
println!("cargo:rustc-check-cfg=cfg(feature, values(\"deserialize_in_place\"))");
// Sometimes on Windows the git checkout does not correctly wire up the
// symlink from serde_derive_internals/src to serde_derive/src/internals.
// When this happens we'll just build based on relative paths within the git
+2 -1
View File
@@ -1,4 +1,5 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.28.0")]
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.1")]
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
// Ignored clippy lints
#![allow(
clippy::cognitive_complexity,
+1 -1
View File
@@ -18,4 +18,4 @@ rustversion = "1.0"
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = "1.0.176"
trybuild = { version = "1.0.66", features = ["diff"] }
trybuild = { version = "1.0.97", features = ["diff"] }
+6 -5
View File
@@ -1,3 +1,4 @@
#![allow(internal_features)]
#![feature(lang_items, start)]
#![no_std]
@@ -22,21 +23,21 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Unit;
pub struct Unit;
#[derive(Serialize, Deserialize)]
struct Newtype(u8);
pub struct Newtype(u8);
#[derive(Serialize, Deserialize)]
struct Tuple(u8, u8);
pub struct Tuple(u8, u8);
#[derive(Serialize, Deserialize)]
struct Struct {
pub struct Struct {
f: u8,
}
#[derive(Serialize, Deserialize)]
enum Enum {
pub enum Enum {
Unit,
Newtype(u8),
Tuple(u8, u8),
+3 -3
View File
@@ -1,6 +1,6 @@
#[cfg_attr(target_os = "emscripten", ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[cfg_attr(miri, ignore)]
#[cfg_attr(target_os = "emscripten", ignore = "disabled on Emscripten")]
#[rustversion::attr(not(nightly), ignore = "requires nightly")]
#[cfg_attr(miri, ignore = "incompatible with miri")]
#[allow(unused_attributes)]
#[test]
fn ui() {
+66
View File
@@ -0,0 +1,66 @@
#![allow(dead_code)] // we do not read enum fields
use serde_derive::Deserialize;
#[derive(Deserialize)]
pub struct Nested;
#[derive(Deserialize)]
pub enum ExternallyTagged1 {
Tuple(f64, String),
Flatten {
#[serde(flatten)]
nested: Nested,
},
}
#[derive(Deserialize)]
pub enum ExternallyTagged2 {
Flatten {
#[serde(flatten)]
nested: Nested,
},
Tuple(f64, String),
}
// Internally tagged enums cannot contain tuple variants so not tested here
#[derive(Deserialize)]
#[serde(tag = "tag", content = "content")]
pub enum AdjacentlyTagged1 {
Tuple(f64, String),
Flatten {
#[serde(flatten)]
nested: Nested,
},
}
#[derive(Deserialize)]
#[serde(tag = "tag", content = "content")]
pub enum AdjacentlyTagged2 {
Flatten {
#[serde(flatten)]
nested: Nested,
},
Tuple(f64, String),
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Untagged1 {
Tuple(f64, String),
Flatten {
#[serde(flatten)]
nested: Nested,
},
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Untagged2 {
Flatten {
#[serde(flatten)]
nested: Nested,
},
Tuple(f64, String),
}
+8
View File
@@ -7,7 +7,9 @@ pub struct Nested;
pub enum ExternallyTagged {
Flatten {
#[serde(flatten)]
#[allow(dead_code)]
nested: Nested,
#[allow(dead_code)]
string: &'static str,
},
}
@@ -17,7 +19,9 @@ pub enum ExternallyTagged {
pub enum InternallyTagged {
Flatten {
#[serde(flatten)]
#[allow(dead_code)]
nested: Nested,
#[allow(dead_code)]
string: &'static str,
},
}
@@ -27,7 +31,9 @@ pub enum InternallyTagged {
pub enum AdjacentlyTagged {
Flatten {
#[serde(flatten)]
#[allow(dead_code)]
nested: Nested,
#[allow(dead_code)]
string: &'static str,
},
}
@@ -37,7 +43,9 @@ pub enum AdjacentlyTagged {
pub enum UntaggedWorkaround {
Flatten {
#[serde(flatten)]
#[allow(dead_code)]
nested: Nested,
#[allow(dead_code)]
string: &'static str,
},
}
+41
View File
@@ -0,0 +1,41 @@
use serde_derive::{Serialize, Deserialize};
use serde_test::{assert_tokens, Token};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
enum Enum {
Simple {
a: i32,
},
Flatten {
#[serde(flatten)]
flatten: (),
a: i32,
},
}
#[test]
fn simple_variant() {
assert_tokens(
&Enum::Simple { a: 42 },
&[
Token::StructVariant { name: "Enum", variant: "Simple", len: 1 },
Token::Str("a"),
Token::I32(42),
Token::StructVariantEnd,
]
);
}
#[test]
fn flatten_variant() {
assert_tokens(
&Enum::Flatten { flatten: (), a: 42 },
&[
Token::NewtypeVariant { name: "Enum", variant: "Flatten" },
Token::Map { len: None },
Token::Str("a"),
Token::I32(42),
Token::MapEnd,
]
);
}
+18
View File
@@ -0,0 +1,18 @@
#![allow(dead_code)] // we do not read enum fields
use serde_derive::Deserialize;
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub enum A {
B {
c: String,
},
D {
#[serde(flatten)]
e: E,
},
}
#[derive(Deserialize)]
pub struct E {}
+460 -327
View File
@@ -114,42 +114,6 @@ struct CollectOther {
extra: HashMap<String, u32>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructEnumWrapper {
#[serde(flatten)]
data: FlattenStructEnum,
#[serde(flatten)]
extra: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum FlattenStructEnum {
InsertInteger { index: u32, value: u32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumWrapper {
outer: u32,
#[serde(flatten)]
data: FlattenStructTagContentEnumNewtype,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
enum FlattenStructTagContentEnum {
InsertInteger { index: u32, value: u32 },
NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtypeVariant {
value: u32,
}
#[test]
fn test_default_struct() {
assert_de_tokens(
@@ -641,7 +605,7 @@ fn test_unknown_field_rename_struct() {
Token::Str("a4"),
Token::I32(3),
],
"unknown field `a4`, expected one of `a1`, `a3`, `a2`, `a5`, `a6`",
"unknown field `a4`, expected one of `a1`, `a2`, `a3`, `a5`, `a6`",
);
}
@@ -835,7 +799,7 @@ fn test_unknown_field_rename_enum() {
Token::Str("d"),
Token::I8(2),
],
"unknown field `d`, expected one of `a`, `c`, `b`, `e`, `f`",
"unknown field `d`, expected one of `a`, `b`, `c`, `e`, `f`",
);
}
@@ -1643,149 +1607,6 @@ fn test_collect_other() {
);
}
#[test]
fn test_flatten_struct_enum() {
let mut extra = HashMap::new();
extra.insert("extra_key".into(), "extra value".into());
let change_request = FlattenStructEnumWrapper {
data: FlattenStructEnum::InsertInteger {
index: 0,
value: 42,
},
extra,
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("insert_integer"),
Token::Map { len: None },
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::MapEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("insert_integer"),
Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_struct_tag_content_enum() {
let change_request = FlattenStructTagContentEnumWrapper {
outer: 42,
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
index: 0,
value: 42,
}),
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("insert_integer"),
Token::Str("value"),
Token::Map { len: None },
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::MapEnd,
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("insert_integer"),
Token::Str("value"),
Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_struct_tag_content_enum_newtype() {
let change_request = FlattenStructTagContentEnumWrapper {
outer: 42,
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
FlattenStructTagContentEnumNewtypeVariant { value: 23 },
)),
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("newtype_variant"),
Token::Str("value"),
Token::Map { len: None },
Token::Str("value"),
Token::U32(23),
Token::MapEnd,
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("newtype_variant"),
Token::Str("value"),
Token::Struct {
len: 1,
name: "FlattenStructTagContentEnumNewtypeVariant",
},
Token::Str("value"),
Token::U32(23),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_unknown_field_in_flatten() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -2142,86 +1963,6 @@ fn test_lifetime_propagation_for_flatten() {
);
}
#[test]
fn test_flatten_enum_newtype() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
flat: E,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum E {
Q(HashMap<String, String>),
}
let e = E::Q({
let mut map = HashMap::new();
map.insert("k".to_owned(), "v".to_owned());
map
});
let s = S { flat: e };
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("Q"),
Token::Map { len: Some(1) },
Token::Str("k"),
Token::Str("v"),
Token::MapEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_internally_tagged() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
let s = S {
x: X::B { b: 1 },
y: Y::D { d: 2 },
};
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn test_externally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -2367,7 +2108,10 @@ fn test_adjacently_tagged_enum_bytes() {
len: 2,
},
Token::Str("t"),
Token::Str("A"),
Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Str("c"),
Token::Struct { name: "A", len: 1 },
Token::Str("a"),
@@ -2385,7 +2129,10 @@ fn test_adjacently_tagged_enum_bytes() {
len: 2,
},
Token::Bytes(b"t"),
Token::Str("A"),
Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Bytes(b"c"),
Token::Struct { name: "A", len: 1 },
Token::Str("a"),
@@ -2426,7 +2173,10 @@ fn test_adjacently_tagged_enum_containing_flatten() {
len: 2,
},
Token::Str("t"),
Token::Str("A"),
Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Str("c"),
Token::Map { len: None },
Token::Str("a"),
@@ -2630,35 +2380,118 @@ fn test_partially_untagged_enum_desugared() {
);
}
// Regression test for https://github.com/serde-rs/serde/issues/1904
#[test]
fn test_flatten_untagged_enum() {
fn test_enum_tuple_and_struct_with_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Outer {
#[serde(flatten)]
inner: Inner,
enum Outer {
Tuple(f64, i32),
Flatten {
#[serde(flatten)]
nested: Nested,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Inner {
Variant { a: i32 },
struct Nested {
a: i32,
b: i32,
}
let data = Outer {
inner: Inner::Variant { a: 0 },
};
assert_tokens(
&data,
&Outer::Tuple(1.2, 3),
&[
Token::TupleVariant {
name: "Outer",
variant: "Tuple",
len: 2,
},
Token::F64(1.2),
Token::I32(3),
Token::TupleVariantEnd,
],
);
assert_tokens(
&Outer::Flatten {
nested: Nested { a: 1, b: 2 },
},
&[
Token::NewtypeVariant {
name: "Outer",
variant: "Flatten",
},
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::I32(1),
Token::Str("b"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn test_partially_untagged_internally_tagged_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t")]
enum Data {
A,
B,
#[serde(untagged)]
Var(u32),
}
let data = Data::A;
assert_de_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("t"),
Token::Str("A"),
Token::MapEnd,
],
);
let data = Data::Var(42);
assert_de_tokens(&data, &[Token::U32(42)]);
// TODO test error output
}
#[test]
fn test_partially_untagged_adjacently_tagged_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t", content = "c")]
enum Data {
A(u32),
B,
#[serde(untagged)]
Var(u32),
}
let data = Data::A(7);
assert_de_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("t"),
Token::Str("A"),
Token::Str("c"),
Token::U32(7),
Token::MapEnd,
],
);
let data = Data::Var(42);
assert_de_tokens(&data, &[Token::U32(42)]);
// TODO test error output
}
#[test]
fn test_flatten_option() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -2815,48 +2648,6 @@ fn test_internally_tagged_unit_enum_with_unknown_fields() {
);
}
#[test]
fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
#[derive(Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A,
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
B { c: u32 },
}
let s = S {
x: X::A,
y: Y::B { c: 0 },
};
assert_de_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("A"),
Token::Str("typeY"),
Token::Str("B"),
Token::Str("c"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_any_after_flatten_struct() {
#[derive(PartialEq, Debug)]
@@ -3040,7 +2831,7 @@ fn test_expecting_message_externally_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>(
&[Token::Enum { name: "Enum" }, Token::Unit],
r#"invalid type: unit value, expected variant identifier"#,
"invalid type: unit value, expected variant identifier",
);
}
@@ -3061,7 +2852,7 @@ fn test_expecting_message_internally_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>(
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
r#"invalid type: unit value, expected variant identifier"#,
"invalid type: unit value, expected variant identifier",
);
}
@@ -3087,7 +2878,7 @@ fn test_expecting_message_adjacently_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>(
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
r#"invalid type: unit value, expected variant identifier"#,
"invalid type: unit value, expected variant of enum Enum",
);
}
@@ -3100,7 +2891,7 @@ fn test_expecting_message_untagged_tagged_enum() {
Untagged,
}
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], "something strange...");
}
#[test]
@@ -3121,7 +2912,7 @@ fn test_expecting_message_identifier_enum() {
assert_de_tokens_error::<FieldEnum>(
&[Token::Unit],
r#"invalid type: unit value, expected something strange..."#,
"invalid type: unit value, expected something strange...",
);
assert_de_tokens_error::<FieldEnum>(
@@ -3130,12 +2921,12 @@ fn test_expecting_message_identifier_enum() {
Token::Str("Unknown"),
Token::None,
],
r#"invalid type: map, expected something strange..."#,
"invalid type: map, expected something strange...",
);
assert_de_tokens_error::<VariantEnum>(
&[Token::Unit],
r#"invalid type: unit value, expected something strange..."#,
"invalid type: unit value, expected something strange...",
);
assert_de_tokens_error::<VariantEnum>(
@@ -3146,6 +2937,348 @@ fn test_expecting_message_identifier_enum() {
Token::Str("Unknown"),
Token::None,
],
r#"invalid type: map, expected something strange..."#,
"invalid type: map, expected something strange...",
);
}
mod flatten {
use super::*;
mod enum_ {
use super::*;
mod externally_tagged {
use super::*;
use std::iter::FromIterator;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
data: Enum,
#[serde(flatten)]
extra: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum Enum {
Newtype(HashMap<String, String>),
Tuple(u32, u32),
Struct { index: u32, value: u32 },
}
#[test]
fn newtype() {
assert_tokens(
&Flatten {
data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])),
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Newtype"), // variant
Token::Map { len: Some(1) },
Token::Str("key"),
Token::Str("value"),
Token::MapEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
// Content::Seq case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn tuple() {
assert_tokens(
&Flatten {
data: Enum::Tuple(0, 42),
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Tuple"), // variant
Token::Seq { len: Some(2) },
Token::U32(0),
Token::U32(42),
Token::SeqEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Seq case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn struct_from_seq() {
assert_de_tokens(
&Flatten {
data: Enum::Struct {
index: 0,
value: 42,
},
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Struct"), // variant
Token::Seq { len: Some(2) },
Token::U32(0), // index
Token::U32(42), // value
Token::SeqEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Map case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn struct_from_map() {
assert_tokens(
&Flatten {
data: Enum::Struct {
index: 0,
value: 42,
},
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Struct"), // variant
Token::Struct {
len: 2,
name: "Struct",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
}
mod adjacently_tagged {
use super::*;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
outer: u32,
#[serde(flatten)]
data: NewtypeWrapper,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NewtypeWrapper(pub Enum);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "tag", content = "content")]
enum Enum {
Newtype(NewtypeVariant),
Struct { index: u32, value: u32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NewtypeVariant {
value: u32,
}
#[test]
fn struct_() {
assert_tokens(
&Flatten {
outer: 42,
data: NewtypeWrapper(Enum::Struct {
index: 0,
value: 42,
}),
},
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("tag"),
Token::UnitVariant {
name: "Enum",
variant: "Struct",
},
Token::Str("content"),
Token::Struct {
len: 2,
name: "Struct",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn newtype() {
assert_tokens(
&Flatten {
outer: 42,
data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })),
},
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("tag"),
Token::UnitVariant {
name: "Enum",
variant: "Newtype",
},
Token::Str("content"),
Token::Struct {
len: 1,
name: "NewtypeVariant",
},
Token::Str("value"),
Token::U32(23),
Token::StructEnd,
Token::MapEnd,
],
);
}
}
mod internally_tagged {
use super::*;
#[test]
fn structs() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
assert_tokens(
&Flatten {
x: X::B { b: 1 },
y: Y::D { d: 2 },
},
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn unit_enum_with_unknown_fields() {
#[derive(Debug, PartialEq, Deserialize)]
struct Flatten {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "typeX")]
enum X {
A,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "typeY")]
enum Y {
B { c: u32 },
}
assert_de_tokens(
&Flatten {
x: X::A,
y: Y::B { c: 0 },
},
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("A"),
Token::Str("typeY"),
Token::Str("B"),
Token::Str("c"),
Token::I32(0),
Token::MapEnd,
],
);
}
}
mod untagged {
use super::*;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
data: Enum,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum Enum {
Struct { a: i32 },
}
#[test]
fn struct_() {
assert_tokens(
&Flatten {
data: Enum::Struct { a: 0 },
},
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::MapEnd,
],
);
}
}
}
}
+2 -2
View File
@@ -162,7 +162,7 @@ fn test_cow() {
#[test]
fn test_lifetimes() {
#[derive(Deserialize)]
struct Cows<'a, 'b> {
pub struct Cows<'a, 'b> {
_copied: Cow<'a, str>,
#[serde(borrow)]
@@ -178,7 +178,7 @@ fn test_lifetimes() {
}
#[derive(Deserialize)]
struct Wrap<'a, 'b> {
pub struct Wrap<'a, 'b> {
#[serde(borrow = "'b")]
_cows: Cows<'a, 'b>,
}
+100 -2
View File
@@ -11,6 +11,7 @@
#![cfg_attr(feature = "unstable", feature(never_type))]
use fnv::FnvHasher;
use serde::de::value::{F32Deserializer, F64Deserializer};
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, Configure, Token};
@@ -22,7 +23,7 @@ use std::iter;
use std::net;
use std::num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping,
};
use std::ops::Bound;
use std::path::{Path, PathBuf};
@@ -92,7 +93,7 @@ struct StructSkipDefault {
#[derive(PartialEq, Debug, Deserialize)]
#[serde(default)]
struct StructSkipDefaultGeneric<T> {
pub struct StructSkipDefaultGeneric<T> {
#[serde(skip_deserializing)]
t: T,
}
@@ -832,6 +833,26 @@ fn test_f64() {
test(1.11, &[Token::F64(1.11)]);
}
#[test]
fn test_nan() {
let f32_deserializer = F32Deserializer::<serde::de::value::Error>::new;
let f64_deserializer = F64Deserializer::<serde::de::value::Error>::new;
let pos_f32_nan = f32_deserializer(f32::NAN.copysign(1.0));
let pos_f64_nan = f64_deserializer(f64::NAN.copysign(1.0));
assert!(f32::deserialize(pos_f32_nan).unwrap().is_sign_positive());
assert!(f32::deserialize(pos_f64_nan).unwrap().is_sign_positive());
assert!(f64::deserialize(pos_f32_nan).unwrap().is_sign_positive());
assert!(f64::deserialize(pos_f64_nan).unwrap().is_sign_positive());
let neg_f32_nan = f32_deserializer(f32::NAN.copysign(-1.0));
let neg_f64_nan = f64_deserializer(f64::NAN.copysign(-1.0));
assert!(f32::deserialize(neg_f32_nan).unwrap().is_sign_negative());
assert!(f32::deserialize(neg_f64_nan).unwrap().is_sign_negative());
assert!(f64::deserialize(neg_f32_nan).unwrap().is_sign_negative());
assert!(f64::deserialize(neg_f64_nan).unwrap().is_sign_negative());
}
#[test]
fn test_char() {
test('a', &[Token::Char('a')]);
@@ -1877,6 +1898,46 @@ fn test_range_inclusive() {
);
}
#[test]
fn test_range_from() {
test(
1u32..,
&[
Token::Struct {
name: "RangeFrom",
len: 1,
},
Token::Str("start"),
Token::U32(1),
Token::StructEnd,
],
);
test(
1u32..,
&[Token::Seq { len: Some(1) }, Token::U32(1), Token::SeqEnd],
);
}
#[test]
fn test_range_to() {
test(
..2u32,
&[
Token::Struct {
name: "RangeTo",
len: 1,
},
Token::Str("end"),
Token::U32(2),
Token::StructEnd,
],
);
test(
..2u32,
&[Token::Seq { len: Some(1) }, Token::U32(2), Token::SeqEnd],
);
}
#[test]
fn test_bound() {
test(
@@ -2004,6 +2065,43 @@ fn test_wrapping() {
test(Wrapping(1usize), &[Token::U64(1)]);
}
#[test]
fn test_saturating() {
test(Saturating(1usize), &[Token::U32(1)]);
test(Saturating(1usize), &[Token::U64(1)]);
test(Saturating(0u8), &[Token::I8(0)]);
test(Saturating(0u16), &[Token::I16(0)]);
// saturate input values at the minimum or maximum value
test(Saturating(u8::MAX), &[Token::U16(u16::MAX)]);
test(Saturating(u8::MAX), &[Token::U16(u8::MAX as u16 + 1)]);
test(Saturating(u16::MAX), &[Token::U32(u32::MAX)]);
test(Saturating(u32::MAX), &[Token::U64(u64::MAX)]);
test(Saturating(u8::MIN), &[Token::I8(i8::MIN)]);
test(Saturating(u16::MIN), &[Token::I16(i16::MIN)]);
test(Saturating(u32::MIN), &[Token::I32(i32::MIN)]);
test(Saturating(i8::MIN), &[Token::I16(i16::MIN)]);
test(Saturating(i16::MIN), &[Token::I32(i32::MIN)]);
test(Saturating(i32::MIN), &[Token::I64(i64::MIN)]);
test(Saturating(u8::MIN), &[Token::I8(-1)]);
test(Saturating(u16::MIN), &[Token::I16(-1)]);
#[cfg(target_pointer_width = "64")]
{
test(Saturating(usize::MIN), &[Token::U64(u64::MIN)]);
test(Saturating(usize::MAX), &[Token::U64(u64::MAX)]);
test(Saturating(isize::MIN), &[Token::I64(i64::MIN)]);
test(Saturating(isize::MAX), &[Token::I64(i64::MAX)]);
test(Saturating(0usize), &[Token::I64(i64::MIN)]);
test(
Saturating(9_223_372_036_854_775_807usize),
&[Token::I64(i64::MAX)],
);
}
}
#[test]
fn test_rc_dst() {
test(Rc::<str>::from("s"), &[Token::Str("s")]);
+14 -7
View File
@@ -1434,7 +1434,15 @@ fn test_number_from_string() {
fn test_integer_from_float() {
assert_de_tokens_error::<isize>(
&[Token::F32(0.0)],
"invalid type: floating point `0`, expected isize",
"invalid type: floating point `0.0`, expected isize",
);
}
#[test]
fn test_nan_no_decimal_point() {
assert_de_tokens_error::<isize>(
&[Token::F32(f32::NAN)],
"invalid type: floating point `NaN`, expected isize",
);
}
@@ -1459,7 +1467,7 @@ fn test_duration_overflow_seq() {
assert_de_tokens_error::<Duration>(
&[
Token::Seq { len: Some(2) },
Token::U64(u64::max_value()),
Token::U64(u64::MAX),
Token::U32(1_000_000_000),
Token::SeqEnd,
],
@@ -1476,7 +1484,7 @@ fn test_duration_overflow_struct() {
len: 2,
},
Token::Str("secs"),
Token::U64(u64::max_value()),
Token::U64(u64::MAX),
Token::Str("nanos"),
Token::U32(1_000_000_000),
Token::StructEnd,
@@ -1490,7 +1498,7 @@ fn test_systemtime_overflow_seq() {
assert_de_tokens_error::<SystemTime>(
&[
Token::Seq { len: Some(2) },
Token::U64(u64::max_value()),
Token::U64(u64::MAX),
Token::U32(1_000_000_000),
Token::SeqEnd,
],
@@ -1507,7 +1515,7 @@ fn test_systemtime_overflow_struct() {
len: 2,
},
Token::Str("secs_since_epoch"),
Token::U64(u64::max_value()),
Token::U64(u64::MAX),
Token::Str("nanos_since_epoch"),
Token::U32(1_000_000_000),
Token::StructEnd,
@@ -1516,13 +1524,12 @@ fn test_systemtime_overflow_struct() {
);
}
#[cfg(systemtime_checked_add)]
#[test]
fn test_systemtime_overflow() {
assert_de_tokens_error::<SystemTime>(
&[
Token::Seq { len: Some(2) },
Token::U64(u64::max_value()),
Token::U64(u64::MAX),
Token::U32(0),
Token::SeqEnd,
],
+77 -54
View File
@@ -4,6 +4,7 @@
#![deny(warnings)]
#![allow(
confusable_idents,
unknown_lints,
mixed_script_confusables,
clippy::derive_partial_eq_without_eq,
@@ -19,6 +20,7 @@
clippy::trivially_copy_pass_by_ref,
clippy::type_repetition_in_bounds
)]
#![deny(clippy::collection_is_never_read)]
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
use serde::ser::{Serialize, Serializer};
@@ -287,60 +289,60 @@ fn test_gen() {
assert::<EmptyEnumVariant>();
#[derive(Serialize, Deserialize)]
struct NonAsciiIdents {
pub struct NonAsciiIdents {
σ: f64,
}
#[derive(Serialize, Deserialize)]
struct EmptyBraced {}
pub struct EmptyBraced {}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct EmptyBracedDenyUnknown {}
pub struct EmptyBracedDenyUnknown {}
#[derive(Serialize, Deserialize)]
struct BracedSkipAll {
pub struct BracedSkipAll {
#[serde(skip_deserializing)]
f: u8,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct BracedSkipAllDenyUnknown {
pub struct BracedSkipAllDenyUnknown {
#[serde(skip_deserializing)]
f: u8,
}
#[derive(Serialize, Deserialize)]
struct EmptyTuple();
pub struct EmptyTuple();
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct EmptyTupleDenyUnknown();
pub struct EmptyTupleDenyUnknown();
#[derive(Serialize, Deserialize)]
struct TupleSkipAll(#[serde(skip_deserializing)] u8);
pub struct TupleSkipAll(#[serde(skip_deserializing)] u8);
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
pub struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
#[derive(Serialize, Deserialize)]
enum EmptyEnum {}
pub enum EmptyEnum {}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
enum EmptyEnumDenyUnknown {}
pub enum EmptyEnumDenyUnknown {}
#[derive(Serialize, Deserialize)]
enum EnumSkipAll {
pub enum EnumSkipAll {
#[serde(skip_deserializing)]
#[allow(dead_code)]
Variant,
}
#[derive(Serialize, Deserialize)]
enum EmptyVariants {
pub enum EmptyVariants {
Braced {},
Tuple(),
BracedSkip {
@@ -352,7 +354,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
enum EmptyVariantsDenyUnknown {
pub enum EmptyVariantsDenyUnknown {
Braced {},
Tuple(),
BracedSkip {
@@ -364,21 +366,21 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct UnitDenyUnknown;
pub struct UnitDenyUnknown;
#[derive(Serialize, Deserialize)]
struct EmptyArray {
pub struct EmptyArray {
empty: [X; 0],
}
enum Or<A, B> {
pub enum Or<A, B> {
A(A),
B(B),
}
#[derive(Serialize, Deserialize)]
#[serde(untagged, remote = "Or")]
enum OrDef<A, B> {
pub enum OrDef<A, B> {
A(A),
B(B),
}
@@ -390,7 +392,7 @@ fn test_gen() {
struct StrDef<'a>(&'a str);
#[derive(Serialize, Deserialize)]
struct Remote<'a> {
pub struct Remote<'a> {
#[serde(with = "OrDef")]
or: Or<u8, bool>,
#[serde(borrow, with = "StrDef")]
@@ -398,7 +400,7 @@ fn test_gen() {
}
#[derive(Serialize, Deserialize)]
enum BorrowVariant<'a> {
pub enum BorrowVariant<'a> {
#[serde(borrow, with = "StrDef")]
S(Str<'a>),
}
@@ -415,14 +417,14 @@ fn test_gen() {
// This would not work if SDef::serialize / deserialize are private.
#[derive(Serialize, Deserialize)]
struct RemoteVisibility {
pub struct RemoteVisibility {
#[serde(with = "vis::SDef")]
s: vis::S,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "Self")]
struct RemoteSelf;
pub struct RemoteSelf;
#[derive(Serialize, Deserialize)]
enum ExternallyTaggedVariantWith {
@@ -547,25 +549,25 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct FlattenDenyUnknown<T> {
pub struct FlattenDenyUnknown<T> {
#[serde(flatten)]
t: T,
}
#[derive(Serialize, Deserialize)]
struct StaticStrStruct<'a> {
pub struct StaticStrStruct<'a> {
a: &'a str,
b: &'static str,
}
#[derive(Serialize, Deserialize)]
struct StaticStrTupleStruct<'a>(&'a str, &'static str);
pub struct StaticStrTupleStruct<'a>(&'a str, &'static str);
#[derive(Serialize, Deserialize)]
struct StaticStrNewtypeStruct(&'static str);
pub struct StaticStrNewtypeStruct(&'static str);
#[derive(Serialize, Deserialize)]
enum StaticStrEnum<'a> {
pub enum StaticStrEnum<'a> {
Struct { a: &'a str, b: &'static str },
Tuple(&'a str, &'static str),
Newtype(&'static str),
@@ -639,6 +641,7 @@ fn test_gen() {
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[allow(dead_code)]
struct Restricted {
pub(super) a: usize,
pub(in super::inner) b: usize,
@@ -648,7 +651,7 @@ fn test_gen() {
#[derive(Deserialize)]
#[serde(tag = "t", content = "c")]
enum AdjacentlyTaggedVoid {}
pub enum AdjacentlyTaggedVoid {}
#[derive(Serialize, Deserialize)]
enum SkippedVariant<T> {
@@ -661,14 +664,13 @@ fn test_gen() {
assert::<SkippedVariant<X>>();
#[derive(Deserialize)]
struct ImplicitlyBorrowedOption<'a> {
#[allow(dead_code)]
pub struct ImplicitlyBorrowedOption<'a> {
option: std::option::Option<&'a str>,
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum UntaggedNewtypeVariantWith {
pub enum UntaggedNewtypeVariantWith {
Newtype(
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
@@ -678,7 +680,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
struct TransparentWith {
pub struct TransparentWith {
#[serde(serialize_with = "ser_x")]
#[serde(deserialize_with = "de_x")]
x: X,
@@ -686,41 +688,63 @@ fn test_gen() {
#[derive(Deserialize)]
#[serde(untagged)]
enum UntaggedWithBorrow<'a> {
Single(#[serde(borrow)] RelObject<'a>),
Many(#[serde(borrow)] Vec<RelObject<'a>>),
pub enum UntaggedWithBorrow<'a> {
Single(
#[serde(borrow)]
#[allow(dead_code)]
RelObject<'a>,
),
Many(
#[serde(borrow)]
#[allow(dead_code)]
Vec<RelObject<'a>>,
),
}
#[derive(Deserialize)]
struct RelObject<'a> {
#[allow(dead_code)]
pub struct RelObject<'a> {
ty: &'a str,
#[allow(dead_code)]
id: String,
}
#[derive(Serialize, Deserialize)]
struct FlattenSkipSerializing<T> {
pub struct FlattenSkipSerializing<T> {
#[serde(flatten, skip_serializing)]
#[allow(dead_code)]
flat: T,
}
#[derive(Serialize, Deserialize)]
struct FlattenSkipSerializingIf<T> {
pub struct FlattenSkipSerializingIf<T> {
#[serde(flatten, skip_serializing_if = "StdOption::is_none")]
flat: StdOption<T>,
}
#[allow(clippy::collection_is_never_read)] // FIXME
const _: () = {
#[derive(Serialize, Deserialize)]
pub struct FlattenSkipDeserializing<T> {
#[serde(flatten, skip_deserializing)]
flat: T,
}
};
#[derive(Serialize, Deserialize)]
struct FlattenSkipDeserializing<T> {
#[serde(flatten, skip_deserializing)]
flat: T,
#[serde(untagged)]
pub enum Inner<T> {
Builder {
s: T,
#[serde(flatten)]
o: T,
},
Default {
s: T,
},
}
// https://github.com/serde-rs/serde/issues/1804
#[derive(Serialize, Deserialize)]
enum Message {
pub enum Message {
#[serde(skip)]
#[allow(dead_code)]
String(String),
@@ -730,6 +754,7 @@ fn test_gen() {
#[derive(Serialize)]
#[repr(packed)]
#[allow(dead_code)]
struct Packed {
x: u8,
y: u16,
@@ -738,8 +763,7 @@ fn test_gen() {
macro_rules! deriving {
($field:ty) => {
#[derive(Deserialize)]
struct MacroRules<'a> {
#[allow(dead_code)]
pub struct MacroRules<'a> {
field: $field,
}
};
@@ -754,21 +778,20 @@ fn test_gen() {
}
#[derive(Deserialize)]
struct BorrowLifetimeInsideMacro<'a> {
pub struct BorrowLifetimeInsideMacro<'a> {
#[serde(borrow = "'a")]
#[allow(dead_code)]
f: mac!(Cow<'a, str>),
pub f: mac!(Cow<'a, str>),
}
#[derive(Serialize)]
struct Struct {
pub struct Struct {
#[serde(serialize_with = "vec_first_element")]
vec: Vec<Self>,
pub vec: Vec<Self>,
}
#[derive(Deserialize)]
#[serde(bound(deserialize = "[&'de str; N]: Copy"))]
struct GenericUnitStruct<const N: usize>;
pub struct GenericUnitStruct<const N: usize>;
}
//////////////////////////////////////////////////////////////////////////
@@ -843,7 +866,7 @@ pub fn is_zero(n: &u8) -> bool {
*n == 0
}
fn vec_first_element<T, S>(vec: &Vec<T>, serializer: S) -> StdResult<S::Ok, S::Error>
fn vec_first_element<T, S>(vec: &[T], serializer: S) -> StdResult<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
@@ -855,7 +878,7 @@ where
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "tag")]
enum InternallyTagged {
pub enum InternallyTagged {
#[serde(deserialize_with = "deserialize_generic")]
Unit,
+158 -58
View File
@@ -3,86 +3,186 @@
#![allow(clippy::derive_partial_eq_without_eq)]
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, Token};
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
mod variant_identifier {
use super::*;
#[test]
fn test_variant_identifier() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(variant_identifier)]
enum V {
Aaa,
#[serde(alias = "Ccc", alias = "Ddd")]
Bbb,
}
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
#[test]
fn variant1() {
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
}
#[test]
fn aliases() {
assert_de_tokens(&V::Bbb, &[Token::U8(1)]);
assert_de_tokens(&V::Bbb, &[Token::U16(1)]);
assert_de_tokens(&V::Bbb, &[Token::U32(1)]);
assert_de_tokens(&V::Bbb, &[Token::U64(1)]);
assert_de_tokens(&V::Bbb, &[Token::Str("Bbb")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Bbb")]);
assert_de_tokens(&V::Bbb, &[Token::Str("Ccc")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ccc")]);
assert_de_tokens(&V::Bbb, &[Token::Str("Ddd")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ddd")]);
}
#[test]
fn unknown() {
assert_de_tokens_error::<V>(
&[Token::U8(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U16(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U32(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U64(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::Str("Unknown")],
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
);
assert_de_tokens_error::<V>(
&[Token::Bytes(b"Unknown")],
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
);
}
}
#[test]
fn test_field_identifier() {
mod field_identifier {
use super::*;
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
#[serde(alias = "ccc", alias = "ddd")]
Bbb,
}
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
}
#[test]
fn test_unit_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
#[serde(other)]
Other,
#[test]
fn field1() {
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
}
assert_de_tokens(&F::Other, &[Token::U8(42)]);
assert_de_tokens(&F::Other, &[Token::U16(42)]);
assert_de_tokens(&F::Other, &[Token::U32(42)]);
assert_de_tokens(&F::Other, &[Token::U64(42)]);
assert_de_tokens(&F::Other, &[Token::Str("x")]);
}
#[test]
fn aliases() {
assert_de_tokens(&F::Bbb, &[Token::U8(1)]);
assert_de_tokens(&F::Bbb, &[Token::U16(1)]);
assert_de_tokens(&F::Bbb, &[Token::U32(1)]);
assert_de_tokens(&F::Bbb, &[Token::U64(1)]);
#[test]
fn test_newtype_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
Other(String),
assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]);
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]);
assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]);
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]);
assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]);
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]);
}
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
#[test]
fn test_newtype_fallthrough_generic() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F<T> {
Aaa,
Bbb,
Other(T),
#[test]
fn unknown() {
assert_de_tokens_error::<F>(
&[Token::U8(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U16(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U32(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U64(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::Str("unknown")],
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
);
assert_de_tokens_error::<F>(
&[Token::Bytes(b"unknown")],
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
);
}
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
#[test]
fn unit_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
#[serde(other)]
Other,
}
assert_de_tokens(&F::Other, &[Token::U8(42)]);
assert_de_tokens(&F::Other, &[Token::U16(42)]);
assert_de_tokens(&F::Other, &[Token::U32(42)]);
assert_de_tokens(&F::Other, &[Token::U64(42)]);
assert_de_tokens(&F::Other, &[Token::Str("x")]);
}
#[test]
fn newtype_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
Other(String),
}
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
#[test]
fn newtype_fallthrough_generic() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F<T> {
Aaa,
Bbb,
Other(T),
}
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
}
+212 -19
View File
@@ -472,7 +472,10 @@ fn test_adjacently_tagged_newtype_struct() {
},
Token::U32(5),
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "E",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -811,6 +814,100 @@ fn test_internally_tagged_enum() {
);
}
#[test]
fn test_internally_tagged_enum_with_untagged_variant() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind")]
enum InternallyTagged {
Tagged {
a: u8,
},
#[serde(untagged)]
Untagged {
kind: String,
b: u8,
},
}
assert_de_tokens(
&InternallyTagged::Tagged { a: 1 },
&[
Token::Map { len: Some(2) },
Token::Str("kind"),
Token::Str("Tagged"),
Token::Str("a"),
Token::U8(1),
Token::MapEnd,
],
);
assert_tokens(
&InternallyTagged::Tagged { a: 1 },
&[
Token::Struct {
name: "InternallyTagged",
len: 2,
},
Token::Str("kind"),
Token::Str("Tagged"),
Token::Str("a"),
Token::U8(1),
Token::StructEnd,
],
);
assert_de_tokens(
&InternallyTagged::Untagged {
kind: "Foo".to_owned(),
b: 2,
},
&[
Token::Map { len: Some(2) },
Token::Str("kind"),
Token::Str("Foo"),
Token::Str("b"),
Token::U8(2),
Token::MapEnd,
],
);
assert_tokens(
&InternallyTagged::Untagged {
kind: "Foo".to_owned(),
b: 2,
},
&[
Token::Struct {
name: "InternallyTagged",
len: 2,
},
Token::Str("kind"),
Token::Str("Foo"),
Token::Str("b"),
Token::U8(2),
Token::StructEnd,
],
);
assert_tokens(
&InternallyTagged::Untagged {
kind: "Tagged".to_owned(),
b: 2,
},
&[
Token::Struct {
name: "InternallyTagged",
len: 2,
},
Token::Str("kind"),
Token::Str("Tagged"),
Token::Str("b"),
Token::U8(2),
Token::StructEnd,
],
);
}
#[test]
fn test_internally_tagged_bytes() {
#[derive(Debug, PartialEq, Deserialize)]
@@ -984,6 +1081,15 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
Log { level: Level },
}
assert_de_tokens(
&Level::Info,
&[
Token::Enum { name: "Level" },
Token::BorrowedStr("Info"),
Token::Unit,
],
);
assert_de_tokens(
&Message::Log { level: Level::Info },
&[
@@ -994,7 +1100,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
Token::Str("action"),
Token::Str("Log"),
Token::Str("level"),
Token::Enum { name: "Level" },
Token::BorrowedStr("Info"),
Token::Unit,
Token::StructEnd,
],
);
@@ -1006,7 +1114,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
Token::Str("action"),
Token::Str("Log"),
Token::Str("level"),
Token::Enum { name: "Level" },
Token::BorrowedStr("Info"),
Token::Unit,
Token::MapEnd,
],
);
@@ -1016,7 +1126,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
&[
Token::Seq { len: Some(2) },
Token::Str("Log"),
Token::Enum { name: "Level" },
Token::BorrowedStr("Info"),
Token::Unit,
Token::SeqEnd,
],
);
@@ -1066,7 +1178,10 @@ fn test_adjacently_tagged_enum() {
len: 1,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd,
],
);
@@ -1080,7 +1195,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd,
],
);
@@ -1094,7 +1212,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"),
Token::Unit,
Token::StructEnd,
@@ -1112,7 +1233,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("c"),
Token::Unit,
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd,
],
);
@@ -1128,7 +1252,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("f"),
Token::Unit,
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("g"),
Token::Unit,
Token::Str("c"),
@@ -1148,7 +1275,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::Str("c"),
Token::U8(1),
Token::StructEnd,
@@ -1166,7 +1296,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("c"),
Token::U8(1),
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1180,7 +1313,10 @@ fn test_adjacently_tagged_enum() {
len: 1,
},
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1194,7 +1330,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Tuple"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Tuple",
},
Token::Str("c"),
Token::Tuple { len: 2 },
Token::U8(1),
@@ -1218,7 +1357,10 @@ fn test_adjacently_tagged_enum() {
Token::U8(1),
Token::TupleEnd,
Token::Str("t"),
Token::Str("Tuple"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Tuple",
},
Token::StructEnd,
],
);
@@ -1232,7 +1374,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Struct"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Struct",
},
Token::Str("c"),
Token::Struct {
name: "Struct",
@@ -1262,7 +1407,10 @@ fn test_adjacently_tagged_enum() {
Token::U8(1),
Token::StructEnd,
Token::Str("t"),
Token::Str("Struct"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Struct",
},
Token::StructEnd,
],
);
@@ -1278,7 +1426,10 @@ fn test_adjacently_tagged_enum() {
Token::U64(1), // content field
Token::U8(1),
Token::U64(0), // tag field
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1294,7 +1445,10 @@ fn test_adjacently_tagged_enum() {
Token::Bytes(b"c"),
Token::U8(1),
Token::Bytes(b"t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1316,7 +1470,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"),
Token::Unit,
Token::StructEnd,
@@ -1330,7 +1487,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"),
Token::Unit,
Token::Str("h"),
@@ -1369,7 +1529,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::U64(3),
],
r#"invalid value: integer `3`, expected "t" or "c""#,
@@ -1429,6 +1592,9 @@ fn test_enum_in_internally_tagged_enum() {
],
);
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
// Content::Seq case
// via ContentDeserializer::deserialize_enum
assert_tokens(
&Outer::Inner(Inner::Tuple(1, 1)),
&[
@@ -1447,6 +1613,9 @@ fn test_enum_in_internally_tagged_enum() {
],
);
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Map case
// via ContentDeserializer::deserialize_enum
assert_tokens(
&Outer::Inner(Inner::Struct { f: 1 }),
&[
@@ -1464,6 +1633,23 @@ fn test_enum_in_internally_tagged_enum() {
Token::MapEnd,
],
);
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Seq case
// via ContentDeserializer::deserialize_enum
assert_de_tokens(
&Outer::Inner(Inner::Struct { f: 1 }),
&[
Token::Map { len: Some(2) },
Token::Str("type"),
Token::Str("Inner"),
Token::Str("Struct"),
Token::Seq { len: Some(1) },
Token::U8(1), // f
Token::SeqEnd,
Token::MapEnd,
],
);
}
#[test]
@@ -1542,7 +1728,10 @@ fn test_internally_tagged_struct_with_flattened_field() {
Token::Str("tag_struct"),
Token::Str("Struct"),
Token::Str("tag_enum"),
Token::Str("A"),
Token::UnitVariant {
name: "Enum",
variant: "A",
},
Token::Str("content"),
Token::U64(0),
Token::MapEnd,
@@ -2045,24 +2234,28 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() {
fn test_packed_struct_can_derive_serialize() {
#[derive(Copy, Clone, Serialize)]
#[repr(packed, C)]
#[allow(dead_code)]
struct PackedC {
t: f32,
}
#[derive(Copy, Clone, Serialize)]
#[repr(C, packed)]
#[allow(dead_code)]
struct CPacked {
t: f32,
}
#[derive(Copy, Clone, Serialize)]
#[repr(C, packed(2))]
#[allow(dead_code)]
struct CPacked2 {
t: f32,
}
#[derive(Copy, Clone, Serialize)]
#[repr(packed(2), C)]
#[allow(dead_code)]
struct Packed2C {
t: f32,
}
+35
View File
@@ -7,14 +7,17 @@ mod remote {
pub struct PrimitivePriv(u8);
#[allow(dead_code)]
pub struct PrimitivePub(pub u8);
pub struct NewtypePriv(Unit);
#[allow(dead_code)]
pub struct NewtypePub(pub Unit);
pub struct TuplePriv(u8, Unit);
#[allow(dead_code)]
pub struct TuplePub(pub u8, pub Unit);
pub struct StructPriv {
@@ -22,6 +25,7 @@ mod remote {
b: Unit,
}
#[allow(dead_code)]
pub struct StructPub {
pub a: u8,
pub b: Unit,
@@ -86,12 +90,14 @@ mod remote {
}
}
#[allow(dead_code)]
pub enum EnumGeneric<T> {
Variant(T),
}
}
#[derive(Serialize, Deserialize)]
#[allow(dead_code)]
struct Test {
#[serde(with = "UnitDef")]
unit: remote::Unit,
@@ -125,10 +131,14 @@ struct Test {
#[serde(with = "EnumConcrete")]
enum_concrete: remote::EnumGeneric<u8>,
#[serde(with = "ErrorKindDef")]
io_error_kind: ErrorKind,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::Unit")]
#[allow(dead_code)]
struct UnitDef;
#[derive(Serialize, Deserialize)]
@@ -137,6 +147,7 @@ struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePub")]
#[allow(dead_code)]
struct PrimitivePubDef(u8);
#[derive(Serialize, Deserialize)]
@@ -145,6 +156,7 @@ struct NewtypePrivDef(#[serde(getter = "remote::NewtypePriv::get", with = "UnitD
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePub")]
#[allow(dead_code)]
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
#[derive(Serialize, Deserialize)]
@@ -156,6 +168,7 @@ struct TuplePrivDef(
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePub")]
#[allow(dead_code)]
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
#[derive(Serialize, Deserialize)]
@@ -171,6 +184,7 @@ struct StructPrivDef {
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPub")]
#[allow(dead_code)]
struct StructPubDef {
a: u8,
@@ -187,16 +201,37 @@ struct StructGenericWithGetterDef<T> {
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructGeneric<u8>")]
#[allow(dead_code)]
struct StructConcrete {
value: u8,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::EnumGeneric<u8>")]
#[allow(dead_code)]
enum EnumConcrete {
Variant(u8),
}
#[derive(Debug)]
#[allow(dead_code)]
enum ErrorKind {
NotFound,
PermissionDenied,
#[allow(dead_code)]
ConnectionRefused,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "ErrorKind")]
#[non_exhaustive]
#[allow(dead_code)]
enum ErrorKindDef {
NotFound,
PermissionDenied,
// ...
}
impl From<PrimitivePrivDef> for remote::PrimitivePriv {
fn from(def: PrimitivePrivDef) -> Self {
remote::PrimitivePriv::new(def.0)
+2 -2
View File
@@ -41,7 +41,7 @@ fn test_self() {
}
#[derive(Deserialize, Serialize)]
struct Tuple(
pub struct Tuple(
Box<Self>,
Box<<Self as Trait>::Assoc>,
[(); Self::ASSOC],
@@ -60,7 +60,7 @@ fn test_self() {
}
#[derive(Deserialize, Serialize)]
enum Enum {
pub enum Enum {
Struct {
_f1: Box<Self>,
_f2: Box<<Self as Trait>::Assoc>,
+38 -1
View File
@@ -8,7 +8,7 @@ use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::ffi::CString;
use std::net;
use std::num::Wrapping;
use std::num::{Saturating, Wrapping};
use std::ops::Bound;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak};
@@ -500,6 +500,38 @@ fn test_range_inclusive() {
);
}
#[test]
fn test_range_from() {
assert_ser_tokens(
&(1u32..),
&[
Token::Struct {
name: "RangeFrom",
len: 1,
},
Token::Str("start"),
Token::U32(1),
Token::StructEnd,
],
);
}
#[test]
fn test_range_to() {
assert_ser_tokens(
&(..2u32),
&[
Token::Struct {
name: "RangeTo",
len: 1,
},
Token::Str("end"),
Token::U32(2),
Token::StructEnd,
],
);
}
#[test]
fn test_bound() {
assert_ser_tokens(
@@ -592,6 +624,11 @@ fn test_wrapping() {
assert_ser_tokens(&Wrapping(1usize), &[Token::U64(1)]);
}
#[test]
fn test_saturating() {
assert_ser_tokens(&Saturating(1usize), &[Token::U64(1)]);
}
#[test]
fn test_rc_dst() {
assert_ser_tokens(&Rc::<str>::from("s"), &[Token::Str("s")]);
+4 -2
View File
@@ -27,19 +27,21 @@ mod fake_serde {
{
}
#[allow(dead_code)]
pub trait Serialize {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
}
#[allow(dead_code)]
pub trait Deserialize<'a>: Sized {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error>;
}
}
trait AssertNotSerdeSerialize {}
pub trait AssertNotSerdeSerialize {}
impl<T: serde::Serialize> AssertNotSerdeSerialize for T {}
trait AssertNotSerdeDeserialize<'a> {}
pub trait AssertNotSerdeDeserialize<'a> {}
impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {}
+1 -1
View File
@@ -63,7 +63,7 @@ fn test_map_access_to_enum() {
type Value = Potential;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a map")
formatter.write_str("a map")
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
@@ -1,4 +1,4 @@
error: #[serde(default)] can only be used on structs with named fields
error: #[serde(default)] can only be used on structs
--> tests/ui/default-attribute/enum.rs:4:9
|
4 | #[serde(default)]
@@ -1,4 +1,4 @@
error: #[serde(default = "...")] can only be used on structs with named fields
error: #[serde(default = "...")] can only be used on structs
--> tests/ui/default-attribute/enum_path.rs:4:9
|
4 | #[serde(default = "default_e")]
@@ -1,7 +0,0 @@
use serde_derive::Deserialize;
#[derive(Deserialize)]
#[serde(default)]
struct T(u8, u8);
fn main() {}
@@ -1,5 +0,0 @@
error: #[serde(default)] can only be used on structs with named fields
--> tests/ui/default-attribute/nameless_struct_fields.rs:5:9
|
5 | struct T(u8, u8);
| ^^^^^^^^
@@ -1,7 +0,0 @@
use serde_derive::Deserialize;
#[derive(Deserialize)]
#[serde(default = "default_t")]
struct T(u8, u8);
fn main() {}
@@ -1,5 +0,0 @@
error: #[serde(default = "...")] can only be used on structs with named fields
--> tests/ui/default-attribute/nameless_struct_fields_path.rs:4:9
|
4 | #[serde(default = "default_t")]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -0,0 +1,47 @@
use serde_derive::Deserialize;
// No errors expected.
#[derive(Deserialize)]
struct T0(u8, u8);
// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
#[derive(Deserialize)]
struct T1(u8, #[serde(default)] u8);
// ERROR: The first field can get default value only if sequence is empty, but
// that mean that all other fields cannot be deserialized without errors.
#[derive(Deserialize)]
struct T2(#[serde(default)] u8, u8, u8);
// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
// - If no fields are provided, both get default value.
#[derive(Deserialize)]
struct T3(#[serde(default)] u8, #[serde(default)] u8);
////////////////////////////////////////////////////////////////////////////////
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T4(u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T5(#[serde(default)] u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T6(u8, #[serde(default)] u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T7(#[serde(default)] u8, #[serde(default)] u8);
fn main() {}

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