Compare commits

...

632 Commits

Author SHA1 Message Date
David Tolnay abb2a8494d Release 1.0.142 2022-08-03 07:09:15 -07:00
David Tolnay a31d0be191 Update keywords in crates.io metadata 2022-08-02 10:38:57 -07:00
David Tolnay d786e750d7 Release 1.0.141 2022-08-01 08:50:46 -07:00
David Tolnay 10e4839f83 Move Postcard link up to Bincode spot
Bincode has been in prerelease limbo for nearly a year and the readme
does not mention anything related to Serde, so it is not serving as a
good first link to a Serde binary format.
2022-08-01 08:49:45 -07:00
David Tolnay 85e72653c8 Add categories to crates.io metadata 2022-08-01 00:06:49 -07:00
David Tolnay c9cc8a8924 Add authors to Cargo.toml 2022-07-31 19:25:47 -07:00
David Tolnay a925ce4119 Sort package entries in Cargo.toml 2022-07-31 19:19:07 -07:00
David Tolnay c5f6338ce2 Release 1.0.140 2022-07-20 09:26:28 -07:00
David Tolnay 5185487d73 Merge pull request #2251 from taiki-e/derive-cfg
Invert build.rs cfgs in serde_derive
2022-07-20 09:25:14 -07:00
Taiki Endo efaafd4458 Invert build.rs cfgs in serde_derive 2022-07-21 01:15:37 +09:00
David Tolnay a0eb83a5d4 Resolve invalid_utf8_in_unchecked clippy lint in ancient test code
error: non UTF-8 literal in `std::str::from_utf8_unchecked`
       --> test_suite/tests/test_ser.rs:803:25
        |
    803 |     let path = unsafe { str::from_utf8_unchecked(b"Hello \xF0\x90\x80World") };
        |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = note: `-D clippy::invalid-utf8-in-unchecked` implied by `-D clippy::all`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
2022-07-18 21:29:39 -07:00
David Tolnay 7cc6f7fbb0 Ignore new_without_default clippy lint
error: you should consider adding a `Default` implementation for `UnitDeserializer<E>`
       --> serde/src/de/value.rs:144:5
        |
    144 | /     pub fn new() -> Self {
    145 | |         UnitDeserializer {
    146 | |             marker: PhantomData,
    147 | |         }
    148 | |     }
        | |_____^
        |
        = note: `-D clippy::new-without-default` implied by `-D clippy::all`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default
    help: try adding this
        |
    142 + impl<E> Default for UnitDeserializer<E> {
    143 +     fn default() -> Self {
    144 +         Self::new()
    145 +     }
    146 + }
        |
2022-07-11 21:19:58 -07:00
David Tolnay 44b9496c91 Release 1.0.139 2022-07-10 21:51:21 -07:00
David Tolnay 7e1486d0da Merge pull request #2246 from dtolnay/valuedenew
Add constructor function for all IntoDeserializer impls
2022-07-10 21:50:24 -07:00
David Tolnay 8170ffef2e Add constructor function for all IntoDeserializer impls 2022-07-10 21:42:03 -07:00
David Tolnay 4b622f6bbf Release 1.0.138 2022-07-01 20:09:56 -07:00
David Tolnay 0ee71c70af Ignore explicit_auto_deref clippy lint
error: deref which would be done by auto-deref
        --> serde/src/de/impls.rs:2014:59
         |
    2014 | ...                   Err(Error::unknown_field(&*value, FIELDS))
         |                                                 ^^^^^^ help: try this: `value`
         |
         = note: `-D clippy::explicit-auto-deref` implied by `-D clippy::all`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref

    error: deref which would be done by auto-deref
        --> serde/src/de/impls.rs:2354:55
         |
    2354 | ...                   Err(Error::unknown_field(&*value, FIELDS))
         |                                                 ^^^^^^ help: try this: `value`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref
2022-07-01 19:41:14 -07:00
David Tolnay 6c098e497e Merge pull request #2240 from Kixunil/patch-1
Call `reserve()` in `DeserializeSeed` example
2022-06-30 09:39:25 -07:00
Martin Habovštiak 41ffa6df7e Call reserve() in DeserializeSeed example
This suggests calling `reserve()` in example code so that people who ~blindly copy it get faster code.
2022-06-30 18:28:52 +02:00
David Tolnay 845b900fd5 Exclude deliberately pinned prettyplease crate from cargo outdated 2022-06-22 21:07:57 -07:00
David Tolnay 7891ae7184 Merge pull request #2228 from serde-rs/expandtest
Update macrotest to 1.0.9 and enable in CI
2022-06-20 03:53:50 -07:00
David Tolnay bac90d19b9 Update macrotest to 1.0.9 and enable in CI 2022-06-20 03:40:49 -07:00
David Tolnay 227bf3023a Merge pull request #2229 from dtolnay/expandlinguist
Mark expandtest outputs as generated code
2022-06-20 03:40:37 -07:00
David Tolnay f4535f68c1 Mark expandtest outputs as generated code 2022-06-20 03:27:20 -07:00
David Tolnay c6c35b5a31 Ignore buggy doc_link_with_quotes clippy lint
https://github.com/rust-lang/rust-clippy/issues/8961

    error: possible intra-doc link using quotes instead of backticks
       --> serde_test/src/token.rs:277:5
        |
    277 |     /// let vec = vec!['a', 'b', 'c'];
        |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = note: `-D clippy::doc-link-with-quotes` implied by `-D clippy::pedantic`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
2022-06-07 00:30:50 -07:00
David Tolnay 31e51324e2 Add actions job to notice outdated dependencies 2022-06-06 16:09:41 -07:00
David Tolnay bc3f24e0e9 Update toolchain_find dependency to 0.2 2022-06-06 16:09:14 -07:00
David Tolnay 2e38e2bf2f Ignore derive_partial_eq_without_eq clippy lint
error: you are deriving `PartialEq` and can implement `Eq`
      --> serde/src/de/value.rs:51:17
       |
    51 | #[derive(Clone, PartialEq)]
       |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = note: `-D clippy::derive-partial-eq-without-eq` implied by `-D clippy::all`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> serde_derive/src/internals/case.rs:13:23
       |
    13 | #[derive(Copy, Clone, PartialEq)]
       |                       ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
     --> test_suite/tests/unstable/mod.rs:6:21
      |
    6 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
      |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
      |
      = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
     --> test_suite/tests/test_ignored_any.rs:7:10
      |
    7 | #[derive(PartialEq, Debug, Deserialize)]
      |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
      |
      = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
     --> test_suite/tests/test_identifier.rs:7:34
      |
    7 |     #[derive(Deserialize, Debug, PartialEq)]
      |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
      |
      = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_identifier.rs:24:34
       |
    24 |     #[derive(Deserialize, Debug, PartialEq)]
       |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_identifier.rs:41:34
       |
    41 |     #[derive(Deserialize, Debug, PartialEq)]
       |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_identifier.rs:59:34
       |
    59 |     #[derive(Deserialize, Debug, PartialEq)]
       |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_ser.rs:46:10
       |
    46 | #[derive(PartialEq, Debug)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_value.rs:11:34
       |
    11 |     #[derive(Deserialize, Debug, PartialEq)]
       |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de_error.rs:15:23
       |
    15 | #[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
       |                       ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de_error.rs:18:10
       |
    18 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de_error.rs:26:10
       |
    26 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de_error.rs:34:10
       |
    34 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de_error.rs:41:19
       |
    41 | #[derive(Default, PartialEq, Debug)]
       |                   ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de_error.rs:60:10
       |
    60 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_borrow.rs:70:34
       |
    70 |     #[derive(Deserialize, Debug, PartialEq)]
       |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_borrow.rs:97:34
       |
    97 |     #[derive(Deserialize, Debug, PartialEq)]
       |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_borrow.rs:106:34
        |
    106 |     #[derive(Deserialize, Debug, PartialEq)]
        |                                  ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de.rs:43:23
       |
    43 | #[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
       |                       ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de.rs:46:10
       |
    46 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de.rs:49:10
       |
    49 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de.rs:52:10
       |
    52 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de.rs:76:10
       |
    76 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_de.rs:82:10
       |
    82 | #[derive(PartialEq, Debug, Deserialize)]
       |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_de.rs:102:10
        |
    102 | #[derive(PartialEq, Debug, Deserialize)]
        |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_de.rs:109:19
        |
    109 | #[derive(Default, PartialEq, Debug)]
        |                   ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_de.rs:128:10
        |
    128 | #[derive(PartialEq, Debug, Deserialize)]
        |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_de.rs:135:10
        |
    135 | #[derive(PartialEq, Debug)]
        |          ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_de.rs:185:14
        |
    185 |     #[derive(PartialEq, Debug, Deserialize)]
        |              ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
      --> test_suite/tests/test_macros.rs:25:17
       |
    25 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
       |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:110:17
        |
    110 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:580:21
        |
    580 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:607:21
        |
    607 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:681:21
        |
    681 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:684:21
        |
    684 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:816:21
        |
    816 |     #[derive(Debug, PartialEq, Deserialize)]
        |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_macros.rs:976:21
        |
    976 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1027:21
         |
    1027 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1273:21
         |
    1273 |     #[derive(Debug, PartialEq, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1342:21
         |
    1342 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1413:21
         |
    1413 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1450:21
         |
    1450 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1474:21
         |
    1474 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1509:21
         |
    1509 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1543:21
         |
    1543 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1601:21
         |
    1601 |     #[derive(Debug, PartialEq, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1743:45
         |
    1743 |     #[derive(Serialize, Deserialize, Debug, PartialEq)]
         |                                             ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1763:45
         |
    1763 |     #[derive(Serialize, Deserialize, Debug, PartialEq)]
         |                                             ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1770:45
         |
    1770 |     #[derive(Serialize, Deserialize, Debug, PartialEq)]
         |                                             ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1870:21
         |
    1870 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_macros.rs:1888:21
         |
    1888 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:108:17
        |
    108 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:124:17
        |
    124 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:147:17
        |
    147 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:344:17
        |
    344 | #[derive(Debug, PartialEq, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:394:17
        |
    394 | #[derive(Debug, PartialEq)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:413:17
        |
    413 | #[derive(Debug, PartialEq)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:458:17
        |
    458 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:512:17
        |
    512 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:520:17
        |
    520 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:528:17
        |
    528 | #[derive(Debug, PartialEq, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:647:17
        |
    647 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_gen.rs:835:17
        |
    835 | #[derive(Debug, PartialEq, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
       --> test_suite/tests/test_annotations.rs:675:17
        |
    675 | #[derive(Debug, PartialEq, Deserialize)]
        |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1047:17
         |
    1047 | #[derive(Debug, PartialEq)]
         |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1050:17
         |
    1050 | #[derive(Debug, PartialEq)]
         |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1196:17
         |
    1196 | #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1514:17
         |
    1514 | #[derive(Debug, PartialEq, Deserialize)]
         |                 ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1548:41
         |
    1548 | #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
         |                                         ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1566:41
         |
    1566 | #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
         |                                         ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1600:30
         |
    1600 | #[derive(Clone, Deserialize, PartialEq, Debug)]
         |                              ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1803:21
         |
    1803 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1843:21
         |
    1843 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1852:21
         |
    1852 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:1947:21
         |
    1947 |     #[derive(Debug, PartialEq, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2003:21
         |
    2003 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2037:21
         |
    2037 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                     ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2074:45
         |
    2074 |     #[derive(Deserialize, Serialize, Debug, PartialEq)]
         |                                             ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2080:45
         |
    2080 |     #[derive(Deserialize, Serialize, Debug, PartialEq)]
         |                                             ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2157:38
         |
    2157 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2193:38
         |
    2193 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2200:38
         |
    2200 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2240:38
         |
    2240 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2279:38
         |
    2279 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2316:38
         |
    2316 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2359:38
         |
    2359 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2390:38
         |
    2390 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2421:38
         |
    2421 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2426:38
         |
    2426 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2483:38
         |
    2483 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2507:38
         |
    2507 |     #[derive(Serialize, Deserialize, PartialEq, Debug)]
         |                                      ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2521:27
         |
    2521 |     #[derive(Deserialize, PartialEq, Debug)]
         |                           ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2552:27
         |
    2552 |     #[derive(Deserialize, PartialEq, Debug)]
         |                           ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2558:27
         |
    2558 |     #[derive(Deserialize, PartialEq, Debug)]
         |                           ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2586:14
         |
    2586 |     #[derive(PartialEq, Debug)]
         |              ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2624:27
         |
    2624 |     #[derive(Deserialize, PartialEq, Debug)]
         |                           ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq

    error: you are deriving `PartialEq` and can implement `Eq`
        --> test_suite/tests/test_annotations.rs:2647:27
         |
    2647 |     #[derive(Deserialize, PartialEq, Debug)]
         |                           ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
2022-05-21 20:43:51 -07:00
David Tolnay 819f90d9f6 Ignore unused_macro_rules warning in test macros
warning: 1st rule of macro `btreeset` is never used
     --> test_suite/tests/macros/mod.rs:5:5
      |
    5 |     () => {
      |     ^^
      |
      = note: `#[warn(unused_macro_rules)]` on by default

    warning: 1st rule of macro `hashset` is never used
      --> test_suite/tests/macros/mod.rs:27:5
       |
    27 |     () => {
       |     ^^

    warning: 1st rule of macro `hashmap` is never used
      --> test_suite/tests/macros/mod.rs:44:5
       |
    44 |     () => {
       |     ^^

    warning: 1st rule of macro `hashset` is never used
      --> test_suite/tests/macros/mod.rs:27:5
       |
    27 |     () => {
       |     ^^
       |
       = note: `#[warn(unused_macro_rules)]` on by default
2022-05-12 21:33:43 -07:00
David Tolnay 2eed86cd67 Remove doc(hidden) attribute that is being phased out
warning: `#[doc(hidden)]` is ignored on trait impl items
       --> serde/src/de/impls.rs:796:5
        |
    796 |     #[doc(hidden)]
        |     ^^^^^^^^^^^^^^ help: remove this attribute
        |
        = note: `#[warn(unused_attributes)]` on by default
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
2022-05-09 21:16:16 -07:00
David Tolnay 3921b57435 Run miri in stricter miri-strict-provenance mode 2022-05-06 04:01:35 -07:00
David Tolnay 68069d734a Fix needless_borrow for both value=Cow<str> and value=&str 2022-05-05 21:07:33 -07:00
David Tolnay dc84693507 Resolve needless_borrow clippy lint
error: this expression creates a reference which is immediately dereferenced by the compiler
        --> serde/src/de/impls.rs:2015:58
         |
    2015 | ...                   Err(Error::unknown_field(&value, FIELDS))
         |                                                ^^^^^^ help: change this to: `value`
         |
         = note: `-D clippy::needless-borrow` implied by `-D clippy::all`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression creates a reference which is immediately dereferenced by the compiler
        --> serde/src/de/impls.rs:2355:54
         |
    2355 | ...                   Err(Error::unknown_field(&value, FIELDS))
         |                                                ^^^^^^ help: change this to: `value`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
2022-05-05 21:01:03 -07:00
David Tolnay 4cf012c5be Resolve extra_unused_lifetimes clippy lint
error: this lifetime isn't used in the impl
       --> serde/src/de/value.rs:607:11
        |
    607 | impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E>
        |           ^^
        |
        = note: `-D clippy::extra-unused-lifetimes` implied by `-D clippy::all`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
2022-05-05 21:00:37 -07:00
David Tolnay 17c3c0cf86 Release 1.0.137 2022-04-30 21:45:31 -07:00
David Tolnay 210e6c354e Clean up clippy allows which are superseded by msrv in clippy.toml 2022-04-30 21:35:00 -07:00
David Tolnay 41823a96df Ignore more type_repetition_in_bounds
I'm not sure what is going on with this lint but it's triggering in a
lot of test code. Will need to investigate further.

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:194:21
        |
    194 |             bound = "E: SerializeWith + DeserializeWith"
        |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = note: `-D clippy::type-repetition-in-bounds` implied by `-D clippy::pedantic`
        = help: consider combining the bounds: `"E: SerializeWith + DeserializeWith": "E: SerializeWith + DeserializeWith" + "E: SerializeWith + DeserializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:184:21
        |
    184 |     #[serde(bound = "D: SerializeWith + DeserializeWith")]
        |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"D: SerializeWith + DeserializeWith": "D: SerializeWith + DeserializeWith" + "D: SerializeWith + DeserializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:210:31
        |
    210 |             bound(serialize = "E: SerializeWith")
        |                               ^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"E: SerializeWith": "E: SerializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:201:31
        |
    201 |     #[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
        |                               ^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"D: SerializeWith": "D: SerializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:231:21
        |
    231 |             bound = "E: SerializeWith + DeserializeWith"
        |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"E: SerializeWith + DeserializeWith": "E: SerializeWith + DeserializeWith" + "E: SerializeWith + DeserializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:221:21
        |
    221 |     #[serde(bound = "D: SerializeWith + DeserializeWith")]
        |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"D: SerializeWith + DeserializeWith": "D: SerializeWith + DeserializeWith" + "D: SerializeWith + DeserializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:247:31
        |
    247 |             bound(serialize = "E: SerializeWith")
        |                               ^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"E: SerializeWith": "E: SerializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_gen.rs:238:31
        |
    238 |     #[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
        |                               ^^^^^^^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `"D: SerializeWith": "D: SerializeWith"`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
      --> test_suite/tests/test_annotations.rs:84:5
       |
    84 |     C: MyDefault,
       |     ^^^^^^^^^^^^
       |
       = note: `-D clippy::type-repetition-in-bounds` implied by `-D clippy::pedantic`
       = help: consider combining the bounds: `C: MyDefault`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
      --> test_suite/tests/test_annotations.rs:85:5
       |
    85 |     E: MyDefault,
       |     ^^^^^^^^^^^^
       |
       = help: consider combining the bounds: `E: MyDefault`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
       --> test_suite/tests/test_annotations.rs:105:5
        |
    105 |     C: MyDefault;
        |     ^^^^^^^^^^^^
        |
        = help: consider combining the bounds: `C: MyDefault`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
        --> test_suite/tests/test_annotations.rs:1066:5
         |
    1066 |     B: 'a,
         |     ^^^^^
         |
         = help: consider combining the bounds: ``
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
        --> test_suite/tests/test_annotations.rs:1067:5
         |
    1067 |     D: SerializeWith,
         |     ^^^^^^^^^^^^^^^^
         |
         = help: consider combining the bounds: `D: SerializeWith`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
        --> test_suite/tests/test_annotations.rs:1106:5
         |
    1106 |     B: SerializeWith,
         |     ^^^^^^^^^^^^^^^^
         |
         = help: consider combining the bounds: `B: SerializeWith`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
        --> test_suite/tests/test_annotations.rs:1150:5
         |
    1150 |     B: SerializeWith,
         |     ^^^^^^^^^^^^^^^^
         |
         = help: consider combining the bounds: `B: SerializeWith`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds

    error: this type has already been used as a bound predicate
        --> test_suite/tests/test_annotations.rs:1368:5
         |
    1368 |     B: DeserializeWith,
         |     ^^^^^^^^^^^^^^^^^^
         |
         = help: consider combining the bounds: `B: DeserializeWith`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
2022-04-30 21:32:36 -07:00
David Tolnay 7ca13ff240 Ignore type_repetition_in_bounds lint that is incompatible with msrv
https://github.com/rust-lang/rust-clippy/issues/8772
2022-04-30 21:32:26 -07:00
David Tolnay 52391fd868 Inform clippy of supported compiler version in clippy.toml 2022-04-30 20:40:23 -07:00
David Tolnay 9b2d8dfc6b Add a miri test job in CI 2022-04-28 20:43:03 -07:00
David Tolnay 07ba7ea8dd Update workflows to actions/checkout@v3 2022-04-24 19:06:18 -07:00
David Tolnay 9f29f6bb4a Disable expandtest on miri 2022-04-24 16:01:52 -07:00
David Tolnay f6c104fd1d Ignore unused ignore attribute warning in some configurations 2022-04-24 16:01:22 -07:00
David Tolnay 8a3a6fb101 Disable ui test on miri 2022-04-24 15:21:17 -07:00
David Tolnay b5c3b5e8e5 Update ui test suite to nightly-2022-04-17 2022-04-16 23:48:27 -07:00
David Tolnay 996d171461 Merge pull request #2201 from atouchet/urls
Update some URLs
2022-04-14 02:50:36 -07:00
Alex Touchet e1c4517335 Update some URLs 2022-04-13 21:42:37 -07:00
David Tolnay 6e94a27c76 Merge pull request #2194 from serde-rs/exhaustive
Update exhaustive matching to syn 1.0.90
2022-03-28 10:27:27 -07:00
David Tolnay b23a768414 Update exhaustive matching to syn 1.0.90 2022-03-28 10:21:37 -07:00
David Tolnay 7e19ae8c94 Fix rust-version in serde_test Cargo.toml too
#2168
2022-01-25 14:49:56 -08:00
David Tolnay 404a1d142a Fix rust-version in Cargo.toml
Closes #2168.
2022-01-25 14:42:09 -08:00
David Tolnay 02bd79a0ba Release 1.0.136 2022-01-25 13:34:29 -08:00
David Tolnay c3ce2c934a Merge pull request #2167 from serde-rs/error128
Render 128-bit integer value into Visitor errors
2022-01-25 13:07:01 -08:00
David Tolnay 0d71ac84b5 Render 128-bit integer value into Visitor errors 2022-01-25 12:06:35 -08:00
David Tolnay 82c3eb7ba4 Add test of visitor error messages 2022-01-25 11:24:53 -08:00
David Tolnay 8932c852a5 Release 1.0.135 2022-01-22 16:04:17 -08:00
David Tolnay 9f3dd3c7c4 Merge pull request #2163 from serde-rs/discord
Add discord invite links
2022-01-22 11:23:32 -08:00
David Tolnay dd9b415ff9 Add discord invite links 2022-01-22 11:21:08 -08:00
David Tolnay 3bb4a5a4f6 Release 1.0.134 2022-01-20 22:22:30 -08:00
David Tolnay 6164627bea Merge pull request #2159 from serde-rs/nonzero
Write better Visitor for NonZero integers
2022-01-20 22:22:02 -08:00
David Tolnay 51aaf496d4 Write better Visitor for NonZero integers 2022-01-20 22:15:16 -08:00
David Tolnay bc66aeb0d3 Add tests of deserializing NonZero 2022-01-20 21:55:50 -08:00
David Tolnay 7e7044d457 Ignore clippy in number conversion tests 2022-01-20 21:38:31 -08:00
David Tolnay 5498dc0550 Add tests of num conversion errors 2022-01-20 21:37:16 -08:00
David Tolnay ff04e8be9b Improve coverage of num conversion in test suite 2022-01-20 21:16:50 -08:00
David Tolnay 69240c17c5 Eliminate macro from serialization tests 2022-01-20 20:37:08 -08:00
David Tolnay 237434f19c Accept ?Sized references in assert_ser_tokens 2022-01-20 20:21:04 -08:00
David Tolnay 1833914346 Eliminate macro from deserialization error tests 2022-01-20 19:58:45 -08:00
David Tolnay ab848060f2 Extract tests of deserialization errors to separate file 2022-01-20 19:58:01 -08:00
David Tolnay 7e39623f72 Implement test suite seq macro without tt muncher 2022-01-20 19:40:58 -08:00
David Tolnay 157dc44c51 Clean up test suite's macro formatting 2022-01-20 19:40:32 -08:00
David Tolnay 80d01a3a79 Tweak seq iterators in test suite 2022-01-20 19:40:13 -08:00
David Tolnay 343c060fc1 Adapt seq macro to not derail rustfmt 2022-01-20 19:38:51 -08:00
David Tolnay 21c1ab6c50 Format deserialization tests with rustfmt 2022-01-20 19:24:35 -08:00
David Tolnay 594ab7745d Reimplement deserialization tests without macro 2022-01-20 18:09:48 -08:00
David Tolnay 8cf0ba7fe2 Make serde_test build script buildable with older rustc 2022-01-20 17:59:21 -08:00
David Tolnay 34b52c0b83 Include build script in packaged serde_test crate 2022-01-20 17:52:25 -08:00
David Tolnay ec7ddc93cd Include 128-bit integers in test suite unconditionally 2022-01-20 15:45:07 -08:00
David Tolnay 55a7cedd73 Invert all build.rs cfgs
This allows non-Cargo builds to generally not get involved in cfgs. As
long as one is using a reasonably recent toolchain, no cfgs need to be
set and you'll get a fully-featured build.
2022-01-01 21:09:49 -08:00
David Tolnay 7af97c66b8 Release 1.0.133 2022-01-01 13:16:35 -08:00
David Tolnay 1f57084365 Merge pull request #2148 from serde-rs/deserializecontent
Optimize deserialization of recursive buffered types
2022-01-01 13:16:02 -08:00
David Tolnay 56bd369422 Optimize deserialization of recursive buffered types 2022-01-01 13:01:38 -08:00
David Tolnay ff259ec66b Detect warnings in CI 2022-01-01 11:52:55 -08:00
David Tolnay 6c54aafeb9 Document the atomic ordering in the Serialize impl 2021-12-23 11:44:31 -08:00
David Tolnay 5d41404e67 No need for the SeqCst load in test suite 2021-12-23 11:42:41 -08:00
David Tolnay 1eccb3c350 Resolve unnecessary_to_owned clippy lint in test suite
error: unnecessary use of `to_vec`
       --> test_suite/tests/test_de.rs:251:12
        |
    251 |     .chain(ignorable_tokens.to_vec().into_iter())
        |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `ignorable_tokens.iter().copied()`
        |
        = note: `-D clippy::unnecessary-to-owned` implied by `-D clippy::all`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
2021-12-17 18:25:04 -08:00
David Tolnay 77ae1c3bf7 Release 1.0.132 2021-12-16 11:06:42 -08:00
David Tolnay b85e28166c Update path to rustc target spec files 2021-12-16 11:05:58 -08:00
David Tolnay 0508cb50fc Merge pull request #2141 from Avimitin/risc-v
Enable atomic64 on riscv64 arch
2021-12-16 11:05:14 -08:00
Avimitin 84fdc7df69 Enable atomic64 on riscv64 arch
Signed-off-by: Avimitin <avimitin@gmail.com>
2021-12-14 20:30:28 +08:00
David Tolnay ab1ca04b2e Release 1.0.131 2021-12-08 18:47:15 -08:00
David Tolnay fb2fe409c8 Touch up PR 2116 2021-12-08 18:44:41 -08:00
David Tolnay 549fac7235 Merge pull request #2116 from tyranron/fix-unused-results
Fix `unused_results` complaining rustc lint in codegen for adjacently tagged enum
2021-12-08 18:43:31 -08:00
David Tolnay c375d8b19b Merge pull request #2124 from dtolnay/cbor
Change cbor link to new repo
2021-11-26 14:48:40 -08:00
David Tolnay 6cf507f808 Change cbor link to new repo 2021-11-26 14:43:09 -08:00
David Tolnay c3c1641c06 Remove workaround for redundant_field_names Clippy bug 2021-11-04 20:23:25 -07:00
David Tolnay 1fcda0ebdb Enable pedantic lints on test suite in CI 2021-11-04 20:21:48 -07:00
David Tolnay 8f16ac0a94 Move deny(clippy) to command line arguments in the CI job 2021-11-04 20:09:35 -07:00
David Tolnay 737f78c315 Ignore enum_variant_names Clippy lint in test suite
error: all variants have the same prefix: `Serialize`
        --> test_suite/tests/test_macros.rs:1741:5
         |
    1741 | /     enum E {
    1742 | |         #[serde(rename_all = "camelCase")]
    1743 | |         Serialize {
    1744 | |             serialize: bool,
    ...    |
    1756 | |         },
    1757 | |     }
         | |_____^
         |
         = note: `-D clippy::enum-variant-names` implied by `-D clippy::all`
         = help: remove the prefixes and use full paths to the variants instead of glob imports
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names
2021-11-04 20:06:02 -07:00
David Tolnay 4a97386cb9 Clippy if_then_panic lint has been renamed to manual_assert 2021-11-04 19:57:14 -07:00
tyranron 5b32217877 Fix unused_results complaining rustc lint in codegen for adjacently tagged enum 2021-10-29 14:13:26 +03:00
David Tolnay 5b140361a3 Merge pull request #2102 from atouchet/url
Update URL
2021-10-14 16:33:22 -07:00
Alex Touchet 678351eac7 Update URL 2021-10-14 16:27:49 -07:00
David Tolnay 999c261d11 Ui test changes for trybuild 1.0.49 2021-10-08 02:46:15 -04:00
David Tolnay efbe574209 Update ui test files 2021-10-07 00:56:29 -04:00
David Tolnay 33b2677384 Suppress broken semicolon_if_nothing_returned lint
https://github.com/rust-lang/rust-clippy/issues/7768

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:849:1
        |
    849 | / seq_impl!(
    850 | |     BinaryHeap<T: Ord>,
    851 | |     seq,
    852 | |     BinaryHeap::clear,
    ...   |
    855 | |     BinaryHeap::push
    856 | | );
        | |__^
        |
    note: the lint level is defined here
       --> serde/src/lib.rs:97:52
        |
    97  | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                                    ^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::semicolon_if_nothing_returned)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    849 + seq_impl!(
    850 +     BinaryHeap<T: Ord>,
    851 +     seq,
    852 +     BinaryHeap::clear,
    853 +     BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
    854 +     BinaryHeap::reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:859:1
        |
    859 | / seq_impl!(
    860 | |     BTreeSet<T: Eq + Ord>,
    861 | |     seq,
    862 | |     BTreeSet::clear,
    ...   |
    865 | |     BTreeSet::insert
    866 | | );
        | |__^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    859 + seq_impl!(
    860 +     BTreeSet<T: Eq + Ord>,
    861 +     seq,
    862 +     BTreeSet::clear,
    863 +     BTreeSet::new(),
    864 +     nop_reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:869:1
        |
    869 | / seq_impl!(
    870 | |     LinkedList<T>,
    871 | |     seq,
    872 | |     LinkedList::clear,
    ...   |
    875 | |     LinkedList::push_back
    876 | | );
        | |__^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    869 + seq_impl!(
    870 +     LinkedList<T>,
    871 +     seq,
    872 +     LinkedList::clear,
    873 +     LinkedList::new(),
    874 +     nop_reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:879:1
        |
    879 | / seq_impl!(
    880 | |     HashSet<T: Eq + Hash, S: BuildHasher + Default>,
    881 | |     seq,
    882 | |     HashSet::clear,
    883 | |     HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
    884 | |     HashSet::reserve,
    885 | |     HashSet::insert);
        | |_____________________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    879 + seq_impl!(
    880 +     HashSet<T: Eq + Hash, S: BuildHasher + Default>,
    881 +     seq,
    882 +     HashSet::clear,
    883 +     HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
    884 +     HashSet::reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:888:1
        |
    888 | / seq_impl!(
    889 | |     VecDeque<T>,
    890 | |     seq,
    891 | |     VecDeque::clear,
    ...   |
    894 | |     VecDeque::push_back
    895 | | );
        | |__^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    888 + seq_impl!(
    889 +     VecDeque<T>,
    890 +     seq,
    891 +     VecDeque::clear,
    892 +     VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
    893 +     VecDeque::reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde/src/de/impls.rs:1300:1
         |
    1300 | / map_impl!(
    1301 | |     BTreeMap<K: Ord, V>,
    1302 | |     map,
    1303 | |     BTreeMap::new());
         | |_____________________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
         |
    1300 + map_impl!(
    1301 +     BTreeMap<K: Ord, V>,
    1302 +     map,
    1303 +     BTreeMap::new());;
         |

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde/src/de/impls.rs:1306:1
         |
    1306 | / map_impl!(
    1307 | |     HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
    1308 | |     map,
    1309 | |     HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default()));
         | |___________________________________________________________________________________________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
         |
    1306 + map_impl!(
    1307 +     HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
    1308 +     map,
    1309 +     HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default()));;
         |
2021-10-04 23:57:05 -04:00
David Tolnay 01ded9f405 Declare minimum Rust version in Cargo metadata 2021-10-02 02:43:22 -04:00
David Tolnay fc827ecec2 Resolve redundant_closure_for_method_calls clippy lints
error: redundant closure
      --> serde_derive/src/bound.rs:53:19
       |
    53 |         .flat_map(|predicates| predicates.to_vec());
       |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `[T]::to_vec`
       |
    note: the lint level is defined here
      --> serde_derive/src/lib.rs:18:22
       |
    18 | #![deny(clippy::all, clippy::pedantic)]
       |                      ^^^^^^^^^^^^^^^^
       = note: `#[deny(clippy::redundant_closure_for_method_calls)]` implied by `#[deny(clippy::pedantic)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls

    error: redundant closure
      --> serde_derive/src/bound.rs:75:19
       |
    75 |         .flat_map(|predicates| predicates.to_vec());
       |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `[T]::to_vec`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
2021-09-30 00:31:49 -04:00
David Tolnay 5c785eee58 Ignore if_then_panic clippy lint
error: only a `panic!` in `if`-then statement
      --> serde_derive/src/internals/ctxt.rs:58:9
       |
    58 | /         if !thread::panicking() && self.errors.borrow().is_some() {
    59 | |             panic!("forgot to check for errors");
    60 | |         }
       | |_________^ help: try: `assert!(!!thread::panicking() && self.errors.borrow().is_some(), "forgot to check for errors");`
       |
    note: the lint level is defined here
      --> serde_derive/src/lib.rs:18:9
       |
    18 | #![deny(clippy::all, clippy::pedantic)]
       |         ^^^^^^^^^^^
       = note: `#[deny(clippy::if_then_panic)]` implied by `#[deny(clippy::all)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:73:5
        |
    73  | /     if ser.remaining() > 0 {
    74  | |         panic!("{} remaining tokens", ser.remaining());
    75  | |     }
        | |_____^ help: try: `assert!(!ser.remaining() > 0, "{} remaining tokens", ser.remaining());`
        |
    note: the lint level is defined here
       --> serde_test/src/lib.rs:149:44
        |
    149 | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                            ^^^^^^
        = note: `#[deny(clippy::if_then_panic)]` implied by `#[deny(clippy::all)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:126:5
        |
    126 | /     if ser.remaining() > 0 {
    127 | |         panic!("{} remaining tokens", ser.remaining());
    128 | |     }
        | |_____^ help: try: `assert!(!ser.remaining() > 0, "{} remaining tokens", ser.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:166:5
        |
    166 | /     if de.remaining() > 0 {
    167 | |         panic!("{} remaining tokens", de.remaining());
    168 | |     }
        | |_____^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:180:5
        |
    180 | /     if de.remaining() > 0 {
    181 | |         panic!("{} remaining tokens", de.remaining());
    182 | |     }
        | |_____^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:220:5
        |
    220 | /     if de.remaining() > 0 {
    221 | |         panic!("{} remaining tokens", de.remaining());
    222 | |     }
        | |_____^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
        --> test_suite/tests/test_de.rs:1349:9
         |
    1349 | /         if de.remaining() > 0 {
    1350 | |             panic!("{} remaining tokens", de.remaining());
    1351 | |         }
         | |_________^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
         |
         = note: `-D clippy::if-then-panic` implied by `-D clippy::all`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic
2021-09-30 00:31:49 -04:00
David Tolnay 819db93a3d Format with rustfmt 2021-09-29 2021-09-30 00:31:49 -04:00
David Tolnay a6690ea2fe Update ui test suite to nightly-2021-09-14 2021-09-14 19:13:54 -07:00
David Tolnay 65e1a50749 Release 1.0.130 2021-08-28 11:31:38 -07:00
David Tolnay 87d41b59fd Merge pull request #2081 from dtolnay/accessunsized
Enable unsized Map/SeqAccess types to use the impl for &mut
2021-08-28 11:11:57 -07:00
David Tolnay 3f120fb355 Enable unsized Map/SeqAccess types to use the impl for &mut 2021-08-28 10:59:51 -07:00
David Tolnay 2b92c80cc1 Release 1.0.129 2021-08-23 15:01:24 -07:00
David Tolnay c1c0ede452 Merge pull request #2080 from dtolnay/packeddrop
Support packed remote struct without destructuring
2021-08-23 15:00:50 -07:00
David Tolnay 4a66c5f33d Support packed remote struct without destructuring 2021-08-23 14:38:33 -07:00
David Tolnay 714c8a5586 Add test of packed struct that cannot be destructured
Currently fails:

    error[E0509]: cannot move out of type `RemotePackedNonCopyDef`, which implements the `Drop` trait
       --> test_suite/tests/test_gen.rs:876:10
        |
    876 | #[derive(Deserialize)]
        |          ^^^^^^^^^^^
        |          |
        |          cannot move out of here
        |          data moved here
        |          move occurs because `__v1` has type `std::string::String`, which does not implement the `Copy` trait
        |
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-08-23 14:38:33 -07:00
David Tolnay dc0c0dcba1 Merge pull request #2079 from dtolnay/packedremote
Fix unaligned reference warnings on packed remote def
2021-08-23 14:38:21 -07:00
David Tolnay 54102ee7d0 Avoid generating ref patterns for fields of packed remote struct 2021-08-23 10:18:28 -07:00
David Tolnay 14accf7518 Add test of remote with a packed struct
Currently fails to build:

    error: reference to packed field is unaligned
       --> test_suite/tests/test_gen.rs:858:10
        |
    858 | #[derive(Serialize, Deserialize)]
        |          ^^^^^^^^^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(unaligned_references)]` implied by `#[deny(warnings)]`
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
        = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)

    error: reference to packed field is unaligned
       --> test_suite/tests/test_gen.rs:858:21
        |
    858 | #[derive(Serialize, Deserialize)]
        |                     ^^^^^^^^^^^
        |
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-08-23 10:18:05 -07:00
David Tolnay 55fdbea20b Merge pull request #2077 from dtolnay/tryfold
Use try_fold in default implementation of collect_seq, collect_map
2021-08-21 14:08:20 -07:00
David Tolnay 75d8902371 Use try_fold in default implementation of collect_seq, collect_map 2021-08-21 14:00:51 -07:00
David Tolnay 9451ea8df1 Format PR 1992 with rustfmt 2021-08-21 12:49:58 -07:00
David Tolnay c1ce03b3dd Merge pull request 1992 from Mingun/unnecessary-deserialize-with 2021-08-21 12:49:39 -07:00
David Tolnay a587eb8953 Release 1.0.128 2021-08-21 10:39:32 -07:00
Oli Scherer 990f7eb6c1 Merge pull request #2076 from Manishearth/emscripten-i128
Enable 128-bit integers on emscripten post Rust 1.40
2021-08-21 19:19:30 +02:00
Manish Goregaokar 082e18f9a1 Rust supports i128/u128 on emscripten post Rust 1.40 2021-08-20 21:57:06 -07:00
David Tolnay f309485787 Ignore buggy collapsible_match clippy lint
https://github.com/rust-lang/rust-clippy/issues/7575
2021-08-16 19:32:10 -07:00
David Tolnay e2f85681fe Release 1.0.127 2021-07-30 20:59:13 -07:00
David Tolnay 8b840c3030 Resolve semicolon_in_expressions_from_macros warning in serde_test
warning: trailing semicolon in macro used in expression position
       --> serde_test/src/ser.rs:44:10
        |
    44  |         );
        |          ^
    ...
    152 |             Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
        |                                             ---------------------------------------- in this macro invocation
        |
        = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: this warning originates in the macro `assert_next_token` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: trailing semicolon in macro used in expression position
       --> serde_test/src/ser.rs:36:76
        |
    36  |         assert_next_token!($ser, stringify!($actual), Token::$actual, true);
        |                                                                            ^
    ...
    386 |             Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
        |                                       --------------------------------------------- in this macro invocation
        |
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: this warning originates in the macro `assert_next_token` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-07-30 20:58:07 -07:00
David Tolnay 9c39115f82 Ignore buggy nonstandard_macro_braces clippy lint
Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422

    error: use of irregular braces for `format_args!` macro
       --> test_suite/tests/test_gen.rs:528:25
        |
    528 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        |
        = note: `-D clippy::nonstandard-macro-braces` implied by `-D clippy::all`
    help: consider writing `Deserialize`
       --> test_suite/tests/test_gen.rs:528:25
        |
    528 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

    error: use of irregular braces for `format_args!` macro
        --> test_suite/tests/test_annotations.rs:1791:43
         |
    1791 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                                           ^^^^^^^^^^^
         |
         = note: `-D clippy::nonstandard-macro-braces` implied by `-D clippy::all`
    help: consider writing `Deserialize`
        --> test_suite/tests/test_annotations.rs:1791:43
         |
    1791 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                                           ^^^^^^^^^^^
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
         = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-07-02 20:58:04 -07:00
David Tolnay 89342af71e Merge pull request #2047 from jsoref/spelling
spelling: implicitly
2021-06-24 22:25:58 -07:00
Josh Soref 3c5e2d11f6 spelling: implicitly
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2021-06-25 00:43:23 -04:00
David Tolnay 3805c037a8 Merge pull request #2040 from dtolnay/test
Fix outdated test instructions in CONTRIBUTING.md
2021-06-12 13:43:30 -07:00
David Tolnay 7045fee260 Fix outdated test instructions in CONTRIBUTING.md 2021-06-12 13:38:40 -07:00
David Tolnay 9d81532e41 Merge pull request #2039 from dtolnay/test
Update documented test command for the serde directory
2021-06-12 13:38:34 -07:00
David Tolnay 5e47432ef0 Update documented test command for the serde directory 2021-06-12 13:34:45 -07:00
Mingun e0fc46783d Add test with generic deserialize_with function 2021-06-12 18:47:08 +05:00
Mingun ca772a14f9 Get rid of useless DeserializeWith wrapper 2021-06-12 18:38:03 +05:00
David Tolnay 7b840897a9 Resolve needless_borrow clippy lints
error: this expression borrows a reference (`&syn::Type`) that is immediately dereferenced by the compiler
       --> serde_derive/src/internals/check.rs:399:37
        |
    399 |     if let Type::Path(ty) = ungroup(&field.ty) {
        |                                     ^^^^^^^^^ help: change this to: `field.ty`
        |
    note: the lint level is defined here
       --> serde_derive/src/lib.rs:18:9
        |
    18  | #![deny(clippy::all, clippy::pedantic)]
        |         ^^^^^^^^^^^
        = note: `#[deny(clippy::needless_borrow)]` implied by `#[deny(clippy::all)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
       --> serde_derive/src/de.rs:478:52
        |
    478 |         &type_path, params, fields, false, cattrs, &expecting,
        |                                                    ^^^^^^^^^^ help: change this to: `expecting`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
       --> serde_derive/src/de.rs:564:76
        |
    564 |     let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
        |                                                                            ^^^^^^^^^^ help: change this to: `expecting`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
       --> serde_derive/src/de.rs:925:51
        |
    925 |         &type_path, params, fields, true, cattrs, &expecting,
        |                                                   ^^^^^^^^^^ help: change this to: `expecting`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
        --> serde_derive/src/de.rs:1066:76
         |
    1066 |     let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
         |                                                                            ^^^^^^^^^^ help: change this to: `expecting`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&proc_macro2::TokenStream`) that is immediately dereferenced by the compiler
        --> serde_derive/src/de.rs:2288:80
         |
    2288 |         let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(&fallthrough_arm);
         |                                                                                ^^^^^^^^^^^^^^^^ help: change this to: `fallthrough_arm`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&syn::Member`) that is immediately dereferenced by the compiler
        --> serde_derive/src/ser.rs:1102:43
         |
    1102 |                 get_member(params, field, &member)
         |                                           ^^^^^^^ help: change this to: `member`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
2021-06-04 20:58:23 -07:00
David Tolnay 967795414b Resolve semicolon_if_nothing_returned clippy lints
error: consider adding a `;` to the last statement for consistent formatting
       --> serde_derive/src/internals/attr.rs:559:25
        |
    559 |                         serde_path.set(&m.path, path)
        |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `serde_path.set(&m.path, path);`
        |
    note: the lint level is defined here
       --> serde_derive/src/lib.rs:18:22
        |
    18  | #![deny(clippy::all, clippy::pedantic)]
        |                      ^^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::semicolon_if_nothing_returned)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/internals/attr.rs:1612:9
         |
    1612 |         cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/internals/attr.rs:1623:9
         |
    1623 |         cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/internals/attr.rs:1649:9
         |
    1649 | /         cx.error_spanned_by(
    1650 | |             lit,
    1651 | |             format!("failed to parse type: {} = {:?}", attr_name, string.value()),
    1652 | |         )
         | |_________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
         |
    1649 |         cx.error_spanned_by(
    1650 |             lit,
    1651 |             format!("failed to parse type: {} = {:?}", attr_name, string.value()),
    1652 |         );
         |

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde_derive/src/internals/check.rs:260:9
        |
    260 | /         cx.error_spanned_by(
    261 | |             cont.original,
    262 | |             format!("variant field name `{}` conflicts with internal tag", tag),
    263 | |         )
        | |_________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    260 |         cx.error_spanned_by(
    261 |             cont.original,
    262 |             format!("variant field name `{}` conflicts with internal tag", tag),
    263 |         );
        |

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/de.rs:2090:9
         |
    2090 |         flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
2021-06-04 20:55:22 -07:00
David Tolnay 985725f820 Resolve while_let_on_iterator clippy lint
error: this loop could be written as a `for` loop
        --> serde/src/private/de.rs:2835:9
         |
    2835 |         while let Some(item) = self.iter.next() {
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for item in &mut self.iter`
         |
    note: the lint level is defined here
        --> serde/src/lib.rs:97:44
         |
    97   | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
         |                                            ^^^^^^
         = note: `#[deny(clippy::while_let_on_iterator)]` implied by `#[deny(clippy::all)]`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator

    error: this loop could be written as a `for` loop
        --> serde/src/private/de.rs:2937:9
         |
    2937 |         while let Some(item) = self.iter.next() {
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for item in &mut self.iter`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
2021-05-22 20:29:34 -07:00
David Tolnay 0c303d85d7 Merge pull request #2027 from striezel-stash/fix-typos
fix some typos
2021-05-15 10:14:13 -07:00
Dirk Stolle f68e9e901e fix some typos 2021-05-15 16:18:05 +02:00
David Tolnay 1094e2d334 Update ui test suite to nightly-2021-05-14 2021-05-13 19:16:07 -07:00
David Tolnay d9c338ec4a Release 1.0.126 2021-05-12 10:18:26 -07:00
David Tolnay 699bf3a75d Merge pull request #2026 from hyd-dev/warning
Allow only `unused_extern_crates` instead of the whole `rust_2018_idioms` lint group in `serde_derive`-generated code
2021-05-12 10:16:47 -07:00
hyd-dev dd29825217 Allow only unused_extern_crates instead of the whole rust_2018_idioms lint group in serde_derive-generated code 2021-05-12 18:29:45 +08:00
David Tolnay 6366f17da7 Ignore clone_instead_of_copied pedantic clippy lint
Iterator::copied was introduced in Rust 1.35, whereas serde_test
currently supports a minimum compiler version of 1.13.

    error: used `cloned` where `copied` could be used instead
       --> serde_test/src/de.rs:49:29
        |
    49  |         self.tokens.first().cloned()
        |                             ^^^^^^ help: try: `copied`
        |
    note: the lint level is defined here
       --> serde_test/src/lib.rs:149:52
        |
    149 | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                                    ^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::cloned_instead_of_copied)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied
2021-04-24 19:26:19 -07:00
David Tolnay 1120e5af4a Remove suppression of removed clippy lint
warning: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
      --> serde_derive/src/lib.rs:42:5
       |
    42 |     clippy::filter_map,
       |     ^^^^^^^^^^^^^^^^^^
       |
       = note: `#[warn(renamed_and_removed_lints)]` on by default

    warning: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
      --> serde_derive/src/lib.rs:42:5
       |
    42 |     clippy::filter_map,
       |     ^^^^^^^^^^^^^^^^^^
2021-04-24 19:23:56 -07:00
David Tolnay 1093f7e232 Resolve flat_map_option pedantic clippy lint
error: used `flat_map` where `filter_map` could be used instead
      --> serde_derive/src/bound.rs:52:10
       |
    52 |         .flat_map(|field| from_field(&field.attrs))
       |          ^^^^^^^^ help: try: `filter_map`
       |
    note: the lint level is defined here
      --> serde_derive/src/lib.rs:18:22
       |
    18 | #![deny(clippy::all, clippy::pedantic)]
       |                      ^^^^^^^^^^^^^^^^
       = note: `#[deny(clippy::flat_map_option)]` implied by `#[deny(clippy::pedantic)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option

    error: used `flat_map` where `filter_map` could be used instead
      --> serde_derive/src/bound.rs:74:10
       |
    74 |         .flat_map(|variant| from_variant(&variant.attrs))
       |          ^^^^^^^^ help: try: `filter_map`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option
2021-04-24 19:23:21 -07:00
David Tolnay 2ea132b8c4 Merge pull request #2018 from dtolnay/nonascii
Remove non_ascii_idents feature gate from test suite
2021-04-19 20:24:51 -07:00
David Tolnay 2ebc771b88 Remove non_ascii_idents feature gate from test suite
error: the feature `non_ascii_idents` has been stable since 1.53.0 and no longer requires an attribute to enable
     --> test_suite/tests/test_gen.rs:6:43
      |
    6 | #![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
      |                                           ^^^^^^^^^^^^^^^^
      |
    note: the lint level is defined here
     --> test_suite/tests/test_gen.rs:5:9
      |
    5 | #![deny(warnings)]
      |         ^^^^^^^^
      = note: `#[deny(stable_features)]` implied by `#[deny(warnings)]`
2021-04-19 19:55:12 -07:00
David Tolnay c17c4eef18 Unify stable and beta CI workflow 2021-04-19 19:54:56 -07:00
David Tolnay 7aa4950504 Release serde_derive_internals 0.26.0 2021-04-09 14:23:13 -07:00
David Tolnay 47015a2727 Merge pull request #2015 from dtolnay/symlink
Build using relative path in repo if Windows lost the symlink
2021-04-09 14:20:55 -07:00
David Tolnay dc4c31eb50 Build using relative path in repo if Windows lost symlink 2021-04-09 14:16:17 -07:00
David Tolnay b53ebef438 Resolve safe_packed_borrows lint renamed to unaligned_references
warning: lint `safe_packed_borrows` has been renamed to `unaligned_references`
        --> test_suite/tests/test_macros.rs:1926:8
         |
    1926 | #[deny(safe_packed_borrows)]
         |        ^^^^^^^^^^^^^^^^^^^ help: use the new name: `unaligned_references`
         |
         = note: `#[warn(renamed_and_removed_lints)]` on by default
2021-04-08 20:08:42 -07:00
David Tolnay 6c3bf7a2fc Ignore poor suggestion from branches_sharing_code lint
https://github.com/rust-lang/rust-clippy/issues/7054

    error: all if blocks contain the same code at the end
        --> serde_derive/src/de.rs:2160:5
         |
    2160 | /         &fallthrough_arm_tokens
    2161 | |     };
         | |_____^
         |
    note: the lint level is defined here
        --> serde_derive/src/lib.rs:18:9
         |
    18   | #![deny(clippy::all, clippy::pedantic)]
         |         ^^^^^^^^^^^
         = note: `#[deny(clippy::branches_sharing_code)]` implied by `#[deny(clippy::all)]`
         = note: The end suggestion probably needs some adjustments to use the expression result correctly
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
    help: consider moving the end statements out like this
         |
    2160 |     }
    2161 |     &fallthrough_arm_tokens;
         |
2021-04-08 20:08:42 -07:00
David Tolnay ce0844b9ec Suppress match_wildcard_for_single_variants clippy false positive
https://github.com/rust-lang/rust-clippy/issues/6984

    error: wildcard matches only a single variant and will also match any future added variants
        --> serde_derive/src/internals/attr.rs:1918:9
         |
    1918 |         _ => {}
         |         ^ help: try this: `syn::Type::__TestExhaustive(_)`
         |
    note: the lint level is defined here
        --> serde_derive/src/lib.rs:18:22
         |
    18   | #![deny(clippy::all, clippy::pedantic)]
         |                      ^^^^^^^^^^^^^^^^
         = note: `#[deny(clippy::match_wildcard_for_single_variants)]` implied by `#[deny(clippy::pedantic)]`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants

    error: wildcard matches only a single variant and will also match any future added variants
       --> serde_derive/src/internals/receiver.rs:153:13
        |
    153 |             _ => {}
        |             ^ help: try this: `Type::__TestExhaustive(_)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants

    error: wildcard matches only a single variant and will also match any future added variants
       --> serde_derive/src/bound.rs:190:17
        |
    190 |                 _ => {}
        |                 ^ help: try this: `syn::Type::__TestExhaustive(_)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants
2021-03-26 23:30:15 -04:00
David Tolnay e9270e59f0 Release 1.0.125 2021-03-22 16:15:57 -07:00
David Tolnay 72060b779a Extend test_format_u8 to include u8::MAX
This is equivalent to looping 0..=u8::MAX, except that `..=` syntax is
not supported on old rustc and `...` syntax is not supported on new
rustc, so loop it is.
2021-03-22 16:09:33 -07:00
David Tolnay 1bb23ad9d1 Remove format_u8 when not used by Ipv4Addr impl 2021-03-22 16:00:58 -07:00
David Tolnay 9be4c9654a Merge pull request 2001 from saethlin/optimize-ipaddr 2021-03-22 16:00:11 -07:00
Ben Kimock 4114e90bac Fix off-by-one mistake, explain the offset 2021-03-22 18:39:24 -04:00
Ben Kimock 8bb07b0743 skip UTF8 checking and initialize with b'.' 2021-03-22 18:15:50 -04:00
Ben Kimock ba8c1d63c8 use the algorithm from itoa 2021-03-16 17:33:42 -04:00
Ben Kimock 857a805993 Faster Ipv4 serialization prototype 2021-03-16 10:41:13 -04:00
David Tolnay 5a8dcac2ed Release 1.0.124 2021-03-05 19:55:40 -08:00
David Tolnay 697b082e90 Touch up PR 1997 2021-03-05 19:48:40 -08:00
David Tolnay d91075c8d5 Merge pull request #1997 from cyang1/systemtime-panics
Prevent various panics when deserializing malformed SystemTime
2021-03-05 18:35:48 -08:00
Cary Yang 4118cec731 Prevent various panics when deserializing malformed SystemTime 2021-03-05 17:52:51 -08:00
David Tolnay c261015325 Ignore incorrect suggestion from manual_map lint
https://github.com/rust-lang/rust-clippy/issues/6797

    error[E0382]: use of partially moved value: `self`
       --> serde_derive/src/internals/attr.rs:71:24
        |
    71  |         self.value.map(|value| (self.tokens, value))
        |                    ----^^^^^^^----------------------
        |                    |   |        |
        |                    |   |        use occurs due to use in closure
        |                    |   value used here after partial move
        |                    `self.value` partially moved due to this method call
        |
    note: this function takes ownership of the receiver `self`, which moves `self.value`
       --> /home/david/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:485:38
        |
    485 |     pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
        |                                      ^^^^
        = note: partial move occurs because `self.value` has type `std::option::Option<T>`, which does not implement the `Copy` trait
2021-02-25 20:53:45 -08:00
David Tolnay 6b5e5a83d0 Ignore let_underscore_drop pedantic clippy lint 2021-02-18 19:31:39 -08:00
David Tolnay bc6b2b1dee Make json5 description capitalization consistent with other links 2021-02-10 23:13:12 -08:00
David Tolnay beb21cb640 Ignore new missing_panics_doc pedantic clippy lint 2021-02-03 20:07:44 -08:00
David Tolnay 7cfebbcd72 Merge pull request #1974 from Mingun/new-internally-tagged-tests
New internally tagged tests
2021-02-02 15:23:10 -08:00
Mingun b60c03ec3f Extend test_internally_tagged_newtype_variant_containing_unit_struct to cover structs and seqs 2021-02-02 09:00:04 +05:00
Mingun 3257851192 Extend test_internally_tagged_struct_variant_containing_unit_variant to cover maps and seqs 2021-02-02 08:59:59 +05:00
David Tolnay 9a84622c56 Merge pull request #1971 from arthurprs/untagged-enum-fix-pr
Allow floats to be deserialized from ints in untagged unions (part 2)
2021-01-26 14:41:56 -08:00
Arthur Silva de8ac1c0be Allow floats to be deserialized from ints in untagged unions 2021-01-26 17:47:20 +01:00
David Tolnay 3d6c4149b1 Release 1.0.123 2021-01-25 13:43:11 -08:00
David Tolnay 29cdf888c0 Merge pull request #1970 from serde-rs/self
Support `Self` inside fields that use serialize_with
2021-01-25 13:42:35 -08:00
David Tolnay 2ba97394fb Substitute Self in output of Serialize derive 2021-01-25 13:34:09 -08:00
David Tolnay 6699b0bc40 Add regression test for issue 1969 2021-01-25 13:34:08 -08:00
David Tolnay b054ea4105 Ignore some pedantic lints in serde_derive_internals from PR 1830
error: item name ends with its containing module's name
      --> serde_derive_internals/src/receiver.rs:11:1
       |
    11 | / pub fn replace_receiver(input: &mut DeriveInput) {
    12 | |     let self_ty = {
    13 | |         let ident = &input.ident;
    14 | |         let ty_generics = input.generics.split_for_impl().1;
    ...  |
    19 | |     visitor.visit_data_mut(&mut input.data);
    20 | | }
       | |_^
       |
    note: the lint level is defined here
      --> serde_derive_internals/lib.rs:3:22
       |
    3  | #![deny(clippy::all, clippy::pedantic)]
       |                      ^^^^^^^^^^^^^^^^
       = note: `#[deny(clippy::module_name_repetitions)]` implied by `#[deny(clippy::pedantic)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions

    error: binding's name is too similar to existing binding
      --> serde_derive_internals/src/receiver.rs:31:29
       |
    31 |     fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
       |                             ^^^^^
       |
    note: the lint level is defined here
      --> serde_derive_internals/lib.rs:3:22
       |
    3  | #![deny(clippy::all, clippy::pedantic)]
       |                      ^^^^^^^^^^^^^^^^
       = note: `#[deny(clippy::similar_names)]` implied by `#[deny(clippy::pedantic)]`
    note: existing binding defined here
      --> serde_derive_internals/src/receiver.rs:31:23
       |
    31 |     fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
       |                       ^^^^
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#similar_names

    error: unused `self` argument
       --> serde_derive_internals/src/receiver.rs:286:24
        |
    286 |     fn visit_macro_mut(&mut self, _mac: &mut Macro) {}
        |                        ^^^^^^^^^
        |
    note: the lint level is defined here
       --> serde_derive_internals/lib.rs:3:22
        |
    3   | #![deny(clippy::all, clippy::pedantic)]
        |                      ^^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::unused_self)]` implied by `#[deny(clippy::pedantic)]`
        = help: consider refactoring to a associated function
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
2021-01-25 00:03:03 -08:00
David Tolnay e5efb6ad93 Remove dependency on syn/visit-mut feature 2021-01-24 23:56:57 -08:00
David Tolnay 1f423580a5 Deduplicate token stream respanner 2021-01-24 23:06:08 -08:00
David Tolnay 033114a4ae Touch up PR 1830 2021-01-24 23:06:07 -08:00
David Tolnay 7cec99c7fd Pare down PR 1830
Unlike expr macros, macros in type position in a derive input are rare
enough that it's not worth supporting for an issue that has such an easy
workaround (just replace `Self` in the macro input with your type name).
2021-01-24 23:06:06 -08:00
David Tolnay 6c5bf701be Merge pull request 1830 from taiki-e/self 2021-01-24 23:05:51 -08:00
David Tolnay 6e800ff826 Test exhaustiveness of type match in collect_lifetimes 2021-01-24 23:04:01 -08:00
David Tolnay 68bda7a004 Include serde crate in 1.31 CI job 2021-01-24 20:42:20 -08:00
David Tolnay dfeaf77bb2 Merge pull request #1966 from serde-rs/private
Omit derive helpers in versions older than serde_derive msrv
2021-01-24 20:40:06 -08:00
David Tolnay b0cc213e57 Omit derive helpers in versions older than serde_derive msrv 2021-01-24 20:26:56 -08:00
David Tolnay 74ca06662e Omit size_hint::cautious when not allocating 2021-01-24 20:24:03 -08:00
David Tolnay 38edb473de Move size_hint module out of private::de 2021-01-24 20:23:07 -08:00
David Tolnay 1c03647656 Move InPlaceSeed out of private mod 2021-01-24 20:23:06 -08:00
David Tolnay aeee73fe92 Merge pull request #1831 from taiki-e/borrow-macro
Collect lifetimes inside macro invocations
2021-01-24 19:08:20 -08:00
David Tolnay 1a3ef39040 Merge pull request #1842 from Timmmm/fix2
Allow floats to be deserialized from ints in tagged unions
2021-01-24 18:48:46 -08:00
David Tolnay deaf600af7 Merge pull request #1965 from serde-rs/int
Reduce post-macro-expansion code in integer deserialize impls
2021-01-24 18:43:36 -08:00
David Tolnay 48556a4c7f Reduce post-macro-expansion code in integer deserialize impls 2021-01-24 18:26:50 -08:00
David Tolnay d88a4748f7 Remove unused $ty arg from internal impl_deserialize_num macro 2021-01-24 17:06:36 -08:00
David Tolnay ffed19243d Release 1.0.122 2021-01-24 16:17:29 -08:00
David Tolnay bb7f94df84 Add serde_derive_internals to clippy CI job 2021-01-24 16:11:37 -08:00
David Tolnay ff0f467e25 Opt in to pedantic clippy lints in serde_derive_internals 2021-01-24 16:10:36 -08:00
David Tolnay d1975f3661 Update serde_derive_internals to tool attrs 2021-01-24 16:08:42 -08:00
David Tolnay b91713e824 Suppress clippy should_implement_trait lint
I think there is no ambiguity in from_str as a method name so "choose a
less ambiguous method name" is unnecessary, and it can't be a FromStr
impl in this case because FromStr's error type cannot borrow from the
input string slice.

    warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
      --> serde_derive_internals/src/case.rs:50:5
       |
    50 | /     pub fn from_str(rename_all_str: &str) -> Result<Self, ParseError> {
    51 | |         for (name, rule) in RENAME_RULES {
    52 | |             if rename_all_str == *name {
    53 | |                 return Ok(*rule);
    ...  |
    58 | |         })
    59 | |     }
       | |_____^
       |
       = note: `#[warn(clippy::should_implement_trait)]` on by default
       = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
2021-01-24 16:04:51 -08:00
David Tolnay 6ea446fb4b Suppress clippy unused_self pedantic lint
This usage is fine. It's mirroring trait signatures in syn::visit::Visit.

    error: unused `self` argument
       --> serde_derive/src/bound.rs:241:24
        |
    241 |         fn visit_macro(&mut self, _mac: &'ast syn::Macro) {}
        |                        ^^^^^^^^^
        |
    note: the lint level is defined here
       --> serde_derive/src/lib.rs:18:22
        |
    18  | #![deny(clippy::all, clippy::pedantic)]
        |                      ^^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::unused_self)]` implied by `#[deny(clippy::pedantic)]`
        = help: consider refactoring to a associated function
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
2021-01-24 16:01:05 -08:00
David Tolnay 85c6904a93 Remove dependency on syn/visit feature
The builtin visitor is fairly expensive to compile (3700 lines of code),
particularly if something else in the dependency graph also enables
syn/full. For the usage in serde_derive, it turns out to be easy to
replace.
2021-01-24 15:50:41 -08:00
David Tolnay 2fd5212204 Remove unused trait impls on private MapAsEnum 2021-01-23 23:19:48 -08:00
David Tolnay 7d1bc1f0fc Merge pull request #1963 from serde-rs/valuedebug
Eliminate inferred bound on error type of value deserializer Debug impls
2021-01-23 23:19:36 -08:00
David Tolnay cdc2fa1b9f Eliminate inferred bound on error type of value deserializer Debug impls 2021-01-23 23:15:41 -08:00
David Tolnay ac4001e590 Remove some unused trait impls from private UnitOnly variant accessor 2021-01-23 23:07:13 -08:00
David Tolnay fbcb2230bb Make use of fmt::Result type alias from libcore 2021-01-23 22:57:13 -08:00
David Tolnay 86c88bea12 Hide some irrelevant detail from de::value::Error's Debug impl 2021-01-23 22:49:00 -08:00
David Tolnay 82d0fe00fd Add link to rust-lang/rust#67295 2021-01-23 22:32:30 -08:00
David Tolnay e61261e002 Move doctest-only helpers to a doc module 2021-01-23 22:32:30 -08:00
David Tolnay 9fd56cd41c Remove unused __private_deserialize macro, originally for doctests 2021-01-23 22:26:16 -08:00
Taiki Endo e81f54fbc8 Make AST borrow checker happy 2021-01-24 15:23:54 +09:00
Taiki Endo c67017d466 Fix handling of Self keyword in type definition 2021-01-24 15:23:51 +09:00
David Tolnay f6e7366b46 Remove unused Debug impl on private::ser::content::Content 2021-01-23 22:10:48 -08:00
David Tolnay 1f9f72bc48 Merge pull request 1898 from Mingun/bytes-into-deserializer 2021-01-23 22:04:20 -08:00
David Tolnay e24dbc418d Skip another clone of the fallthrough arm 2021-01-23 20:52:03 -08:00
David Tolnay 18e5b03fd1 Merge pull request #1962 from serde-rs/dupborrowed
Eliminate duplicated borrowed and non-borrowed identifier deserialization
2021-01-23 20:51:56 -08:00
David Tolnay 5aa163f27e Revert "Regenerate macrotest outputs for PR #1917"
This reverts commit 999b94d6ae.
2021-01-23 20:36:26 -08:00
David Tolnay 3728d3c67a Eliminate duplicated borrowed and non-borrowed identifier deserialization 2021-01-23 20:32:38 -08:00
David Tolnay 3f48ed36cc Restore compatibility with rustc <1.31 in Borrowed identifier deserializer
The implied lifetime bound on T only works on 1.31+. Older versions fail
with:

    error[E0309]: the parameter type `T` may not live long enough
        --> serde/src/private/de.rs:2548:37
         |
    2548 | pub struct Borrowed<'de, T: ?Sized>(pub &'de T);
         |                          --         ^^^^^^^^^^
         |                          |
         |                          help: consider adding an explicit lifetime bound `T: 'de`...
         |
    note: ...so that the reference type `&'de T` does not outlive the data it points at
        --> serde/src/private/de.rs:2548:37
         |
    2548 | pub struct Borrowed<'de, T: ?Sized>(pub &'de T);
         |                                     ^^^^^^^^^^
2021-01-23 20:19:33 -08:00
David Tolnay b6a2d07f26 Return IdentifierDeserializer to just one associated type
The BorrowedDeserializer was added in #1917, but only makes sense for
&str and &[u8], not for u64 which also needs to be have an
IdentifierDeserializer impl.
2021-01-23 20:04:58 -08:00
David Tolnay 84ad76b2e5 Ignore too_many_lines clippy pedantic lint in serde_test
error: this function has too many lines (107/100)
       --> serde_test/src/de.rs:128:5
        |
    128 | /     fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    129 | |     where
    130 | |         V: Visitor<'de>,
    131 | |     {
    ...   |
    238 | |         }
    239 | |     }
        | |_____^
        |
    note: the lint level is defined here
       --> serde_test/src/lib.rs:149:52
        |
    149 | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                                    ^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::too_many_lines)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
2021-01-23 20:04:30 -08:00
David Tolnay e6b6602a42 Merge pull request 1914 from Mingun/seq-other 2021-01-23 19:50:39 -08:00
David Tolnay 999b94d6ae Regenerate macrotest outputs for PR #1917 2021-01-23 19:43:02 -08:00
David Tolnay fa6712d2bf Merge pull request #1918 from Mingun/fix-serde-test
Fix incorrect message in serializer tokens and correctly implement next_entry_seed
2021-01-23 15:02:32 -08:00
David Tolnay 012ea8eb84 Keep conditional compilation cfg naming consistent with serde crate
The serde crate's build.rs uses names like `core_duration` or
`integer128`, not `has_core_duration` / `has_integer128`.
2021-01-23 14:57:12 -08:00
David Tolnay 9add5812e2 Update track_caller cfg link to show what version it's in 2021-01-23 14:56:03 -08:00
David Tolnay 5fd52100b6 Merge pull request #1920 from Mingun/track_caller
Show correct location in error messages by tracking caller of utility `assert_tokens` functions
2021-01-23 14:54:24 -08:00
David Tolnay 6670a309ca Merge pull request #1961 from serde-rs/renamerule
Provide list of recognized rename rules on parse error
2021-01-23 14:50:02 -08:00
David Tolnay b7bad3a165 Restore compatibility with rustc 1.31 in RenameRule error
str::escape_debug wasn't stabilized until 1.34, whereas serde_derive
currently supports an oldest version of 1.31.
2021-01-23 14:40:44 -08:00
David Tolnay 4e002ece07 Provide list of recognized rename rules on parse error 2021-01-23 14:38:20 -08:00
David Tolnay eaccae2c46 Fix UPPERCASE rename rule variant to follow idiomatic variant naming
This shouldn't have been named this way in PR #1132.
2021-01-23 14:27:33 -08:00
David Tolnay 990a502c39 Parse rename rules based on table of rules
This will make it possible to reuse the same table of recognized rules
in the parse error message.
2021-01-23 14:24:21 -08:00
David Tolnay 661206d885 Merge pull request #1960 from serde-rs/renamerule
Deduplicate RenameRule parse error message generation
2021-01-23 14:23:09 -08:00
David Tolnay 51d4563ed1 Move RenameRule parse error message to a Display impl 2021-01-23 14:13:47 -08:00
David Tolnay 7db0982e58 Add error type to use for RenameRule parsing 2021-01-23 14:09:58 -08:00
David Tolnay ed04824f10 Move RenameRule parse from trait fn to associated
This will allow updating it to return an Err that borrows the input
string, which is not possible with FromStr.
2021-01-23 14:07:59 -08:00
David Tolnay 88ee470a1c Format PR #1916 with rustfmt 1.4.32 2021-01-23 13:39:12 -08:00
David Tolnay a5ecbdb4f4 Merge pull request 1916 from Mingun/expecting-customize 2021-01-23 13:38:45 -08:00
David Tolnay bd588db067 Release 1.0.121 2021-01-23 13:17:08 -08:00
David Tolnay 8f09aeacdd Merge pull request #1959 from serde-rs/1917
Touch up borrowed field identifiers PR
2021-01-23 13:15:30 -08:00
David Tolnay 0b5c56b0db Touch up documentation from PR #1917 2021-01-23 13:09:37 -08:00
David Tolnay 85de92e6f7 Inline forward_deserializer for bytes deserializers 2021-01-23 13:08:08 -08:00
David Tolnay c858a1fa77 Clean up unnecessary macro_use from PR #1917 2021-01-23 12:59:12 -08:00
David Tolnay d02eb22557 Inline some unnecessary constructor functions from PR #1917 2021-01-23 12:58:42 -08:00
David Tolnay 034fe25d5b Remove redundant unused trait impls from private types from PR #1917 2021-01-23 12:58:42 -08:00
David Tolnay 0a230e8598 Inline forward_deserializer into private::de for Str deserializers
We shouldn't try to use the same macro for public and private types. The
API for a private type can usually be pared much further down to save
compile time, such as Debug and Copy and Clone impls.
2021-01-23 12:57:35 -08:00
David Tolnay b20214d4a0 Undo macro exports from PR #1917
All of these macros are only used internally within the serde crate.
There is no need for them to have #[macro_export] and need to be hidden
from docs.
2021-01-23 12:40:01 -08:00
David Tolnay 34f4b68f77 Fix unneeded clone from PR #1917 2021-01-23 12:40:00 -08:00
David Tolnay 60e08f9545 Format PR #1917 with rustfmt 1.4.32 2021-01-23 12:39:59 -08:00
David Tolnay ba46f45dc5 Merge pull request 1917 from Mingun/borrow-identifier 2021-01-23 12:39:28 -08:00
David Tolnay 44b9567e21 Merge pull request #1958 from jonasbb/duration-panic
Prevent panic when deserializing malformed Duration
2021-01-23 00:45:39 -08:00
Jonas Bushart b276849ce1 Prevent panic when deserializing malformed Duration
std::time::Duration::new can panic. There is no alternative non-panicing constructor.
Check the panic condition beforehand and return an error instead of panicing.

Fixes #1933
2021-01-20 20:41:45 +01:00
David Tolnay 398fba9b1e Release 1.0.120 2021-01-18 22:55:13 -08:00
David Tolnay cd6697b0e4 Merge pull request #1955 from TheJokr/patch-1
Add 128-bit integer support to de::IgnoredAny
2021-01-18 22:54:43 -08:00
Leo Blöcher c162d51866 Add 128-bit integer support to de::IgnoredAny
This fixes the errors that occur when IgnoredAny is deserialized
from anything containing a 128-bit integer somewhere. As IgnoredAny
is used in serde_derive to skip ignored fields in structs, these
errors currently prevent parsing of structs with an ignored field
containing a 128-bit integer in the serialization.
2021-01-19 02:32:26 +01:00
David Tolnay 78a9dbc57e Merge pull request #1948 from Marwes/from_str
refactor: Merge multiple FromStr visitors to a single FromStrVisitor
2021-01-12 13:12:54 -08:00
David Tolnay 391d3ababf Touch up PR 1948 2021-01-12 13:08:50 -08:00
Markus Westerlind 99d9151ce9 refactor: Merge multiple FromStr visitors to a single FromStrVisitor
Only refactors, doesn't actually expose this visitor
2021-01-12 11:32:16 +01:00
David Tolnay 4c89cf89fd Release 1.0.119 2021-01-11 12:13:57 -08:00
David Tolnay b0c99ed761 Restore compatibility with rustc 1.13.0
error[E0432]: unresolved import `private::de::size_hint`
      --> src/de/value.rs:28:5
       |
    28 | use private::de::size_hint;
       |     ^^^^^^^^^^^^^^^^^^^^^^ Maybe a missing `extern crate private`?
2021-01-08 20:01:30 -08:00
David Tolnay dd1f4b483e Make it clearer that the private implementation details are private
Both of these modules are doc(hidden) and commented "Not public API",
but incorrect downstream code sometimes still references them. Naming
the module __private will make it more likely to be noticed in code
review.
2021-01-08 19:55:31 -08:00
David Tolnay 91bfa8f947 Refresh expandtest files with most recent rustfmt 2021-01-08 19:54:21 -08:00
David Tolnay 8847800ce2 Ignore from_over_into clippy lint in test suite 2021-01-03 19:05:43 -08:00
David Tolnay 3c9fa1ccdf Switch to short form for serde.rs link in rustdoc
Fixes a rustdoc warning:

    warning: unneeded long form for URL
      --> serde/src/lib.rs:12:27
       |
    12 | //! See the Serde website [https://serde.rs/] for additional documentation and
       |                           ^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://serde.rs/>`
       |
       = note: `#[warn(non_autolinks)]` on by default
2020-12-21 10:35:28 -08:00
David Tolnay 3c29a8857f Merge pull request #1936 from bryanburgers/add-serde-dynamo
Add serde_dynamo to the list of data formats
2020-12-21 10:33:45 -08:00
Bryan Burgers a5da27e16d Add serde_dynamo to the list of data formats 2020-12-21 10:51:56 -06:00
David Tolnay e797431268 Release 1.0.118 2020-12-05 13:45:47 -08:00
David Tolnay 4a335f8933 Merge pull request #1926 from attente/core-num-wrapping
Allow serializing of Wrapping without std
2020-12-05 13:43:20 -08:00
David Tolnay 84721920fd Resolve clippy items_after_statements lint
error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:1876:9
         |
    1876 | /         impl<'de> Deserialize<'de> for Field {
    1877 | |             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    1878 | |             where
    1879 | |                 D: Deserializer<'de>,
    ...    |
    1917 | |             }
    1918 | |         }
         | |_________^
         |
    note: the lint level is defined here
        --> serde/src/lib.rs:95:52
         |
    95   | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
         |                                                    ^^^^^^^^^^^^^^^
         = note: `#[deny(clippy::items_after_statements)]` implied by `#[deny(clippy::pedantic)]`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:1920:9
         |
    1920 |         struct DurationVisitor;
         |         ^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:1922:9
         |
    1922 | /         impl<'de> Visitor<'de> for DurationVisitor {
    1923 | |             type Value = Duration;
    1924 | |
    1925 | |             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    ...    |
    1979 | |             }
    1980 | |         }
         | |_________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:1982:9
         |
    1982 |         const FIELDS: &'static [&'static str] = &["secs", "nanos"];
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:2001:9
         |
    2001 | /         impl<'de> Deserialize<'de> for Field {
    2002 | |             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    2003 | |             where
    2004 | |                 D: Deserializer<'de>,
    ...    |
    2042 | |             }
    2043 | |         }
         | |_________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:2045:9
         |
    2045 |         struct DurationVisitor;
         |         ^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:2047:9
         |
    2047 | /         impl<'de> Visitor<'de> for DurationVisitor {
    2048 | |             type Value = Duration;
    2049 | |
    2050 | |             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    ...    |
    2108 | |             }
    2109 | |         }
         | |_________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements

    error: adding items after statements is confusing, since items exist from the start of the scope
        --> serde/src/de/impls.rs:2111:9
         |
    2111 |         const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
2020-11-28 19:08:41 -08:00
David Tolnay 192c7819ee Format with rustfmt 1.4.25-beta 2020-11-28 19:06:37 -08:00
William Hua ede40bdfaa Allow serializing of Wrapping without std 2020-11-24 00:56:10 -05:00
David Tolnay e3d871ff7b Opt in to experimental trybuild diffs 2020-10-31 13:28:19 -07:00
Mingun 5cbc8439ea Show correct location in error messages by tracking caller of utility assert_tokens functions 2020-10-28 09:11:54 +05:00
David Tolnay 0e1c4093c8 Suppress new result_unit_err clippy lint 2020-10-27 19:20:45 -07:00
David Tolnay 0d5b6c180c Resolve ptr_eq clippy lint
error: use `std::ptr::eq` when comparing raw pointers
       --> serde_derive/src/de.rs:362:12
        |
    362 |         if field as *const Field == transparent_field as *const Field {
        |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(field, transparent_field)`
        |
    note: the lint level is defined here
       --> serde_derive/src/lib.rs:18:9
        |
    18  | #![deny(clippy::all, clippy::pedantic)]
        |         ^^^^^^^^^^^
        = note: `#[deny(clippy::ptr_eq)]` implied by `#[deny(clippy::all)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
2020-10-27 19:18:29 -07:00
Mingun 97c350a95e Forward Readable|Compact next_entry_seed to underlying next_entry_seed instead of usage of default implementation
Difference is noticeable for deserializers that rely on call of next_entry_seed
(for example, current quick-xml supports only next_entry_seed)
2020-10-28 01:05:27 +05:00
Mingun 920a77ad61 Fix incorrect messages in serialized tokens assertions
Serializer contains expected tokens, called methods provide actual tokens
2020-10-28 01:05:27 +05:00
Taiki Endo a227a87865 Collect lifetimes inside macro invocations 2020-10-24 05:29:47 +09:00
Mingun 7a7a182ab6 Allow borrow for field identifiers 2020-10-23 19:03:18 +05:00
Mingun 9e1f573f88 Use forward_deserializer macro for define StrDeserializer for IdentifierDeserializer 2020-10-23 19:03:18 +05:00
Mingun 094f63b86a Introduce a forward_deserializer macro.
It helps to create deserializers that can stop time: save the value and then use visitor to get it later!
2020-10-23 19:03:14 +05:00
Mingun 42fa79455e Make BytesDeserializer public 2020-10-23 12:13:57 +05:00
Mingun 104ad9a7dd Allow to define custom expectation message for type with #[serde(expecting = "...")]
Closes #1883
2020-10-23 01:23:01 +05:00
Mingun 23c14e5f33 Allow to run assert_de_tokens_error on token sequence that is not expected by enum deserializer
Before that fix following code panics, because `Token::Unit` was unexpected by test deserializer:
```
#[derive(Deserialize)]
enum E { ... }

assert_de_tokens_error::<E>(&[Token::Unit], "...");
```
2020-10-22 23:50:48 +05:00
Mingun e80571751d Allow borrowed and owned strings and bytes and u8, u16, u64 for variant keys in serde_test 2020-10-22 20:43:14 +05:00
Mingun 0737474640 Allow field identifiers be any numbers if #[serde(other)] is used
Thus behavior synchronized between string/bytes identifiers and numeric identifiers
2020-10-22 16:35:28 +05:00
Mingun 34de1e00c8 Implement IdentifierDeserializer for u64 instead of u32 because all identifiers deserialized with visit_u64 2020-10-22 16:35:28 +05:00
Mingun f6eb34a830 Assert that numeric field identifiers correctly deserialized (now failing) 2020-10-22 16:35:28 +05:00
David Tolnay 8084258a3e Update ui tests to nightly-2020-10-20 2020-10-20 19:17:50 -07:00
David Tolnay fc3f104c4a Release 1.0.117 2020-10-15 09:49:03 -07:00
David Tolnay 4bec9ffd0f Merge pull request #1906 from Mingun/fix-misprint
Fix misprint in the error message
2020-10-11 12:13:03 -07:00
Mingun e6d2322e68 Fix misprint in the error message 2020-10-12 00:03:21 +05:00
David Tolnay 2b504099e4 Include room for SocketAddrV6 to serialize scope id
https://github.com/rust-lang/rust/pull/77426
2020-10-05 04:02:05 -07:00
Mingun db3074a40f Implement IntoDeserializer for Cow<[u8]> 2020-10-04 13:38:31 +05:00
Mingun 2e821eab4b Make impl IntoDeserializer for &[u8] public 2020-10-03 16:43:31 +05:00
David Tolnay be7d0e7eb2 Ignore map_err_ignore Clippy pedantic lint 2020-09-25 21:55:59 -04:00
David Tolnay b539cb45d7 Release 1.0.116 2020-09-11 11:56:19 -07:00
David Tolnay a5490e20e1 Merge pull request #1888 from joshtriplett/fix-enum-deserialization-u64
Fix hand-written enum variant deserializations to allow u64 discriminant
2020-09-11 11:55:35 -07:00
Josh Triplett 45c45e87bf Fix hand-written enum variant deserializations to allow u64 discriminant
Automatically generated enum variant deserializers allowed any integer
type as the discriminant, but the hand-written ones for specific enum
types such as Result or IpAddr only allowed types up to u32. This broke
some non-human-readable deserializers for these enums, with
deserializers that emit any integer type as a u64. Switch the visit_u32
methods to visit_u64 methods to allow discriminants to have any size up
to a u64.
2020-09-10 23:24:33 -07:00
David Tolnay 2e76f7013f Update code of conduct link 2020-09-05 13:09:37 -07:00
David Tolnay d35de19120 Merge pull request #1885 from dtolnay/qs
Replace serde_urlencoded link with serde_qs
2020-09-05 10:35:12 -07:00
David Tolnay e5b3507145 Replace serde_urlencoded link with serde_qs 2020-09-05 10:26:36 -07:00
David Tolnay 7ea7c2ceb9 Merge pull request #1882 from dtolnay/bincode
Rename TyOverby/bincode to servo/bincode
2020-08-28 15:43:00 -07:00
David Tolnay 2b5b15967e Rename TyOverby/bincode to servo/bincode 2020-08-28 15:36:51 -07:00
David Tolnay 2ef60b62ac Release 1.0.115 2020-08-10 15:51:19 -07:00
David Tolnay e6f086d85e Merge pull request #1874 from dtolnay/flatunit
Support flattening a Unit
2020-08-10 15:50:30 -07:00
David Tolnay bf76f50294 Support deserializing flattened unit 2020-08-10 15:06:52 -07:00
David Tolnay ba07075590 Support serializing flattened unit 2020-08-10 15:06:47 -07:00
David Tolnay 26186bddd1 Add test for flattened unit 2020-08-10 15:06:34 -07:00
David Tolnay 53b9871b17 Quote no longer requires high recursion 2020-07-16 10:49:16 -07:00
David Tolnay f8787c3ca8 Suppress match_like_matches_macro clippy lint 2020-07-14 18:57:26 -07:00
David Tolnay 3022064f84 Suppress option_if_let_else clippy pedantic lint 2020-07-14 18:57:24 -07:00
David Tolnay 9e140a2071 Tweak yaml format blurb 2020-07-05 20:00:33 -07:00
David Tolnay 24e6acbfae Drop 'help or discussion' issue template
Per https://github.com/serde-rs/serde#getting-help we're steering these
to Discord / Stack Overflow / Reddit / etc.

Can reconsider when GitHub Discussions is out of beta
(https://github.com/vercel/next.js/discussions).
2020-07-04 20:44:22 -07:00
David Tolnay 29c5a50935 Suppress unused_attributes warning in test suite
This test has multiple #[ignore] attributes in some configurations.

    $ cargo +beta check --test expandtest
    warning: unused attribute
     --> test_suite/tests/expandtest.rs:2:29
      |
    2 | #[cfg_attr(not(expandtest), ignore)]
      |                             ^^^^^^
      |
      = note: `#[warn(unused_attributes)]` on by default
2020-06-26 21:37:30 -07:00
David Tolnay c619b2a7c4 Suppress unknown_lints warning in test suite
When building with beta and older rustc:

    error: unknown lint: `mixed_script_confusables`
     --> test_suite/tests/test_gen.rs:7:10
      |
    7 | #![allow(mixed_script_confusables, clippy::trivially_copy_pass_by_ref)]
      |          ^^^^^^^^^^^^^^^^^^^^^^^^
      |
    note: the lint level is defined here
     --> test_suite/tests/test_gen.rs:5:9
      |
    5 | #![deny(warnings)]
      |         ^^^^^^^^
      = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]`
2020-06-26 21:37:26 -07:00
David Tolnay 764ebd9b17 Suppress mixed_script_confusables in test suite
error: The usage of Script Group `Greek` in this crate consists solely of mixed script confusables
       --> test_suite/tests/test_gen.rs:269:9
        |
    269 |         σ: f64,
        |         ^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(mixed_script_confusables)]` implied by `#[deny(warnings)]`
        = note: The usage includes 'σ' (U+03C3).
        = note: Please recheck to make sure their usages are indeed what you want.
2020-06-26 19:06:13 -07:00
Tim Hutt 010444dfa4 Allow floats to be deserialized from ints in tagged unions 2020-06-22 16:31:13 +01:00
David Tolnay 9c6f0c3a0e Release 1.0.114 2020-06-21 17:31:02 -07:00
David Tolnay a9f8ea0a1e Simplify search for packed repr attr 2020-06-21 17:22:07 -07:00
David Tolnay 04faac962a Remove error_on_line_overflow rustfmt setting
No longer seeing warnings on this from rustfmt.
2020-06-21 16:48:22 -07:00
Tanner Rogalsky 7e5701ad2b add alignment specific packed repr tests 2020-06-21 16:46:27 -07:00
Tanner Rogalsky 1cd10a7d09 Improved packed repr matching. 2020-06-21 16:46:27 -07:00
Tanner Rogalsky d5e6436b28 Add tests validating Serialize derivation for packed structs. 2020-06-21 16:46:27 -07:00
David Tolnay 8ff11dc234 Merge pull request #1841 from dtolnay/lenhint
Remove len hint specialization
2020-06-20 19:08:34 -07:00
David Tolnay 6b3777b617 Remove len hint specialization 2020-06-20 19:02:26 -07:00
David Tolnay 7350b58f5c Release 1.0.113 2020-06-19 13:31:38 -07:00
David Tolnay 7351e0e55a Link to feature announcements where available 2020-06-19 13:30:14 -07:00
David Tolnay b3ff7e43ef Merge pull request #1827 from taiki-e/underscore_consts
Use underscore consts on Rust 1.37+
2020-06-19 13:27:33 -07:00
Taiki Endo a50e1c20e9 Use underscore consts on Rust 1.37+ 2020-06-19 15:55:43 +09:00
David Tolnay 6980727d74 Merge pull request #1840 from rw/patch-1
Add FlexBuffers to serde ecosystem list
2020-06-18 22:57:59 -07:00
Robert Winslow bb1dedf04d Add FlexBuffers to serde ecosystem list
Add FlexBuffers to serde ecosystem list
2020-06-16 13:36:14 -07:00
David Tolnay f3520e526b Release 1.0.112 2020-06-14 11:16:04 -07:00
David Tolnay e8fd2c85c3 Merge pull request #1839 from dtolnay/entry
Forward serialize_entry on flattened maps
2020-06-14 11:15:26 -07:00
David Tolnay 97962d51e2 Forward serialize_entry on flattened maps 2020-06-14 11:10:18 -07:00
David Tolnay 95b1a5d3d9 Ignore unnested_or_patterns suggesting unstable code
Clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
2020-06-10 19:41:16 -07:00
David Tolnay 0856a2c101 No need to specify Cargo.toml in package.include
Cargo.toml is always included in the published crate.
2020-06-10 01:21:19 -07:00
David Tolnay 9f331cc257 Release 1.0.111 2020-05-29 18:53:07 -07:00
David Tolnay ef16c815f6 Merge pull request #1821 from dtolnay/ungroup
Look inside of None-delimited groups when examining types
2020-05-29 18:11:14 -07:00
David Tolnay c45a809d5c Look inside of None-delimited groups when examining types 2020-05-29 17:58:34 -07:00
David Tolnay f7d06cae4c Add failing test involving macro_rules metavariable 2020-05-29 17:58:10 -07:00
David Tolnay 31fe82a215 Resolve match_wildcard_for_single_variants pedantic lint 2020-05-29 17:46:40 -07:00
David Tolnay ef6ed1d1be Copy some new links from serde.rs to the crate-level doc 2020-05-22 12:49:15 -07:00
David Tolnay 9d1251548b Mirror 'Getting help' from github readme to crates.io readme 2020-05-15 23:09:48 -07:00
David Tolnay c20730ee39 Remove reference to mozilla irc 2020-05-15 23:07:35 -07:00
David Tolnay afd51ef0f4 Merge pull request #1808 from dtolnay/help
Update 'Getting help' section
2020-05-09 23:38:40 -07:00
David Tolnay 3167f98689 Update 'Getting help' section 2020-05-09 23:34:38 -07:00
David Tolnay 078b171c1b Release 1.0.110 2020-05-09 23:06:56 -07:00
David Tolnay da8d6f678e Simplify finding of repr(packed) attributes 2020-05-09 23:02:49 -07:00
David Tolnay 548eb8f667 Format PR 1791 with rustfmt 2020-05-09 22:54:42 -07:00
David Tolnay 1fe39043ee Simplify access of packed struct fields in derived Serialize impls 2020-05-09 22:53:38 -07:00
David Tolnay c2114491ca Add test of Serialize impl for packed struct 2020-05-09 22:52:49 -07:00
alvardes 9f47c47cad Add support for packed structs. 2020-05-09 22:45:44 -07:00
David Tolnay d6b39fd2c1 Merge pull request #1807 from dtolnay/31
Add a CI builder on 1.31.0
2020-05-09 22:44:41 -07:00
David Tolnay 4d6d0ae539 Add a CI builder on 1.31.0 2020-05-09 22:38:26 -07:00
David Tolnay dda070f45c Fix borrow error on pre-NLL compilers
error[E0506]: cannot assign to `missing_content` because it is borrowed
        --> serde_derive/src/de.rs:1414:9
         |
    1388 |           .filter_map(|(i, variant)| {
         |                       -------------- borrow of `missing_content` occurs here
    ...
    1414 | /         missing_content = quote! {
    1415 | |             match __field {
    1416 | |                 #(#missing_content_arms)*
    1417 | |                 #missing_content_fallthrough
    1418 | |             }
    1419 | |         };
         | |_________^ assignment to borrowed `missing_content` occurs here

    error[E0502]: cannot borrow `missing_content_fallthrough` as immutable because it is also borrowed as mutable
        --> serde_derive/src/de.rs:1414:27
         |
    1388 |           .filter_map(|(i, variant)| {
         |                       -------------- mutable borrow occurs here
    ...
    1404 |                       missing_content_fallthrough = quote!(_ => #missing_content);
         |                       --------------------------- previous borrow occurs due to use of `missing_content_fallthrough` in closure
    ...
    1414 |           missing_content = quote! {
         |  ___________________________^
    1415 | |             match __field {
    1416 | |                 #(#missing_content_arms)*
    1417 | |                 #missing_content_fallthrough
    1418 | |             }
    1419 | |         };
         | |_________^ immutable borrow occurs here
    ...
    1622 |   }
         |   - mutable borrow ends here
         |
         = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
2020-05-09 22:37:31 -07:00
David Tolnay b97a183e82 Release 1.0.109 2020-05-09 21:00:51 -07:00
David Tolnay 9433004307 Omit missing content match if not needed 2020-05-09 20:59:01 -07:00
David Tolnay 9476838264 Omit missing content fallthrough arm if not needed 2020-05-09 20:59:00 -07:00
asdsad 172edc4cf4 Allow optional content field for adjacently tagged newtype variants
* Deserialize adjacently tagged newtype variants with optional content as None instead of erroring when content field is missing

* refactor to remove duplicate code and remove panic
2020-05-09 20:58:28 -07:00
David Tolnay 3c97e1b9a9 Format PR 1702 with rustfmt 2020-05-09 18:24:05 -07:00
ppc a81968af3c Turn panic to error in SystemTime serialization 2020-05-09 18:22:29 -07:00
David Tolnay ea2789df0f Release 1.0.108 2020-05-09 17:53:23 -07:00
David Tolnay b7cfe33101 Add example usage to Formatter Serializer impl 2020-05-09 17:48:27 -07:00
David Tolnay 1b8ebf6b64 Add 128-bit integer support for Formatter 2020-05-09 17:48:27 -07:00
David Tolnay 35ad468780 Allow serializing newtype struct to Formatter
Serialize_newtype_struct is typically expected to just pass through the
wrapped value.
2020-05-09 17:48:27 -07:00
David Tolnay 850a29beb1 Directly display to the Formatter
This allows formatter flags to take effect.
2020-05-09 17:48:26 -07:00
David Tolnay 16bf9871cd Remove serialize_unit from Formatter's impl 2020-05-09 17:48:26 -07:00
David Tolnay 6182eceed1 Move the Formatter Serializer to a module
Let's keep impls.rs for Serialize impls, which there are enough of
already.
2020-05-09 17:48:26 -07:00
David Tolnay 99bc52f685 Support no-default-features mode in Formatter's impl 2020-05-09 17:48:26 -07:00
Jethro Beekman 726ff5ed31 impl Serializer for &mut fmt::Formatter 2020-05-09 17:48:13 -07:00
David Tolnay f63acb52dc Release 1.0.107 2020-05-08 15:45:36 -07:00
David Tolnay 36a66873cc Merge pull request #1805 from dtolnay/skip
Fix indexing bug when `skip` and `other` are combined
2020-05-08 15:43:51 -07:00
David Tolnay 63809e69c7 Fix indexing bug when skip and other are combined 2020-05-08 15:39:07 -07:00
David Tolnay f44402e224 Add regression test for issue 1804 2020-05-08 15:38:44 -07:00
David Tolnay 099fa25b86 Fix unused matrix component in name of clippy job 2020-05-06 01:53:58 -07:00
David Tolnay c120c4518b Move clippy to ci.yml gated with github.event_name != 'pull_request' 2020-05-05 22:09:35 -07:00
David Tolnay 115c1b4830 Exclude expansion tests from test suite by default
This test isn't high enough signal to have all contributors run it.
2020-05-05 21:52:37 -07:00
David Tolnay 23db3a41e7 Run expansion tests only if rustfmt is present 2020-05-05 21:50:14 -07:00
David Tolnay e2ff603587 Add Actions job to run macrotest 2020-05-05 17:41:35 -07:00
David Tolnay 19a11237b8 Regenerate macrotest *.expanded.rs files
This picks up changes from a135199ab1 and 1b35c9e27e.
2020-05-05 17:23:30 -07:00
David Tolnay 732544aed6 Update to macrotest 1.0 2020-05-05 17:23:30 -07:00
David Tolnay 65dfa607c8 Update to rustversion 1.0 2020-05-05 17:23:30 -07:00
David Tolnay 59104bbc24 Remove AppVeyor configuration 2020-05-05 17:08:09 -07:00
David Tolnay 38ad09aeb7 Add Windows CI in GitHub Actions 2020-05-05 17:08:09 -07:00
David Tolnay 02631cef42 Remove clippy from main CI workflow
We don't run clippy on PRs. It is covered by a separate clippy.yml
workflow.
2020-05-05 17:04:51 -07:00
David Tolnay f369707dc5 Update build status badge to GitHub Actions 2020-05-05 16:43:36 -07:00
David Tolnay e16e924c21 Split test suite to its own Actions job
Since this step takes the longest.
2020-05-05 16:39:36 -07:00
David Tolnay 8b52ddd5b9 Add GitHub Actions workflow to run Clippy 2020-05-05 16:34:27 -07:00
David Tolnay 112f2040ea Remove Travis configuration 2020-05-05 11:33:56 -07:00
David Tolnay cd836eb3ca Try caching Cargo index to speed up 1.13 build
This one build always took several (10+) minutes on:

    Updating registry `https://github.com/rust-lang/crates.io-index`
2020-05-03 17:59:26 -07:00
David Tolnay 2b4355724e Merge pull request #1795 from serde-rs/actions
Enable GitHub Actions
2020-05-03 02:38:48 -07:00
David Tolnay 5534bf4df1 Enable GitHub Actions 2020-05-03 02:23:04 -07:00
David Tolnay 60522937af Remove CI badge from Cargo.toml
Support for badges has been deprecated by crates.io.
2020-05-01 21:11:02 -07:00
David Tolnay 29be721f79 Work around clippy redundant_field_names bug 2020-04-23 11:21:28 -07:00
David Tolnay 0c4ffad9ec Run clippy on latest nightly that has clippy 2020-04-23 10:44:12 -07:00
David Tolnay 03addbae55 Format with rustfmt 2020-03-11 2020-04-19 17:32:11 -07:00
David Tolnay 0bab6be124 Resolve redundant_pattern_matching lint 2020-04-19 17:31:15 -07:00
David Tolnay b6def5300a Resolve redundant_field_names lint in serde_derive 2020-04-05 21:07:52 -07:00
David Tolnay 1b35c9e27e Update serde_derive to tool attrs 2020-04-05 21:00:58 -07:00
David Tolnay d1564525ad Release 1.0.106 2020-04-03 14:26:42 -07:00
David Tolnay 645f672a55 Merge pull request #1768 from robo9k/dummy-const-hidden-doc
Hide generated dummy const in rustdoc
2020-04-03 14:25:50 -07:00
robo9k a135199ab1 Hide generated dummy const in rustdoc 2020-04-03 22:21:38 +02:00
David Tolnay 2a9971a69d Merge pull request #1764 from serde-rs/collect
Simplify default Serializer::collect_str implementation
2020-03-27 23:10:06 -07:00
David Tolnay e2ada0efef Simplify default Serializer::collect_str implementation 2020-03-27 22:55:25 -07:00
David Tolnay 69653a762d Release 1.0.105 2020-03-18 11:42:51 -07:00
David Tolnay c33fb95127 Merge pull request #1754 from maciejhirsz/non-std-cow-borrow
Allow #[serde(borrow)] for non-std Cow
2020-03-18 11:40:35 -07:00
Maciej Hirsz ec6ca6bf73 Allow non-std Cow borrows 2020-03-18 13:34:38 +01:00
David Tolnay 078e88b223 Select a single docs.rs build target 2020-03-17 13:31:35 -07:00
David Tolnay 1894cb703f Resolve clippy question_mark lint 2020-03-05 19:48:07 -08:00
David Tolnay 27c283ab53 Suppress wildcard import pedantic lints 2020-02-26 21:00:12 -08:00
David Tolnay 142955b109 Ignore struct_excessive_bools pedantic lint 2020-02-12 19:34:14 -08:00
David Tolnay a61cd0f236 Update ui tests to nightly-2020-02-08 2020-02-08 00:10:00 -08:00
David Tolnay cb1632e957 Fix unused_parens lint
These are left over from a series of unfortunate rustfmt interactions.
https://github.com/serde-rs/serde/commit/ee75e6c0e9e5cc359163202554feb00a28b62d0d#diff-c052b162f01a664f8184ef1855d1f1cfL767-R735
https://github.com/serde-rs/serde/commit/cc2558b0dc6fd0a40f45c5c5fc3088332b4d6cdf#diff-c052b162f01a664f8184ef1855d1f1cfL733-R738
https://github.com/serde-rs/serde/commit/9f38ca032e0735109adbde10a9f16822a4b975aa#diff-c052b162f01a664f8184ef1855d1f1cfL779-R782
2020-01-25 00:05:15 -08:00
David Tolnay dbf1f9ab8f Remove unneeded type ascription 2020-01-17 19:50:48 -08:00
David Tolnay 137ab48aff Suppress unseparated_literal_suffix lint 2020-01-17 19:50:09 -08:00
David Tolnay fc43def8a3 Merge pull request #1721 from WildCryptoFox/remove-unsafe-code
remove the tiny bit of unsafe code
2020-01-17 14:13:35 -08:00
James McGlashan 2a351016ed remove the tiny bit of unsafe code 2020-01-17 00:00:00 +00:00
David Tolnay dfa321a1dd Ignore wildcard_in_or_patterns lint 2020-01-14 20:31:03 -08:00
David Tolnay 895eb2ba6c Update ui tests to nightly-2019-12-19 2019-12-18 23:46:29 -08:00
David Tolnay cd365de70c Update ui tests to nightly-2019-12-18 2019-12-17 23:47:40 -08:00
David Tolnay 7f799f3948 Ignore missing_errors_doc pedantic lint 2019-12-15 20:16:22 -08:00
David Tolnay 234fbfd7e3 Release 1.0.104 2019-12-15 20:01:04 -08:00
David Tolnay b9909cef3d Revert "Remove never_type feature gate"
This reverts commit 533fb9cc44.
2019-12-15 19:52:59 -08:00
David Tolnay d540e72fc7 Format with rustfmt 2019-10-07 2019-11-26 00:02:11 -08:00
David Tolnay 13d0899776 Add missing import in de_enum expand test 2019-11-26 00:00:05 -08:00
David Tolnay 4fefa7a01d Format imports in expandtest inputs 2019-11-25 23:57:34 -08:00
David Tolnay 90486607a1 Update test suite to nightly-2019-11-26 2019-11-25 23:51:43 -08:00
David Tolnay 0b303c766c Mark tests ignored on emscripten rather than omitting
This way they still appear in `cargo test`'s output.
2019-11-24 17:27:30 -08:00
David Tolnay c371563bfc Reduce nesting of macrotest test cases 2019-11-24 17:25:44 -08:00
David Tolnay d17d8eb3ee Rely on std::process::Command's path search 2019-11-24 17:23:02 -08:00
David Tolnay bcaebdb2b7 Merge pull request #1662 from eupn/use-macrotest
Implement expansion tests
2019-11-24 17:14:35 -08:00
David Tolnay 43a9f59c18 Release 1.0.103 2019-11-24 16:15:13 -08:00
David Tolnay ff70409215 Merge pull request #1669 from H2CO3/master
Allow untagged unit variants to deserialize from `Visitor::visit_none()`
2019-11-24 16:13:37 -08:00
David Tolnay 97a98a7031 Test only deser for untagged unit visit_none 2019-11-24 15:59:08 -08:00
David Tolnay 533fb9cc44 Remove never_type feature gate
The stabilization for this feature has landed in nightly.
2019-11-23 19:30:39 -08:00
Árpád Goretity 59b99d2d60 Move test for untagged-variant-from-unit where it belongs 2019-11-07 21:18:12 +01:00
Árpád Goretity c796daed7c Fix test for untagged unit variant 2019-11-07 12:58:09 +01:00
Árpád Goretity 6e2c385fa5 Allow untagged unit variants to deserialize from Visitor::visit_none() 2019-11-06 17:31:27 +01:00
Evgenii P 9a0e4e0176 Ignore expansion test if cargo-expand subcommand isn't present 2019-11-03 20:31:08 +08:00
Evgenii P 640f8e0e82 Remove stdlib derives and fix expanded files to have newlines at the end 2019-11-03 20:08:39 +08:00
David Tolnay 4eb580790d Require serde_derive version to be the same as serde version
Without this, Cargo could combine new serde_derive with old serde
resulting in generated code that refers to types that don't exist yet in
the serde version.
2019-11-02 15:17:09 -07:00
David Tolnay a2c83d754b Merge pull request #1664 from mathstuf/minimal-versions-compat
serde_derive: require the same version as serde
2019-11-02 12:04:20 -07:00
Ben Boeckel 6f946b20ec serde_derive: require the same version as serde
This ensures that all features supported by serde are always available
through the derive macro provided through the feature flag.

Fixes: #1647
2019-11-01 19:47:31 -04:00
Evgenii P 4dda90502a Add *.expanded.rs files 2019-11-01 02:32:34 +08:00
Evgenii P dc6dbba47c Implement derive macros expansion tests using macrotest 2019-11-01 02:32:06 +08:00
David Tolnay 2ceabad360 Release 1.0.102 2019-10-27 13:39:27 -07:00
David Tolnay a00aee1495 Use a dedicated cfg for PathBuf::into_boxed_path 2019-10-27 13:38:25 -07:00
David Tolnay 4e31c9984d Merge pull request #1656 from heftig/path-improvements
Improve Path deserialization
2019-10-27 13:37:12 -07:00
Jan Alexander Steffens (heftig) b8772a1e40 Deserialize Box<Path> through PathBuf::into_boxed_path
Including Rc<Path> et al.

Fixes https://github.com/serde-rs/serde/issues/1633
2019-10-22 22:31:51 +02:00
Jan Alexander Steffens (heftig) 42990d8264 Deserialize PathBuf from bytes
&Path already allows this. Also complete the tests for Path/PathBuf.
2019-10-22 22:30:53 +02:00
David Tolnay cf31418555 Resolve unused_self lint 2019-10-17 11:05:30 -04:00
David Tolnay 5db72b8ad9 Ignore must_use_candidate pedantic lint 2019-10-17 11:05:28 -04:00
David Tolnay fe8f8bcf7b Address needless_doctest_main lint in serde_test 2019-10-08 21:23:17 -07:00
David Tolnay d4d737de8d Resolve redundant_clone lint 2019-10-08 21:16:45 -07:00
David Tolnay 52f6e96ee8 Ignore needless_doctest_main lint 2019-10-08 21:15:08 -07:00
David Tolnay 44fa7b0f6b Remove unused rustc-serialize dependency from test suite 2019-10-04 21:29:06 -04:00
David Tolnay bda561df4e Update test suite to nightly-2019-10-04 2019-10-03 21:45:09 -04:00
David Tolnay 8955420baf Update test suite to nightly-2019-10-02 2019-10-02 09:45:00 -04:00
David Tolnay 21ee256911 Update test suite to nightly-2019-09-30 2019-09-30 15:56:04 -04:00
David Tolnay 4aba6fae78 Release 1.0.101 2019-09-16 00:32:28 -07:00
David Tolnay fe06bc2f88 More concise explanation of allow(unused_variables) 2019-09-16 00:31:23 -07:00
David Tolnay 8dfb4cd02f Merge pull request #1617 from arilotter/master
Fix unused variable warning when field of adjacently tagged enum is skipped
2019-09-15 23:51:39 -07:00
David Tolnay d1ade37827 Ignore new too_many_lines lint 2019-09-10 23:15:59 -07:00
Ari Lotter 9de49241fb Bug fix for #1610
Allow unused variables in tuple in AdjacentlyTagged serializer
2019-09-09 10:43:05 -04:00
David Tolnay b24d50160a Remove use of ref keyword from serde_derive 2019-09-07 23:16:02 -07:00
David Tolnay e46463e69f Add tests for attribute parse errors 2019-09-07 22:57:27 -07:00
David Tolnay a3157c9572 Produce errors on attr that fails to parse as Meta 2019-09-07 22:46:50 -07:00
David Tolnay 0d4722680a Use flatten() to iterate serde meta items 2019-09-07 22:44:25 -07:00
David Tolnay 7ab12597bb Un-wrap error message strings for better grepping 2019-09-07 22:40:24 -07:00
David Tolnay b86a46c83c Factor skipping in newtype variants into effective_style 2019-09-07 22:16:56 -07:00
David Tolnay 187a0a3ec0 Format with rustfmt 2019-08-19 2019-09-07 22:16:49 -07:00
David Tolnay 111c18dec3 Merge pull request #1622 from Xaeroxe/fix-new-types
Fix (de)serialization of new types where the internal type is skipped
2019-09-07 22:16:40 -07:00
David Tolnay 7a2b137912 Reuse span in default deserialize_with path for Cows 2019-09-07 20:24:59 -07:00
David Tolnay 791b9fbe81 Release serde_derive_internals 2019-09-07 20:14:30 -07:00
David Tolnay 0fdc0257aa Sort Postcard in the same order as on the website 2019-09-07 19:10:48 -07:00
David Tolnay b6a77c4413 Release 1.0.100 2019-09-07 18:55:50 -07:00
David Tolnay 33438850a6 Merge pull request #1620 from dtolnay/error
Export std error type so no_std data formats don't need a "std" feature
2019-09-07 18:54:34 -07:00
Jake Kiesel fcbb3d3783 Add support for other enum representations 2019-09-07 11:43:53 -06:00
Jake Kiesel acc8640c1e Fix (de)serialization of new types where the internal type is skipped 2019-09-07 03:20:43 -06:00
David Tolnay c083cfd65e Export std error type so downstream doesn't need "std" feature 2019-09-04 20:20:36 -07:00
David Tolnay 4cea81f93f Merge pull request #1615 from jamesmunns/patch-1
Add Postcard to the list of Serde Data Formats
2019-08-28 10:17:43 -07:00
James Munns 2d36be753a Add Postcard to the list of Serde Data Formats 2019-08-28 12:23:54 +02:00
David Tolnay 738d29eaa9 Update serde_derive_internals to syn 1.0 2019-08-26 12:29:45 -07:00
David Tolnay b536fb67a4 Merge pull request #1604 from UnHumbleBen/patch-1
Fixed a typo
2019-08-19 03:10:49 -07:00
Benjamin Lee b10c23a950 Fixed a typo 2019-08-18 22:37:28 -07:00
David Tolnay 85a5cf7cb1 Document serde_derive minimum rustc 2019-08-18 18:31:40 -07:00
David Tolnay 192f5cd647 Release 1.0.99 2019-08-16 11:50:19 -07:00
David Tolnay 7dceee64fe Merge pull request #1591 from dtolnay/up
Update to syn/quote 1.0
2019-08-16 11:49:33 -07:00
David Tolnay 8ad6ae71c6 Update serde_derive minimum rustc version to 1.31 2019-08-16 11:31:15 -07:00
David Tolnay 3ea85a28cf Update to syn/quote 1.0 2019-08-16 11:31:15 -07:00
David Tolnay 273ecdb786 Update ui tests on nightly-2019-08-16 2019-08-16 11:30:49 -07:00
David Tolnay de40eb7306 Update serde_derive to use question mark 2019-08-16 11:28:25 -07:00
David Tolnay b9c44073ce Update serde_test to use question mark 2019-08-16 11:25:12 -07:00
David Tolnay d6e5947ad2 Suppress warnings about try! macro 2019-08-16 11:24:22 -07:00
David Tolnay 668651ee01 Format with rustfmt 2019-07-30 2019-07-31 21:19:46 -07:00
David Tolnay fb1cacc10e Update Attr structs to hold symbols 2019-07-31 21:06:36 -07:00
David Tolnay 735e56c26f Use symbols when parsing values out of attribute 2019-07-31 21:06:36 -07:00
David Tolnay 97de3dccbb Factor out attr symbols into constants 2019-07-31 21:06:36 -07:00
David Tolnay 690467cbe2 Release 1.0.98 2019-07-28 10:33:34 -07:00
David Tolnay 71efd8ffda Merge pull request #1590 from dtolnay/manifest
Work around failing to parse manifest in 1.27 and 1.28 builds
2019-07-28 10:32:14 -07:00
David Tolnay 9bb196ae6e Work around failing to parse manifest in 1.27 and 1.28 builds 2019-07-28 10:07:15 -07:00
David Tolnay ce75418e40 Merge pull request #1589 from Flaise/nonzeroi
Add support for NonZeroI* types
2019-07-28 10:02:09 -07:00
Flaise 78c7f09e28 Add build gate for nonzero signed integers so rustc <1.34 still works 2019-07-28 11:44:31 -05:00
David Tolnay e7269ac84e Add travis builds on every version in build.rs 2019-07-28 08:36:06 -07:00
Flaise 34866e20a8 Add support for NonZeroI* types 2019-07-28 09:12:29 -05:00
David Tolnay 3ae2bee272 Release 1.0.97 2019-07-17 14:56:51 -07:00
David Tolnay d0fb958e99 Remove unneeded explicit type parameters in test_from_into_traits 2019-07-17 12:32:34 -07:00
David Tolnay b941c63a53 More typical TryFrom usage for test 2019-07-17 12:31:41 -07:00
David Tolnay cf70c3fb05 Format with rustfmt 2019-06-09 2019-07-17 12:27:26 -07:00
David Tolnay f249e72162 Provide try_from only on 1.34+ 2019-07-17 12:21:18 -07:00
David Tolnay 92e0b62c6b Merge pull request 1526 from fanzeyi/try_from 2019-07-17 12:16:31 -07:00
David Tolnay cf32a5b204 Release 1.0.96 2019-07-17 12:04:19 -07:00
David Tolnay 7b0e06c825 Provide 32 bit atomic impls for emscripten 2019-07-17 11:44:24 -07:00
David Tolnay 3158bf9093 Merge pull request #1581 from Roguelazer/issue-1579
conservatively limit atomic features
2019-07-17 11:01:21 -07:00
James Brown 01fade764c replaced one too many _ with - 2019-07-17 09:57:53 -07:00
James Brown 210c2419be conservatively limit atomic features 2019-07-17 09:19:03 -07:00
David Tolnay da05163d51 Release 1.0.95 2019-07-16 10:08:53 -07:00
David Tolnay f3e2bb5104 Disable 64 bit atomic tests on emscripten 2019-07-16 10:00:44 -07:00
David Tolnay 7a4c1086b5 Emscripten does not have 64 bit atomics 2019-07-16 09:57:00 -07:00
David Tolnay e89feb9635 Test atomics without needing a macro
As a secondary benefit, this avoids a congnitive_complexity lint from
Clippy.
2019-07-16 09:17:36 -07:00
David Tolnay 5f72766c27 Ignore unreadable_literal lint in test code 2019-07-16 09:04:43 -07:00
David Tolnay 85ae57040d One macro to deserialize all atomics 2019-07-16 07:46:44 -07:00
David Tolnay d55a4a279f Deserialize atomics without needing element type 2019-07-16 07:45:41 -07:00
David Tolnay bee9299693 One macro to serialize all atomics 2019-07-16 07:42:42 -07:00
David Tolnay 9529fcec96 Serialize atomics using the primitive's Serialize impl 2019-07-16 07:40:37 -07:00
David Tolnay bcec168e23 Centralize atomic imports 2019-07-16 07:36:16 -07:00
David Tolnay 102a332616 Format with rustfmt 2019-06-09 2019-07-16 07:32:13 -07:00
David Tolnay a280942f02 Add a builder on 1.34 to cover atomic types 2019-07-16 07:29:10 -07:00
David Tolnay 637dba5c2a Merge pull request #1572 from Roguelazer/issue-1496
Implement serialization and deserialization for std::sync::atomic types
2019-07-16 07:28:18 -07:00
David Tolnay 24f292d081 Build alloc feature on 1.36 in travis 2019-07-16 07:22:47 -07:00
David Tolnay fa5c99e48a Alloc crate is no longer unstable 2019-07-16 07:21:09 -07:00
David Tolnay 48f1a2c9b2 Merge pull request #1576 from c410-f3r/alloc-feature
Make `alloc` feature work on stable
2019-07-16 07:19:49 -07:00
Caio 50ebbd63c6 Enable alloc on stable 2019-07-15 14:24:03 -03:00
James Brown 4e5f63ff45 gate atomic serde on rust 1.34 or higher 2019-07-12 13:44:42 -07:00
James Brown de709e72a8 implement deserialization for atomic integer types 2019-07-11 18:18:54 -07:00
James Brown 56d3c8f071 implement serialization for atomic integer types 2019-07-11 17:34:53 -07:00
David Tolnay ce89adecc1 Suppress deprecation warning on mem::uninitialized 2019-07-07 21:19:50 -07:00
David Tolnay bc7a85063d Switch to rustversion 2019-07-07 21:14:11 -07:00
David Tolnay 0574f1e020 Merge pull request #1561 from BurntSushi/ag/update-i128-docs
Update docs for serde_if_integer128
2019-07-01 15:04:54 -07:00
Andrew Gallant f9fdd60e2e Update docs for serde_if_integer128
The docs imply that the only consideration for using the
serde_if_integer128 macro is support for older versions of Rust, but
Serde's build configuration for 128-bit integers is also gated on the
target platform. For example, if Serde is being compiled for an
emscripten target, then it will not provide 128-bit integer APIs.

See also: https://github.com/BurntSushi/rust-csv/issues/158
2019-07-01 10:18:57 -04:00
David Tolnay 1c1eecabc0 Release 1.0.94 2019-06-27 10:55:12 -07:00
David Tolnay abd3fd004e Merge pull request #1559 from dtolnay/ignore-enum
Accept enums in IgnoredAny
2019-06-27 10:54:22 -07:00
David Tolnay 15ee353488 IgnoredAny::visit_enum for old compilers 2019-06-27 10:45:18 -07:00
David Tolnay e75efbfd31 Support ignoring enum with IgnoredAny 2019-06-27 10:29:55 -07:00
David Tolnay 1c97a7ecb3 Add comprehensive test for deserializing IgnoredAny from enum 2019-06-27 10:23:39 -07:00
David Tolnay fccd3e9fba Add deserialization tests for IgnoredAny 2019-06-27 10:07:06 -07:00
David Tolnay 4cb13b33e0 Release 1.0.93 2019-06-23 12:50:17 -07:00
David Tolnay 629802f2ab Merge pull request #1555 from serde-rs/int
Allow integer key in untagged flattened map
2019-06-23 12:49:21 -07:00
David Tolnay afb1754528 Allow integer key in untagged flattened map 2019-06-23 12:09:15 -07:00
David Tolnay dbd67c6c89 Clippy const_static_lifetime lint has been renamed 2019-06-19 01:34:13 -07:00
David Tolnay ed01bdb9dd Remove fixed cast_precision_loss lint 2019-06-15 10:13:05 -07:00
David Tolnay b54821d8ab Alloc feature has been stabilized
warning: the feature `alloc` has been stable since 1.36.0 and no longer requires an attribute to enable
      --> serde/src/lib.rs:84:40
       |
    84 | #![cfg_attr(feature = "alloc", feature(alloc))]
       |                                        ^^^^^
       |
       = note: #[warn(stable_features)] on by default
2019-05-31 21:26:43 -07:00
David Tolnay 89c6a79b6e Suppress a new pedantic lint 2019-05-31 21:25:36 -07:00
David Tolnay cd0412bddc Release 1.0.92 2019-05-31 13:44:01 -07:00
David Tolnay e42262f0f5 Provide ToString for re-export by serde::export 2019-05-31 13:42:22 -07:00
David Tolnay 0a3eeab273 Merge pull request #1543 from jplatte/alloc-de-compile-fix
Fix a compile error in derive(Deserialize) with no_std + alloc
2019-05-31 13:41:07 -07:00
Jonas Platte e4e110e28f Fix a compile error in derive(Deserialize) with no_std + alloc 2019-05-31 22:16:40 +02:00
David Tolnay 0726623389 Ignore bare_trait_objects lint to support old compilers 2019-05-31 11:34:18 -07:00
David Tolnay fd9d334d01 Smaller format for license section 2019-05-18 17:35:47 -07:00
David Tolnay 840eb14121 Merge pull request #1528 from est31/no_variable_names
Don't use variable names
2019-05-17 08:57:14 -07:00
est31 8fef196ee4 Don't use variable names
They aren't needed. This makes the macro a bit simpler
2019-05-17 16:50:41 +02:00
David Tolnay 9c756f1ec0 Disable ui tests on emscripten
These hit a strange error in our Emscripten builder in Travis as well as
locally through cargo web:

    ERROR: failed to execute cargo: Resource temporarily unavailable (os error 11)
2019-05-12 00:28:22 -07:00
Zeyi Fan 4c29eea790 add attribute try_from 2019-05-11 23:31:24 -07:00
David Tolnay 6dd2b4607f Switch to SPDX 2.1 license expression 2019-05-09 15:21:20 -07:00
David Tolnay 1e9ae88f53 Work around "failed to select a version for serde_test_suite"
Without this:

    error: failed to select a version for `serde_test_suite`.
        ... required by package `serde_test_suite-tests v0.0.0`
    versions that meet the requirements `= 0.0.0` are: 0.0.0

    the package `serde_test_suite-tests` depends on `serde_test_suite`, with features: `serde` but `serde_test_suite` does not have these features.

    failed to select a version for `serde_test_suite` which could resolve this conflict

Seems like a Cargo bug -- I will minimize and report.
2019-05-06 22:53:38 -07:00
David Tolnay 5cc3902ab9 Release 1.0.91 2019-05-06 16:27:04 -07:00
David Tolnay c8e09e2d6d Merge pull request #1522 from dtolnay/enum
Support deserializing enum out of MapAccessDeserializer
2019-05-06 16:26:43 -07:00
David Tolnay e2a2ba116c Remove old instructions intended for compiletest 2019-05-06 16:17:30 -07:00
David Tolnay 0a9d24a218 Support deserializing enum out of MapAccessDeserializer 2019-05-06 16:11:28 -07:00
David Tolnay c222183669 Merge pull request #1521 from serde-rs/trybuild
Switch ui tests to trybuild
2019-05-06 10:44:25 -07:00
David Tolnay 140f9beee7 Switch ui tests to trybuild 2019-05-06 10:25:47 -07:00
David Tolnay 28ce892617 Disable compiletest in appveyor
error[E0464]: multiple matching crates for `serde`
      --> $DIR/wrong_getter.rs:15:10
       |
    15 | #[derive(Serialize)]
       |          ^^^^^^^^^
       |
       = note: candidates:
               crate `serde`: /?/C:/projects/serde/test_suite/deps/target/debug/deps/libserde-a1a28acc73b0edde.rlib
               crate `serde`: /?/C:/Users/appveyor/.
2019-04-22 23:18:21 -07:00
David Tolnay 1e6d3ff99b Merge pull request #1512 from dtolnay/off
Temporarily disable compiletest testing in CI
2019-04-22 23:05:54 -07:00
David Tolnay fba1b92cbf Temporarily disable compiletest testing in CI
The nightly compiler just added a dependency on serde so libserde ends
up in the sysroot, breaking crate resolution inside of compiletest. We
will need to figure out how else to run these tests.

    error[E0464]: multiple matching crates for `serde`
      --> $DIR/wrong_ser.rs:9:10
       |
     9 | #[derive(Serialize)]
       |          ^^^^^^^^^
       |
       = note: candidates:
               crate `serde`: /rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libserde-2b75907288aa7c40.rlib
               crate `serde`: /serde/test_suite/deps/target/debug/deps/libserde-33e0a319242344ce.rlib
2019-04-22 22:42:36 -07:00
David Tolnay ce1686379d Update test suite to nightly-2019-04-20 2019-04-19 22:54:59 -07:00
David Tolnay 79a20e9e33 Resolve option_map_unwrap_or_else lint 2019-04-10 22:57:47 -07:00
David Tolnay e9cd73f78e Remove link to hjson
This project has still not been updated to Serde 1.0.
2019-04-08 10:39:55 -07:00
David Tolnay 0be7f36d51 Release 1.0.90 2019-04-03 09:41:38 -07:00
David Tolnay 4c6cb6e359 Match on serde_path to handle Some(path) and None
I find this a bit easier to follow than map + unwrap_or_else.
2019-04-03 09:40:25 -07:00
David Tolnay 82bde8d166 Format with rustfmt 2019-03-27 2019-04-03 09:40:12 -07:00
David Tolnay 465392b618 Merge pull request #1499 from sgrif/sg-custom-serde-path
Allow `#[serde(crate = "...")]` to override `extern crate serde`
2019-04-03 09:32:07 -07:00
David Tolnay f3c6b9f05a Simplify signature of Container::serde_path 2019-04-03 09:18:45 -07:00
David Tolnay 2f1945eaf2 Refer directly to serde_path in Deserialize impl
This makes it not a breaking change if we later want to eliminate
the `use #serde_path as _serde;` line.
2019-04-03 09:16:21 -07:00
Sean Griffin b4d8a55b2a Change serde_path to crate
Also changed the generated code to have at least one thing refer to the
path directly, rather than via `use` -- This shows that the impl *can*
work without `use`, but doesn't actually do all the work to remove the
`use` lines unless we decide we need this feature to work on the 2015
edition
2019-03-28 11:42:50 -06:00
Sean Griffin 0e6ce8fa50 Fix for Rust 1.15 2019-03-20 14:31:49 -06:00
Sean Griffin a295c38ba3 Allow #[serde(serde_path = "...")] to override extern crate serde
This is intended to be used by other crates which provide their own proc
macros and use serde internally. Today there's no consistent way to put
`#[derive(Deserialize)]` on a struct that consistently works, since
crates may be using either `features = ["derive"]` or relying on
`serde_derive` separately.

Even if we assume that everyone is using `features = ["derive"]`,
without this commit, any crate which generates
`#[derive(serde::Deserialize)]` forces its consumers to put `serde` in
their `Cargo.toml`, even if they aren't otherwise using serde for
anything.

Examples of crates which suffer from this in the real world are
tower-web and swirl.

With this feature, it's expected that these crates would have `pub
extern crate serde;` in some accessible path, and add
`#[serde(serde_path = "that_crate::wherever::serde")]` anywhere they
place serde's derives. Those crates would also have to derive
`that_crate::whatever::serde::Deserialize`, or `use` the macros
explicitly beforehand.

The test for this is a little funky, as it's testing this in a way that
is not the intended use case, or even one we want to support. It has its
own module which re-exports all of serde, but defines its own
`Serialize` and `Deserialize` traits. We then test that we generated
impls for those traits, instead of serde's. The only other way to test
this would be to create a new test crate which does not depend on serde,
but instead depends on `serde_derive` and a third crate which publicly
re-exports serde. This feels like way too much overhead for a single
test case, hence the funky test given.

I didn't see anywhere in this repo to document this attribute, so I
assume the docs will have to be done as a separate PR to a separate
repo.

Fixes #1487
2019-03-18 15:20:19 -06:00
David Tolnay 295730ba1e Clippy cyclomatic complexity lint has been renamed 2019-03-09 16:36:51 -08:00
David Tolnay ac0d8f61c5 Use non-preview name of Clippy rustup component 2019-03-01 23:11:06 -08:00
David Tolnay b811588fa0 Release 1.0.89 2019-02-28 17:09:10 -08:00
David Tolnay 5fcdf0ff2b Sort version-conditional imports at the bottom 2019-02-28 16:53:13 -08:00
David Tolnay 650b723da3 Format with rustfmt 2019-02-14 2019-02-28 16:40:54 -08:00
David Tolnay 97920be33a Merge pull request #1486 from vorot93/reverse
impl Serialize and Deserialize for core::cmp::Reverse
2019-02-28 16:39:54 -08:00
David Tolnay 58bbaa9e80 Refer to Option through serde::export in generated code 2019-02-28 16:36:17 -08:00
David Tolnay 94f152730c Merge pull request #1492 from thomaseizinger/1491-clippy-warning
Don't generate code with redundant closures
2019-02-28 16:35:59 -08:00
David Tolnay 535e3d4372 Mention rc feature in list of trait impls in documentation 2019-02-28 01:13:36 -08:00
Thomas Eizinger 2ea43c8986 Don't generate code with redundant closures
Fixes #1491.
2019-02-28 17:30:21 +11:00
Artem Vorotnikov 71fe2a5534 Reverse impls available for Rust >=1.19 2019-02-20 12:56:35 +03:00
Artem Vorotnikov f3ffcfd61e impl Serialize and Deserialize for core::cmp::Reverse 2019-02-20 04:32:55 +03:00
David Tolnay bf27b28554 Simplify running update-references.sh 2019-02-17 10:58:46 -08:00
David Tolnay 344602d27e Make array ser impls macro better fit rustfmt style 2019-02-16 15:22:53 -08:00
David Tolnay 64c483cf80 Release 1.0.88 2019-02-15 19:55:50 -08:00
David Tolnay 19091aacc7 Fix mistaken double negative in flatten error message 2019-02-15 18:56:31 -08:00
David Tolnay ef9028d798 Remove conflict between flatten and skip 2019-02-15 18:39:15 -08:00
David Tolnay 1668cd19d3 Eliminate try!(..).value to improve rustfmt'd code
Rustfmt bails out on the original code, leaving it all on one line.
2019-02-13 09:13:50 -08:00
David Tolnay 134f268cee Release 1.0.87 2019-02-04 07:08:41 +01:00
David Tolnay c473633676 Format with rustfmt 2018-12-10 2019-02-04 00:39:32 +01:00
David Tolnay 6a3a82007c Merge pull request #1474 from jwillbold/master
Fixed #1468, flattened struct fields made structs ignore their tag
2019-02-03 15:37:44 -08:00
Johannes Willbold 1d6ef76cfb Fixed #1468, flattened struct fields made structs ignore their tag 2019-02-03 02:09:37 +01:00
David Tolnay c8e3959435 Release 1.0.86 2019-02-01 21:07:19 -08:00
David Tolnay 796f412a1e Document that Bound<T> impls exist 2019-02-01 21:07:18 -08:00
David Tolnay fa854a2108 Format with rustfmt 2018-12-10 2019-02-01 21:04:08 -08:00
David Tolnay 3a097ff2d2 Deserialize Bound::Unbounded as unit variant 2019-02-01 21:04:07 -08:00
David Tolnay 8463bfc1e5 Remove as yet unrequested range impls 2019-02-01 21:04:06 -08:00
David Tolnay 7a72b4c624 Merge pull request #1466 from 0nkery/master
Impl Serialize/Deserialize for std::ops::{Bound, RangeFrom, RangeTo, RangeToInclusive}
2019-02-01 21:03:55 -08:00
David Tolnay 670c179417 Re-enable deny unused_imports 2019-02-01 17:56:52 -08:00
David Tolnay 1b1d868837 Combine the two clippy lists 2019-02-01 17:56:31 -08:00
David Tolnay d9704d02bb Remove clippy lints that are no longer triggering 2019-02-01 17:53:14 -08:00
David Tolnay 1349548367 Fix indentation of cfg that isn't formatted by rustfmt 2019-02-01 17:48:14 -08:00
Dmitry Shlagoff 18b1604fc8 Fix compatibility issues with syntax and Bound 2019-01-30 00:41:03 +07:00
Dmitry Shlagoff 0def7da5a8 Impl Ser/De for RangeFrom, RangeTo, RangeToInclusive 2019-01-29 20:29:14 +07:00
Dmitry Shlagoff 4bb45c8252 Impl Serialize for Bound<T> 2019-01-29 15:20:27 +07:00
218 changed files with 15698 additions and 4868 deletions
+1
View File
@@ -0,0 +1 @@
test_suite/tests/expand/*.expanded.rs linguist-generated
-7
View File
@@ -1,7 +0,0 @@
---
name: Help or discussion
about: This is the right place
---
+194
View File
@@ -0,0 +1,194 @@
name: CI
on:
push:
pull_request:
schedule: [cron: "40 1 * * *"]
env:
RUSTFLAGS: -Dwarnings
jobs:
test:
name: Test suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable
- uses: dtolnay/install@cargo-expand
if: github.event_name != 'pull_request'
- run: cd test_suite && cargo test --features expandtest --test expandtest -- --include-ignored
if: github.event_name != 'pull_request'
windows:
name: Test suite (windows)
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
stable:
name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [stable, beta]
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd serde_test && cargo build
- run: cd serde_test && cargo test --features serde/derive,serde/rc
nightly:
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
runs-on: ${{matrix.os}}-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu, windows]
steps:
- uses: actions/checkout@v3
- 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 test --features derive,rc,unstable
- run: cd test_suite/no_std && cargo build
if: matrix.os != 'windows'
- run: cd serde_derive && cargo check --tests
env:
RUSTFLAGS: --cfg exhaustive ${{env.RUSTFLAGS}}
if: matrix.os != 'windows'
msrv:
name: Rust 1.13.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.13.0
- name: Get timestamp for cache
id: date
run: echo ::set-output name=yearmo::$(date +%Y%m)
- uses: actions/cache@v1
with:
path: ~/.cargo/registry/index
key: cargo-registry-index-${{steps.date.outputs.yearmo}}
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd serde_test && cargo build
build:
name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- 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]
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.31.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.31.0
- run: cd serde && cargo check --no-default-features
- run: cd serde && cargo check
- run: cd serde_derive && cargo check
alloc:
name: Rust 1.36.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.36.0
- run: cd serde && cargo build --no-default-features --features alloc
emscripten:
name: Emscripten
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- uses: actions/setup-node@v1
with:
node-version: 9
- name: Install cargo-web
run: |
CARGO_WEB_RELEASE=$(curl -L -s -H Accept:application/json https://github.com/koute/cargo-web/releases/latest)
CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | jq -r .tag_name)
CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
mkdir -p ~/.cargo/bin
curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
chmod +x ~/.cargo/bin/cargo-web
- run: cd test_suite && cargo web test --target=asmjs-unknown-emscripten --nodejs
continue-on-error: true
- run: cd test_suite && cargo web test --target=wasm32-unknown-emscripten --nodejs
continue-on-error: true
clippy:
name: Clippy
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- uses: actions/checkout@v3
- 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
- run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
- run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
miri:
name: Miri
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@miri
- run: cd serde && cargo miri test --features derive,rc,unstable
env:
MIRIFLAGS: -Zmiri-strict-provenance
- run: cd test_suite && cargo miri test --features unstable
env:
MIRIFLAGS: -Zmiri-strict-provenance
outdated:
name: Outdated
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- uses: actions/checkout@v3
- uses: dtolnay/install@cargo-outdated
- run: cargo outdated --workspace --exclude macrotest,prettyplease --exit-code 1
-95
View File
@@ -1,95 +0,0 @@
language: rust
matrix:
include:
- rust: stable
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build
- cargo test --features serde/derive,serde/rc
- rust: beta
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test
- rust: nightly
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build
- cargo build --no-default-features
- cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc
- cargo test --features derive,rc,unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/deps"
- cargo build
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test --features compiletest,unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo build
- rust: 1.13.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build
- rust: 1.15.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo build
- rust: 1.20.0
- rust: 1.21.0
- rust: 1.25.0
- rust: 1.26.0
- rust: nightly
name: Clippy
script:
- rustup component add clippy-preview || travis_terminate 0
- cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo clippy --features rc,unstable -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo clippy --tests --features unstable -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo clippy -- -D clippy::all
- rust: nightly
name: Emscripten
script:
- CARGO_WEB_RELEASE=$(curl -L -s -H Accept:application/json https://github.com/koute/cargo-web/releases/latest)
- CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | jq -r .tag_name)
- CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
- nvm install 9
- mkdir -p ~/.cargo/bin
- curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
- chmod +x ~/.cargo/bin/cargo-web
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo web test --target=asmjs-unknown-emscripten --nodejs
- cargo web test --target=wasm32-unknown-emscripten --nodejs
allow_failures:
- rust: nightly
name: Clippy
- rust: nightly
name: Emscripten
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --no-default-features
- cargo build
+5 -16
View File
@@ -4,11 +4,6 @@ Serde welcomes contribution from everyone in the form of suggestions, bug
reports, pull requests, and feedback. This document gives some guidance if you
are thinking of helping us.
Please reach out here in a GitHub issue or in the #serde IRC channel on
[`irc.mozilla.org`] if we can do anything to help you contribute.
[`irc.mozilla.org`]: https://wiki.mozilla.org/IRC
## Submitting bug reports and feature requests
Serde development is spread across lots of repositories, but this serde-rs/serde
@@ -36,25 +31,19 @@ tests for you.
```sh
# Test all the example code in Serde documentation
cargo test
```
##### In the [`test_suite/deps`] directory
```sh
# This is a prerequisite for running the full test suite
cargo clean && cargo update && cargo build
cargo test --features derive
```
##### In the [`test_suite`] directory
```sh
# Run the full test suite, including tests of unstable functionality
cargo test --features unstable
cargo +nightly test --features unstable
```
Note that this test suite currently only supports running on a nightly compiler.
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde
[`test_suite/deps`]: https://github.com/serde-rs/serde/tree/master/test_suite/deps
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
## Conduct
@@ -63,4 +52,4 @@ In all Serde-related forums, we follow the [Rust Code of Conduct]. For
escalation or moderation issues please contact Erick (erick.tryzelaar@gmail.com)
instead of the Rust moderation team.
[Rust Code of Conduct]: https://www.rust-lang.org/conduct.html
[Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct
+35 -20
View File
@@ -1,11 +1,13 @@
# Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.13+]][rustc]
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
[travis]: https://travis-ci.org/serde-rs/serde
[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/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
[Rustc Version 1.13+]: https://img.shields.io/badge/rustc-1.13+-lightgray.svg
[rustc]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
[serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg
[serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg
[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
@@ -73,27 +75,40 @@ fn main() {
## Getting help
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
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:
<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
[Discourse forum][discourse]. It's acceptable to file a support issue in this
repo but they tend not to get as many eyes as any of the above and may get
closed without a response after some time.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
[#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513
[#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281
[#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848
[#beginners]: https://discord.com/channels/442252698964721669/448238009733742612
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general
[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
[/r/rust]: https://www.reddit.com/r/rust
[discourse]: https://users.rust-lang.org
## License
<br>
Serde is licensed under either of
#### License
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
at your option.
### Contribution
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
</sub>
-41
View File
@@ -1,41 +0,0 @@
environment:
matrix:
- APPVEYOR_RUST_CHANNEL: stable
- APPVEYOR_RUST_CHANNEL: nightly
install:
# Install rust, x86_64-pc-windows-msvc host
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -vV
- cargo -vV
build: false
for:
- matrix:
only:
- APPVEYOR_RUST_CHANNEL: stable
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\serde
- cargo build --features rc
- cargo build --no-default-features
- cd %APPVEYOR_BUILD_FOLDER%\serde_test
- cargo build
- cargo test --features serde/derive,serde/rc
- matrix:
only:
- APPVEYOR_RUST_CHANNEL: nightly
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\serde
- cargo build
- cargo build --no-default-features
- cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc
- cargo test --features derive,rc,unstable
- cd %APPVEYOR_BUILD_FOLDER%\test_suite\deps
- cargo build
- cd %APPVEYOR_BUILD_FOLDER%\test_suite
- cargo test --features compiletest,unstable
+19 -6
View File
@@ -43,10 +43,23 @@ fn main() {
## Getting help
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
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:
<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
[Discourse forum][discourse]. It's acceptable to file a support issue in this
repo but they tend not to get as many eyes as any of the above and may get
closed without a response after some time.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
[#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513
[#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281
[#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848
[#beginners]: https://discord.com/channels/442252698964721669/448238009733742612
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general
[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
[/r/rust]: https://www.reddit.com/r/rust
[discourse]: https://users.rust-lang.org
-1
View File
@@ -1 +0,0 @@
error_on_line_overflow = false
+1
View File
@@ -0,0 +1 @@
msrv = "1.13.0"
+16 -20
View File
@@ -1,24 +1,21 @@
[package]
name = "serde"
version = "1.0.85" # remember to update html_root_url
version = "1.0.142" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
readme = "crates-io.md"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs"
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
categories = ["encoding", "no-std"]
description = "A generic serialization/deserialization framework"
documentation = "https://docs.serde.rs/serde/"
homepage = "https://serde.rs"
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
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.13"
[dependencies]
serde_derive = { version = "1.0", optional = true, path = "../serde_derive" }
serde_derive = { version = "=1.0.142", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" }
@@ -26,6 +23,9 @@ serde_derive = { version = "1.0", path = "../serde_derive" }
[package.metadata.playground]
features = ["derive", "rc"]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
### FEATURES #################################################################
@@ -48,11 +48,7 @@ unstable = []
# Provide impls for types in the Rust core allocation and collections library
# including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
# be enabled without depending on all of std.
#
# Requires a dependency on the unstable core allocation library:
#
# https://doc.rust-lang.org/alloc/
alloc = ["unstable"]
alloc = []
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data.
+71 -16
View File
@@ -14,44 +14,99 @@ fn main() {
let target = env::var("TARGET").unwrap();
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
// CString::into_boxed_c_str stabilized in Rust 1.20:
// 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
if minor >= 20 {
println!("cargo:rustc-cfg=de_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=de_rc_dst");
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=core_duration");
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 as Emscripten doesn't
// currently support integers larger than 64 bits.
if minor >= 26 && !emscripten {
println!("cargo:rustc-cfg=integer128");
// 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
if minor >= 27 {
println!("cargo:rustc-cfg=range_inclusive");
// 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://github.com/rust-lang/rust/pull/50808
if minor >= 28 {
println!("cargo:rustc-cfg=num_nonzero");
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
if minor < 28 {
println!("cargo:rustc-cfg=no_num_nonzero");
}
// Current minimum supported version of serde_derive crate is Rust 1.31.
if minor < 31 {
println!("cargo:rustc-cfg=no_serde_derive");
}
// 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
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
if minor < 34 {
println!("cargo:rustc-cfg=no_core_try_from");
println!("cargo:rustc-cfg=no_num_nonzero_signed");
println!("cargo:rustc-cfg=no_systemtime_checked_add");
}
// Whitelist of archs that support std::sync::atomic module. Ideally we
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
// Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs.
let has_atomic64 = target.starts_with("x86_64")
|| target.starts_with("i686")
|| target.starts_with("aarch64")
|| target.starts_with("powerpc64")
|| target.starts_with("sparc64")
|| target.starts_with("mips64el")
|| target.starts_with("riscv64");
let has_atomic32 = has_atomic64 || emscripten;
if minor < 34 || !has_atomic64 {
println!("cargo:rustc-cfg=no_std_atomic64");
}
if minor < 34 || !has_atomic32 {
println!("cargo:rustc-cfg=no_std_atomic");
}
}
+30
View File
@@ -0,0 +1,30 @@
use lib::fmt::{self, Write};
use lib::str;
pub struct Buf<'a> {
bytes: &'a mut [u8],
offset: usize,
}
impl<'a> Buf<'a> {
pub fn new(bytes: &'a mut [u8]) -> Self {
Buf { bytes, offset: 0 }
}
pub fn as_str(&self) -> &str {
let slice = &self.bytes[..self.offset];
unsafe { str::from_utf8_unchecked(slice) }
}
}
impl<'a> Write for Buf<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
if self.offset + s.len() > self.bytes.len() {
Err(fmt::Error)
} else {
self.bytes[self.offset..self.offset + s.len()].copy_from_slice(s.as_bytes());
self.offset += s.len();
Ok(())
}
}
}
-260
View File
@@ -1,260 +0,0 @@
use lib::*;
macro_rules! int_to_int {
($dst:ident, $n:ident) => {
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
Some($n as $dst)
} else {
None
}
};
}
macro_rules! int_to_uint {
($dst:ident, $n:ident) => {
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
};
}
macro_rules! uint_to {
($dst:ident, $n:ident) => {
if $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
};
}
pub trait FromPrimitive: Sized {
fn from_i8(n: i8) -> Option<Self>;
fn from_i16(n: i16) -> Option<Self>;
fn from_i32(n: i32) -> Option<Self>;
fn from_i64(n: i64) -> Option<Self>;
fn from_u8(n: u8) -> Option<Self>;
fn from_u16(n: u16) -> Option<Self>;
fn from_u32(n: u32) -> Option<Self>;
fn from_u64(n: u64) -> Option<Self>;
}
macro_rules! impl_from_primitive_for_int {
($t:ident) => {
impl FromPrimitive for $t {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
int_to_int!($t, n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
uint_to!($t, n)
}
}
};
}
macro_rules! impl_from_primitive_for_uint {
($t:ident) => {
impl FromPrimitive for $t {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
int_to_uint!($t, n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
uint_to!($t, n)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
uint_to!($t, n)
}
}
};
}
macro_rules! impl_from_primitive_for_float {
($t:ident) => {
impl FromPrimitive for $t {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as Self)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as Self)
}
}
};
}
impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
serde_if_integer128! {
impl FromPrimitive for i128 {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as i128)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as i128)
}
}
impl FromPrimitive for u128 {
#[inline]
fn from_i8(n: i8) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
if n >= 0 {
Some(n as u128)
} else {
None
}
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Some(n as u128)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Some(n as u128)
}
}
}
+26 -1
View File
@@ -1,6 +1,8 @@
use lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
use de::{
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};
/// An efficient way of discarding data from a deserializer.
///
@@ -128,12 +130,28 @@ 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_u64<E>(self, x: u64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
serde_if_integer128! {
#[inline]
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
}
#[inline]
fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
let _ = x;
@@ -205,6 +223,13 @@ impl<'de> Visitor<'de> for IgnoredAny {
let _ = bytes;
Ok(IgnoredAny)
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
data.variant::<IgnoredAny>()?.1.newtype_variant()
}
}
impl<'de> Deserialize<'de> for IgnoredAny {
+607 -315
View File
File diff suppressed because it is too large Load Diff
+52 -20
View File
@@ -30,7 +30,7 @@
//! # The Deserializer trait
//!
//! [`Deserializer`] implementations are provided by third-party crates, for
//! example [`serde_json`], [`serde_yaml`] and [`bincode`].
//! example [`serde_json`], [`serde_yaml`] and [`postcard`].
//!
//! A partial list of well-maintained formats is given on the [Serde
//! website][data formats].
@@ -59,13 +59,13 @@
//! - Box\<T\>
//! - Box\<\[T\]\>
//! - Box\<str\>
//! - Rc\<T\>
//! - Arc\<T\>
//! - Cow\<'a, T\>
//! - Cell\<T\>
//! - RefCell\<T\>
//! - Mutex\<T\>
//! - RwLock\<T\>
//! - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - **Collection types**:
//! - BTreeMap\<K, V\>
//! - BTreeSet\<T\>
@@ -89,6 +89,7 @@
//! - PathBuf
//! - Range\<T\>
//! - RangeInclusive\<T\>
//! - Bound\<T\>
//! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**:
@@ -103,7 +104,7 @@
//! [`Deserialize`]: ../trait.Deserialize.html
//! [`Deserializer`]: ../trait.Deserializer.html
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
//! [`bincode`]: https://github.com/TyOverby/bincode
//! [`postcard`]: https://github.com/jamesmunns/postcard
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
//! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json
@@ -117,13 +118,21 @@ use lib::*;
pub mod value;
mod from_primitive;
#[cfg(not(no_integer128))]
mod format;
mod ignored_any;
mod impls;
mod utf8;
pub use self::ignored_any::IgnoredAny;
#[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;
////////////////////////////////////////////////////////////////////////////////
macro_rules! declare_error_trait {
@@ -287,7 +296,7 @@ macro_rules! declare_error_trait {
}
#[cfg(feature = "std")]
declare_error_trait!(Error: Sized + error::Error);
declare_error_trait!(Error: Sized + StdError);
#[cfg(not(feature = "std"))]
declare_error_trait!(Error: Sized + Debug + Display);
@@ -385,7 +394,7 @@ pub enum Unexpected<'a> {
}
impl<'a> fmt::Display for Unexpected<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use self::Unexpected::*;
match *self {
Bool(b) => write!(formatter, "boolean `{}`", b),
@@ -699,6 +708,11 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// where
/// A: SeqAccess<'de>,
/// {
/// // Decrease the number of reallocations if there are many elements
/// if let Some(size_hint) = seq.size_hint() {
/// self.0.reserve(size_hint);
/// }
///
/// // Visit each element in the inner array and push it onto
/// // the existing vector.
/// while let Some(elem) = seq.next_element()? {
@@ -786,7 +800,7 @@ where
///
/// The role of this trait is to define the deserialization half of the [Serde
/// data model], which is a way to categorize every Rust data type into one of
/// 29 possible types. Each method of the `Serializer` trait corresponds to one
/// 29 possible types. Each method of the `Deserializer` trait corresponds to one
/// of the types of the data model.
///
/// Implementations of `Deserialize` map themselves into this data model by
@@ -860,7 +874,7 @@ where
/// `Deserializer::deserialize_any`.
///
/// 2. The various `deserialize_*` methods. Non-self-describing formats like
/// Bincode need to be told what is in the input in order to deserialize it.
/// Postcard need to be told what is in the input in order to deserialize it.
/// The `deserialize_*` methods are hints to the deserializer for how to
/// interpret the next piece of input. Non-self-describing formats are not
/// able to deserialize something like `serde_json::Value` which relies on
@@ -870,7 +884,7 @@ where
/// `Deserializer::deserialize_any` unless you need to be told by the
/// Deserializer what type is in the input. Know that relying on
/// `Deserializer::deserialize_any` means your data type will be able to
/// deserialize from self-describing formats only, ruling out Bincode and many
/// deserialize from self-describing formats only, ruling out Postcard and many
/// others.
///
/// [Serde data model]: https://serde.rs/data-model.html
@@ -901,7 +915,7 @@ pub trait Deserializer<'de>: Sized {
/// `Deserializer::deserialize_any` unless you need to be told by the
/// Deserializer what type is in the input. Know that relying on
/// `Deserializer::deserialize_any` means your data type will be able to
/// deserialize from self-describing formats only, ruling out Bincode and
/// deserialize from self-describing formats only, ruling out Postcard and
/// many others.
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
@@ -1000,7 +1014,7 @@ pub trait Deserializer<'de>: Sized {
/// `Deserializer`.
///
/// If the `Visitor` would benefit from taking ownership of `String` data,
/// indiciate this to the `Deserializer` by using `deserialize_string`
/// indicate this to the `Deserializer` by using `deserialize_string`
/// instead.
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
@@ -1142,7 +1156,7 @@ pub trait Deserializer<'de>: Sized {
/// Some types have a human-readable form that may be somewhat expensive to
/// construct, as well as a binary form that is compact and efficient.
/// Generally text-based formats like JSON and YAML will prefer to use the
/// human-readable one and binary formats like Bincode will prefer the
/// human-readable one and binary formats like Postcard will prefer the
/// compact one.
///
/// ```edition2018
@@ -1206,6 +1220,20 @@ pub trait Deserializer<'de>: Sized {
fn is_human_readable(&self) -> bool {
true
}
// Not public API.
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
#[doc(hidden)]
fn __deserialize_content<V>(
self,
_: ::actually_private::T,
visitor: V,
) -> Result<::private::de::Content<'de>, Self::Error>
where
V: Visitor<'de, Value = ::private::de::Content<'de>>,
{
self.deserialize_any(visitor)
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -1345,8 +1373,10 @@ pub trait Visitor<'de>: Sized {
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Other("i128"), &self))
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))
}
}
@@ -1405,8 +1435,10 @@ pub trait Visitor<'de>: Sized {
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Other("u128"), &self))
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))
}
}
@@ -1528,7 +1560,7 @@ pub trait Visitor<'de>: Sized {
/// `Deserializer`.
///
/// This enables zero-copy deserialization of bytes in some formats. For
/// example Bincode data containing bytes can be deserialized with zero
/// example Postcard data containing bytes can be deserialized with zero
/// copying into a `&'a [u8]` as long as the input data outlives `'a`.
///
/// The default implementation forwards to `visit_bytes`.
@@ -1707,7 +1739,7 @@ pub trait SeqAccess<'de> {
}
}
impl<'de, 'a, A> SeqAccess<'de> for &'a mut A
impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A
where
A: SeqAccess<'de>,
{
@@ -1860,7 +1892,7 @@ pub trait MapAccess<'de> {
}
}
impl<'de, 'a, A> MapAccess<'de> for &'a mut A
impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A
where
A: MapAccess<'de>,
{
+19
View File
@@ -0,0 +1,19 @@
use de::{Deserialize, DeserializeSeed, Deserializer};
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
///
/// Wraps a mutable reference and calls deserialize_in_place on it.
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
where
T: Deserialize<'de>,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize_in_place(deserializer, self.0)
}
}
+341 -43
View File
@@ -24,8 +24,8 @@
use lib::*;
use self::private::{First, Second};
use de::{self, Expected, IntoDeserializer, SeqAccess};
use private::de::size_hint;
use __private::size_hint;
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use ser;
////////////////////////////////////////////////////////////////////////////////
@@ -48,7 +48,7 @@ macro_rules! impl_copy_clone {
/// A minimal representation of all possible errors that can occur using the
/// `IntoDeserializer` trait.
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, PartialEq)]
pub struct Error {
err: ErrorImpl,
}
@@ -93,16 +93,25 @@ impl ser::Error for Error {
impl Display for Error {
#[cfg(any(feature = "std", feature = "alloc"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(&self.err)
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Serde deserialization error")
}
}
impl Debug for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let mut debug = formatter.debug_tuple("Error");
#[cfg(any(feature = "std", feature = "alloc"))]
debug.field(&self.err);
debug.finish()
}
}
#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
@@ -119,20 +128,26 @@ where
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer {
marker: PhantomData,
}
UnitDeserializer::new()
}
}
/// A deserializer holding a `()`.
#[derive(Debug)]
pub struct UnitDeserializer<E> {
marker: PhantomData<E>,
}
impl_copy_clone!(UnitDeserializer);
impl<E> UnitDeserializer<E> {
#[allow(missing_docs)]
pub fn new() -> Self {
UnitDeserializer {
marker: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
where
E: de::Error,
@@ -160,6 +175,12 @@ where
}
}
impl<E> Debug for UnitDeserializer<E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_struct("UnitDeserializer").finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer that cannot be instantiated.
@@ -208,7 +229,6 @@ macro_rules! primitive_deserializer {
($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => {
#[doc = "A deserializer holding"]
#[doc = $doc]
#[derive(Debug)]
pub struct $name<E> {
value: $ty,
marker: PhantomData<E>
@@ -223,8 +243,15 @@ macro_rules! primitive_deserializer {
type Deserializer = $name<E>;
fn into_deserializer(self) -> $name<E> {
$name::new(self)
}
}
impl<E> $name<E> {
#[allow(missing_docs)]
pub fn new(value: $ty) -> Self {
$name {
value: self,
value: value,
marker: PhantomData,
}
}
@@ -249,6 +276,15 @@ macro_rules! primitive_deserializer {
visitor.$method(self.value $($cast)*)
}
}
impl<E> Debug for $name<E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct(stringify!($name))
.field("value", &self.value)
.finish()
}
}
}
}
@@ -272,7 +308,6 @@ serde_if_integer128! {
}
/// A deserializer holding a `u32`.
#[derive(Debug)]
pub struct U32Deserializer<E> {
value: u32,
marker: PhantomData<E>,
@@ -287,8 +322,15 @@ where
type Deserializer = U32Deserializer<E>;
fn into_deserializer(self) -> U32Deserializer<E> {
U32Deserializer::new(self)
}
}
impl<E> U32Deserializer<E> {
#[allow(missing_docs)]
pub fn new(value: u32) -> Self {
U32Deserializer {
value: self,
value: value,
marker: PhantomData,
}
}
@@ -343,10 +385,18 @@ where
}
}
impl<E> Debug for U32Deserializer<E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("U32Deserializer")
.field("value", &self.value)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&str`.
#[derive(Debug)]
pub struct StrDeserializer<'a, E> {
value: &'a str,
marker: PhantomData<E>,
@@ -361,8 +411,15 @@ where
type Deserializer = StrDeserializer<'a, E>;
fn into_deserializer(self) -> StrDeserializer<'a, E> {
StrDeserializer::new(self)
}
}
impl<'a, E> StrDeserializer<'a, E> {
#[allow(missing_docs)]
pub fn new(value: &'a str) -> Self {
StrDeserializer {
value: self,
value: value,
marker: PhantomData,
}
}
@@ -417,11 +474,19 @@ where
}
}
impl<'a, E> Debug for StrDeserializer<'a, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("StrDeserializer")
.field("value", &self.value)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&str` with a lifetime tied to another
/// deserializer.
#[derive(Debug)]
pub struct BorrowedStrDeserializer<'de, E> {
value: &'de str,
marker: PhantomData<E>,
@@ -488,11 +553,19 @@ where
}
}
impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("BorrowedStrDeserializer")
.field("value", &self.value)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `String`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Debug)]
pub struct StringDeserializer<E> {
value: String,
marker: PhantomData<E>,
@@ -516,8 +589,16 @@ where
type Deserializer = StringDeserializer<E>;
fn into_deserializer(self) -> StringDeserializer<E> {
StringDeserializer::new(self)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<E> StringDeserializer<E> {
#[allow(missing_docs)]
pub fn new(value: String) -> Self {
StringDeserializer {
value: self,
value: value,
marker: PhantomData,
}
}
@@ -559,7 +640,7 @@ where
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E>
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
where
E: de::Error,
{
@@ -574,11 +655,20 @@ where
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<E> Debug for StringDeserializer<E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("StringDeserializer")
.field("value", &self.value)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `Cow<str>`.
#[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Debug)]
pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>,
marker: PhantomData<E>,
@@ -602,8 +692,16 @@ where
type Deserializer = CowStrDeserializer<'a, E>;
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
CowStrDeserializer::new(self)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, E> CowStrDeserializer<'a, E> {
#[allow(missing_docs)]
pub fn new(value: Cow<'a, str>) -> Self {
CowStrDeserializer {
value: self,
value: value,
marker: PhantomData,
}
}
@@ -663,29 +761,48 @@ where
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, E> Debug for CowStrDeserializer<'a, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("CowStrDeserializer")
.field("value", &self.value)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&[u8]` with a lifetime tied to another
/// deserializer.
#[derive(Debug)]
pub struct BorrowedBytesDeserializer<'de, E> {
value: &'de [u8],
/// A deserializer holding a `&[u8]`. Always calls [`Visitor::visit_bytes`].
pub struct BytesDeserializer<'a, E> {
value: &'a [u8],
marker: PhantomData<E>,
}
impl_copy_clone!(BorrowedBytesDeserializer<'de>);
impl<'de, E> BorrowedBytesDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given byte slice.
pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> {
BorrowedBytesDeserializer {
impl<'a, E> BytesDeserializer<'a, E> {
/// Create a new deserializer from the given bytes.
pub fn new(value: &'a [u8]) -> Self {
BytesDeserializer {
value: value,
marker: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E>
impl_copy_clone!(BytesDeserializer<'a>);
impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a [u8]
where
E: de::Error,
{
type Deserializer = BytesDeserializer<'a, E>;
fn into_deserializer(self) -> BytesDeserializer<'a, E> {
BytesDeserializer::new(self)
}
}
impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E>
where
E: de::Error,
{
@@ -693,7 +810,55 @@ where
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
V: Visitor<'de>,
{
visitor.visit_bytes(self.value)
}
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<'a, E> Debug for BytesDeserializer<'a, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("BytesDeserializer")
.field("value", &self.value)
.finish()
}
}
/// A deserializer holding a `&[u8]` with a lifetime tied to another
/// deserializer. Always calls [`Visitor::visit_borrowed_bytes`].
pub struct BorrowedBytesDeserializer<'de, E> {
value: &'de [u8],
marker: PhantomData<E>,
}
impl<'de, E> BorrowedBytesDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given borrowed bytes.
pub fn new(value: &'de [u8]) -> Self {
BorrowedBytesDeserializer {
value: value,
marker: PhantomData,
}
}
}
impl_copy_clone!(BorrowedBytesDeserializer<'de>);
impl<'de, E> Deserializer<'de> for BorrowedBytesDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_borrowed_bytes(self.value)
}
@@ -701,14 +866,23 @@ where
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 identifier ignored_any enum
tuple_struct map struct enum identifier ignored_any
}
}
impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("BorrowedBytesDeserializer")
.field("value", &self.value)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer that iterates over a sequence.
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct SeqDeserializer<I, E> {
iter: iter::Fuse<I>,
count: usize,
@@ -813,6 +987,19 @@ impl Expected for ExpectedInSeq {
}
}
impl<I, E> Debug for SeqDeserializer<I, E>
where
I: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("SeqDeserializer")
.field("iter", &self.iter)
.field("count", &self.count)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -1034,7 +1221,7 @@ where
let value = self.value.take();
// Panic because this indicates a bug in the program rather than an
// expected failure.
let value = value.expect("MapAccess::visit_value called before visit_key");
let value = value.expect("MapAccess::next_value called before next_key");
seed.deserialize(value.into_deserializer())
}
@@ -1108,7 +1295,6 @@ where
}
}
// Cannot #[derive(Debug)] because of the bound `Second<I::Item>: Debug`.
impl<'de, I, E> Debug for MapDeserializer<'de, I, E>
where
I: Iterator + Debug,
@@ -1121,8 +1307,6 @@ where
.field("iter", &self.iter)
.field("value", &self.value)
.field("count", &self.count)
.field("lifetime", &self.lifetime)
.field("error", &self.error)
.finish()
}
}
@@ -1287,10 +1471,40 @@ where
visitor.visit_map(self.map)
}
fn deserialize_enum<V>(
self,
_name: &str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_enum(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
tuple_struct map struct identifier ignored_any
}
}
impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer<A>
where
A: de::MapAccess<'de>,
{
type Error = A::Error;
type Variant = private::MapAsEnum<A>;
fn variant_seed<T>(mut self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match 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")),
}
}
}
@@ -1299,9 +1513,8 @@ where
mod private {
use lib::*;
use de::{self, Unexpected};
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
#[derive(Clone, Debug)]
pub struct UnitOnly<E> {
marker: PhantomData<E>,
}
@@ -1360,6 +1573,91 @@ mod private {
}
}
pub struct MapAsEnum<A> {
map: A,
}
pub fn map_as_enum<A>(map: A) -> MapAsEnum<A> {
MapAsEnum { map: map }
}
impl<'de, A> VariantAccess<'de> for MapAsEnum<A>
where
A: MapAccess<'de>,
{
type Error = A::Error;
fn unit_variant(mut self) -> Result<(), Self::Error> {
self.map.next_value()
}
fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
self.map.next_value_seed(seed)
}
fn tuple_variant<V>(mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.map.next_value_seed(SeedTupleVariant {
len: len,
visitor: visitor,
})
}
fn struct_variant<V>(
mut self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.map
.next_value_seed(SeedStructVariant { visitor: visitor })
}
}
struct SeedTupleVariant<V> {
len: usize,
visitor: V,
}
impl<'de, V> DeserializeSeed<'de> for SeedTupleVariant<V>
where
V: Visitor<'de>,
{
type Value = V::Value;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(self.len, self.visitor)
}
}
struct SeedStructVariant<V> {
visitor: V,
}
impl<'de, V> DeserializeSeed<'de> for SeedStructVariant<V>
where
V: Visitor<'de>,
{
type Value = V::Value;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(self.visitor)
}
}
/// Avoid having to restate the generic types on `MapDeserializer`. The
/// `Iterator::Item` contains enough information to figure out K and V.
pub trait Pair {
-36
View File
@@ -1,36 +0,0 @@
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::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::Vec;
mod string {
use lib::*;
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "std", feature = "alloc")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
}
+9 -9
View File
@@ -1,16 +1,16 @@
/// Conditional compilation depending on whether Serde is built with support for
/// 128-bit integers.
///
/// Data formats that wish to support Rust compiler versions older than 1.26 may
/// place the i128 / u128 methods of their Serializer and Deserializer behind
/// this macro.
/// Data formats that 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
/// do not need to bother with this macro and may assume support for 128-bit
/// integers.
/// 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.
///
/// ```edition2018
/// # use serde::private::ser::Error;
/// # use serde::__private::doc::Error;
/// #
/// # struct MySerializer;
/// #
@@ -66,7 +66,7 @@
/// ($($tt:tt)*) => {};
/// }
/// ```
#[cfg(integer128)]
#[cfg(not(no_integer128))]
#[macro_export]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {
@@ -74,7 +74,7 @@ macro_rules! serde_if_integer128 {
};
}
#[cfg(not(integer128))]
#[cfg(no_integer128)]
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
+108 -72
View File
@@ -9,11 +9,9 @@
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
@@ -33,12 +31,11 @@
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//! size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//! language.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//! markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
@@ -46,92 +43,102 @@
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//! definition.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//! *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//! Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//! Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//! and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://github.com/flavray/avro-rs
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.85")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.142")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy 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,
const_static_lifetime,
doc_markdown,
linkedlist,
needless_pass_by_value,
redundant_field_names,
module_name_repetitions,
option_if_let_else,
single_match_else,
type_complexity,
unreadable_literal,
zero_prefixed_literal
use_self,
zero_prefixed_literal,
// correctly used
derive_partial_eq_without_eq,
enum_glob_use,
explicit_auto_deref,
let_underscore_drop,
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,
)
)]
// Ignored clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// simplifies some macros
invalid_upcast_comparisons,
// things are often more readable this way
decimal_literal_representation,
module_name_repetitions,
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
single_match_else,
use_self,
// not practical
indexing_slicing,
many_single_char_names,
missing_docs_in_private_items,
similar_names,
// alternative is not stable
empty_enum,
use_debug,
))]
// Blacklisted Rust lints.
//
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]
////////////////////////////////////////////////////////////////////////////////
@@ -149,7 +156,7 @@ mod lib {
pub use std::*;
}
pub use self::core::{cmp, iter, mem, num, slice, str};
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::{u16, u32, u64, u8, usize};
@@ -160,6 +167,7 @@ mod lib {
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::num::Wrapping;
pub use self::core::ops::Range;
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
@@ -172,7 +180,7 @@ mod lib {
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::string::{String, ToString};
#[cfg(feature = "std")]
pub use std::string::String;
pub use std::string::{String, ToString};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::vec::Vec;
@@ -211,19 +219,34 @@ mod lib {
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(feature = "std")]
pub use std::num::Wrapping;
#[cfg(feature = "std")]
pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(any(core_duration, feature = "std"))]
pub use self::core::time::Duration;
#[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
pub use std::collections::Bound;
#[cfg(range_inclusive)]
#[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", not(no_std_atomic)))]
pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize, Ordering,
};
#[cfg(all(feature = "std", not(no_std_atomic64)))]
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration;
}
////////////////////////////////////////////////////////////////////////////////
@@ -242,13 +265,21 @@ pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};
// Generated code uses these to support no_std. Not public API.
// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod export;
#[path = "private/mod.rs"]
pub mod __private;
// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
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;
#[cfg(not(feature = "std"))]
mod std_error;
// Re-export #[derive(Serialize, Deserialize)].
//
@@ -262,3 +293,8 @@ extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
pub struct T;
}
+1 -1
View File
@@ -124,7 +124,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::export::Result<$v::Value, Self::Error>
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error>
where
$v: $crate::de::Visitor<$l>,
{
+164 -115
View File
@@ -1,9 +1,10 @@
use lib::*;
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))]
use de::{MapAccess, Unexpected};
use de::{DeserializeSeed, MapAccess, Unexpected};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{
@@ -12,6 +13,8 @@ pub use self::content::{
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
};
pub use seed::InPlaceSeed;
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
@@ -53,9 +56,10 @@ where
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error>
pub fn borrow_cow_str<'de: 'a, 'a, D, R>(deserializer: D) -> Result<R, D::Error>
where
D: Deserializer<'de>,
R: From<Cow<'a, str>>,
{
struct CowStrVisitor;
@@ -121,13 +125,14 @@ where
}
}
deserializer.deserialize_str(CowStrVisitor)
deserializer.deserialize_str(CowStrVisitor).map(From::from)
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error>
pub fn borrow_cow_bytes<'de: 'a, 'a, D, R>(deserializer: D) -> Result<R, D::Error>
where
D: Deserializer<'de>,
R: From<Cow<'a, [u8]>>,
{
struct CowBytesVisitor;
@@ -181,30 +186,9 @@ where
}
}
deserializer.deserialize_bytes(CowBytesVisitor)
}
pub mod size_hint {
use lib::*;
pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
I: Iterator,
{
helper(iter.size_hint())
}
#[inline]
pub fn cautious(hint: Option<usize>) -> usize {
cmp::min(hint.unwrap_or(0), 4096)
}
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
match bounds {
(lower, Some(upper)) if lower == upper => Some(upper),
_ => None,
}
}
deserializer
.deserialize_bytes(CowBytesVisitor)
.map(From::from)
}
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -221,7 +205,8 @@ mod content {
use lib::*;
use super::size_hint;
use __private::size_hint;
use actually_private;
use de::{
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
MapAccess, SeqAccess, Unexpected, Visitor,
@@ -231,7 +216,7 @@ mod content {
/// deserializing untagged enums and internally tagged enums.
///
/// Not public API. Use serde-value instead.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Content<'de> {
Bool(bool),
@@ -310,7 +295,7 @@ mod content {
// Untagged and internally tagged enums are only supported in
// self-describing formats.
let visitor = ContentVisitor { value: PhantomData };
deserializer.deserialize_any(visitor)
deserializer.__deserialize_content(actually_private::T, visitor)
}
}
@@ -820,15 +805,17 @@ mod content {
/// Not public API.
pub struct TaggedContentVisitor<'de, T> {
tag_name: &'static str,
expecting: &'static str,
value: PhantomData<TaggedContent<'de, T>>,
}
impl<'de, T> TaggedContentVisitor<'de, T> {
/// Visitor for the content of an internally tagged enum with the given
/// tag name.
pub fn new(name: &'static str) -> Self {
pub fn new(name: &'static str, expecting: &'static str) -> Self {
TaggedContentVisitor {
tag_name: name,
expecting: expecting,
value: PhantomData,
}
}
@@ -857,7 +844,7 @@ mod content {
type Value = TaggedContent<'de, T>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("internally tagged enum")
fmt.write_str(self.expecting)
}
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
@@ -1036,6 +1023,25 @@ mod content {
_ => Err(self.invalid_type(&visitor)),
}
}
fn deserialize_float<V>(self, visitor: V) -> Result<V::Value, E>
where
V: Visitor<'de>,
{
match self.content {
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U16(v) => visitor.visit_u16(v),
Content::U32(v) => visitor.visit_u32(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I8(v) => visitor.visit_i8(v),
Content::I16(v) => visitor.visit_i16(v),
Content::I32(v) => visitor.visit_i32(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
}
}
fn visit_content_seq<'de, V, E>(content: Vec<Content<'de>>, visitor: V) -> Result<V::Value, E>
@@ -1175,25 +1181,14 @@ mod content {
where
V: Visitor<'de>,
{
match self.content {
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
self.deserialize_float(visitor)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.content {
Content::F64(v) => visitor.visit_f64(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
self.deserialize_float(visitor)
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -1293,8 +1288,9 @@ mod content {
// }
//
// We want {"topic":"Info"} to deserialize even though
// ordinarily unit structs do not deserialize from empty map.
// ordinarily unit structs do not deserialize from empty map/seq.
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(),
_ => self.deserialize_any(visitor),
}
}
@@ -1420,6 +1416,7 @@ mod content {
Content::ByteBuf(v) => visitor.visit_byte_buf(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U64(v) => visitor.visit_u64(v),
_ => Err(self.invalid_type(&visitor)),
}
}
@@ -1431,6 +1428,18 @@ mod content {
drop(self);
visitor.visit_unit()
}
fn __deserialize_content<V>(
self,
_: actually_private::T,
visitor: V,
) -> Result<Content<'de>, Self::Error>
where
V: Visitor<'de, Value = Content<'de>>,
{
let _ = visitor;
Ok(self.content)
}
}
impl<'de, E> ContentDeserializer<'de, E> {
@@ -1557,7 +1566,7 @@ mod content {
other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
@@ -1746,6 +1755,25 @@ mod content {
_ => Err(self.invalid_type(&visitor)),
}
}
fn deserialize_float<V>(self, visitor: V) -> Result<V::Value, E>
where
V: Visitor<'de>,
{
match *self.content {
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U16(v) => visitor.visit_u16(v),
Content::U32(v) => visitor.visit_u32(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I8(v) => visitor.visit_i8(v),
Content::I16(v) => visitor.visit_i16(v),
Content::I32(v) => visitor.visit_i32(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
}
}
fn visit_content_seq_ref<'a, 'de, V, E>(
@@ -1893,25 +1921,14 @@ mod content {
where
V: Visitor<'de>,
{
match *self.content {
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
self.deserialize_float(visitor)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match *self.content {
Content::F64(v) => visitor.visit_f64(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
self.deserialize_float(visitor)
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -2123,6 +2140,7 @@ mod content {
Content::ByteBuf(ref v) => visitor.visit_bytes(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U64(v) => visitor.visit_u64(v),
_ => Err(self.invalid_type(&visitor)),
}
}
@@ -2133,6 +2151,18 @@ mod content {
{
visitor.visit_unit()
}
fn __deserialize_content<V>(
self,
_: actually_private::T,
visitor: V,
) -> Result<Content<'de>, Self::Error>
where
V: Visitor<'de, Value = Content<'de>>,
{
let _ = visitor;
Ok(self.content.clone())
}
}
impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> {
@@ -2246,7 +2276,7 @@ mod content {
other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
@@ -2468,7 +2498,7 @@ mod content {
where
M: MapAccess<'de>,
{
while let Some(_) = try!(access.next_entry::<IgnoredAny, IgnoredAny>()) {}
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
Ok(())
}
}
@@ -2508,6 +2538,13 @@ mod content {
{
Ok(())
}
fn visit_none<E>(self) -> Result<(), E>
where
E: de::Error,
{
Ok(())
}
}
}
@@ -2529,11 +2566,13 @@ pub trait IdentifierDeserializer<'de, E: Error> {
fn from(self) -> Self::Deserializer;
}
impl<'de, E> IdentifierDeserializer<'de, E> for u32
pub struct Borrowed<'de, T: 'de + ?Sized>(pub &'de T);
impl<'de, E> IdentifierDeserializer<'de, E> for u64
where
E: Error,
{
type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
type Deserializer = <u64 as IntoDeserializer<'de, E>>::Deserializer;
fn from(self) -> Self::Deserializer {
self.into_deserializer()
@@ -2545,20 +2584,6 @@ pub struct StrDeserializer<'a, E> {
marker: PhantomData<E>,
}
impl<'a, E> IdentifierDeserializer<'a, E> for &'a str
where
E: Error,
{
type Deserializer = StrDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
StrDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E>
where
E: Error,
@@ -2579,26 +2604,12 @@ where
}
}
pub struct BytesDeserializer<'a, E> {
value: &'a [u8],
pub struct BorrowedStrDeserializer<'de, E> {
value: &'de str,
marker: PhantomData<E>,
}
impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8]
where
E: Error,
{
type Deserializer = BytesDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
BytesDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E>
impl<'de, E> Deserializer<'de> for BorrowedStrDeserializer<'de, E>
where
E: Error,
{
@@ -2608,7 +2619,7 @@ where
where
V: Visitor<'de>,
{
visitor.visit_bytes(self.value)
visitor.visit_borrowed_str(self.value)
}
forward_to_deserialize_any! {
@@ -2618,21 +2629,53 @@ where
}
}
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
///
/// Wraps a mutable reference and calls deserialize_in_place on it.
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
impl<'a, E> IdentifierDeserializer<'a, E> for &'a str
where
T: Deserialize<'de>,
E: Error,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize_in_place(deserializer, self.0)
type Deserializer = StrDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
StrDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'de, E> IdentifierDeserializer<'de, E> for Borrowed<'de, str>
where
E: Error,
{
type Deserializer = BorrowedStrDeserializer<'de, E>;
fn from(self) -> Self::Deserializer {
BorrowedStrDeserializer {
value: self.0,
marker: PhantomData,
}
}
}
impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8]
where
E: Error,
{
type Deserializer = BytesDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
BytesDeserializer::new(self)
}
}
impl<'de, E> IdentifierDeserializer<'de, E> for Borrowed<'de, [u8]>
where
E: Error,
{
type Deserializer = BorrowedBytesDeserializer<'de, E>;
fn from(self) -> Self::Deserializer {
BorrowedBytesDeserializer::new(self.0)
}
}
@@ -2709,7 +2752,7 @@ where
}
Err(Error::custom(format_args!(
"no variant of enum {} not found in flattened data",
"no variant of enum {} found in flattened data",
name
)))
}
@@ -2750,6 +2793,13 @@ where
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
forward_to_deserialize_other! {
deserialize_bool()
deserialize_i8()
@@ -2767,7 +2817,6 @@ where
deserialize_string()
deserialize_bytes()
deserialize_byte_buf()
deserialize_unit()
deserialize_unit_struct(&'static str)
deserialize_seq()
deserialize_tuple(usize)
@@ -2808,7 +2857,7 @@ where
where
T: DeserializeSeed<'de>,
{
while let Some(item) = self.iter.next() {
for item in &mut self.iter {
// Items in the vector are nulled out when used by a struct.
if let Some((ref key, ref content)) = *item {
self.pending_content = Some(content);
@@ -2910,7 +2959,7 @@ where
where
T: DeserializeSeed<'de>,
{
while let Some(item) = self.iter.next() {
for item in &mut self.iter {
if let Some((ref key, ref content)) = *item {
// Do not take(), instead borrow this entry. The internally tagged
// enum does its own buffering so we can't tell whether this entry
@@ -1,3 +1,35 @@
// Used only by Serde doc tests. Not public API.
use lib::*;
use ser;
#[doc(hidden)]
#[derive(Debug)]
pub struct Error;
impl ser::Error for Error {
fn custom<T>(_: T) -> Self
where
T: Display,
{
unimplemented!()
}
}
#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
unimplemented!()
}
}
impl Display for Error {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
unimplemented!()
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private_serialize {
@@ -10,19 +42,6 @@ macro_rules! __private_serialize {
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private_deserialize {
() => {
trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: $crate::Deserializer<'de>;
}
};
}
/// Used only by Serde doc tests. Not public API.
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! __serialize_unimplemented {
@@ -37,7 +56,7 @@ 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::export::Result<Self::$ret, Self::Error> {
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error> {
unimplemented!()
}
};
+48 -2
View File
@@ -1,4 +1,50 @@
mod macros;
#[cfg(not(no_serde_derive))]
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 self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::{ToString, Vec};
#[cfg(not(no_core_try_from))]
pub use lib::convert::TryFrom;
mod string {
use lib::*;
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::__private::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "std", feature = "alloc")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
}
+34 -50
View File
@@ -335,33 +335,6 @@ where
}
}
/// Used only by Serde doc tests. Not public API.
#[doc(hidden)]
#[derive(Debug)]
pub struct Error;
impl ser::Error for Error {
fn custom<T>(_: T) -> Self
where
T: Display,
{
unimplemented!()
}
}
#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
unimplemented!()
}
}
impl Display for Error {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
unimplemented!()
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
mod content {
use lib::*;
@@ -452,7 +425,6 @@ mod content {
}
}
#[derive(Debug)]
pub enum Content {
Bool(bool),
@@ -1032,7 +1004,7 @@ impl<'a, M> FlatMapSerializer<'a, M>
where
M: SerializeMap + 'a,
{
fn bad_type(self, what: Unsupported) -> M::Error {
fn bad_type(what: Unsupported) -> M::Error {
ser::Error::custom(format_args!(
"can only flatten structs and maps (got {})",
what
@@ -1057,59 +1029,59 @@ where
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
Err(Self::bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
Err(Self::bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
Err(Self::bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
Err(Self::bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
Err(Self::bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
Err(Self::bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
@@ -1124,11 +1096,11 @@ where
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
Ok(())
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
Err(Self::bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(
@@ -1137,7 +1109,7 @@ where
_: u32,
_: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
Err(Self::bad_type(Unsupported::Enum))
}
fn serialize_newtype_struct<T: ?Sized>(
@@ -1166,11 +1138,11 @@ where
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
Err(Self::bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
Err(Self::bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(
@@ -1178,7 +1150,7 @@ where
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
Err(Self::bad_type(Unsupported::TupleStruct))
}
fn serialize_tuple_variant(
@@ -1188,7 +1160,7 @@ where
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
Err(Self::bad_type(Unsupported::Enum))
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -1243,6 +1215,18 @@ where
self.0.serialize_value(value)
}
fn serialize_entry<K: ?Sized, V: ?Sized>(
&mut self,
key: &K,
value: &V,
) -> Result<(), Self::Error>
where
K: Serialize,
V: Serialize,
{
self.0.serialize_entry(key, value)
}
fn end(self) -> Result<(), Self::Error> {
Ok(())
}
+21
View File
@@ -0,0 +1,21 @@
use lib::*;
pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
I: Iterator,
{
helper(iter.size_hint())
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[inline]
pub fn cautious(hint: Option<usize>) -> usize {
cmp::min(hint.unwrap_or(0), 4096)
}
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
match bounds {
(lower, Some(upper)) if lower == upper => Some(upper),
_ => None,
}
}
+174
View File
@@ -0,0 +1,174 @@
use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};
impl Error for fmt::Error {
fn custom<T: Display>(_msg: T) -> Self {
fmt::Error
}
}
macro_rules! fmt_primitives {
($($f:ident: $t:ty,)*) => {
$(
fn $f(self, v: $t) -> fmt::Result {
Display::fmt(&v, self)
}
)*
};
}
/// ```edition2018
/// use serde::Serialize;
/// use std::fmt::{self, Display};
///
/// #[derive(Serialize)]
/// #[serde(rename_all = "kebab-case")]
/// pub enum MessageType {
/// StartRequest,
/// EndRequest,
/// }
///
/// impl Display for MessageType {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// self.serialize(f)
/// }
/// }
/// ```
impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
type Ok = ();
type Error = fmt::Error;
type SerializeSeq = Impossible<(), fmt::Error>;
type SerializeTuple = Impossible<(), fmt::Error>;
type SerializeTupleStruct = Impossible<(), fmt::Error>;
type SerializeTupleVariant = Impossible<(), fmt::Error>;
type SerializeMap = Impossible<(), fmt::Error>;
type SerializeStruct = Impossible<(), fmt::Error>;
type SerializeStructVariant = Impossible<(), fmt::Error>;
fmt_primitives! {
serialize_bool: bool,
serialize_i8: i8,
serialize_i16: i16,
serialize_i32: i32,
serialize_i64: i64,
serialize_u8: u8,
serialize_u16: u16,
serialize_u32: u32,
serialize_u64: u64,
serialize_f32: f32,
serialize_f64: f64,
serialize_char: char,
serialize_str: &str,
serialize_unit_struct: &'static str,
}
serde_if_integer128! {
fmt_primitives! {
serialize_i128: i128,
serialize_u128: u128,
}
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> fmt::Result {
Display::fmt(variant, self)
}
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
where
T: Serialize,
{
Serialize::serialize(value, self)
}
fn serialize_bytes(self, _v: &[u8]) -> fmt::Result {
Err(fmt::Error)
}
fn serialize_none(self) -> fmt::Result {
Err(fmt::Error)
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
where
T: Serialize,
{
Err(fmt::Error)
}
fn serialize_unit(self) -> fmt::Result {
Err(fmt::Error)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> fmt::Result
where
T: Serialize,
{
Err(fmt::Error)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, fmt::Error> {
Err(fmt::Error)
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, fmt::Error> {
Err(fmt::Error)
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, fmt::Error> {
Err(fmt::Error)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, fmt::Error> {
Err(fmt::Error)
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, fmt::Error> {
Err(fmt::Error)
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, fmt::Error> {
Err(fmt::Error)
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, fmt::Error> {
Err(fmt::Error)
}
fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
where
T: Display,
{
Display::fmt(value, self)
}
}
+150 -15
View File
@@ -160,10 +160,12 @@ macro_rules! array_impls {
}
}
array_impls!(01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32);
array_impls! {
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32
}
////////////////////////////////////////////////////////////////////////////////
@@ -237,7 +239,7 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(range_inclusive)]
#[cfg(not(no_range_inclusive))]
impl<Idx> Serialize for RangeInclusive<Idx>
where
Idx: Serialize,
@@ -256,6 +258,29 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<T> Serialize for Bound<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Bound::Unbounded => serializer.serialize_unit_variant("Bound", 0, "Unbounded"),
Bound::Included(ref value) => {
serializer.serialize_newtype_variant("Bound", 1, "Included", value)
}
Bound::Excluded(ref value) => {
serializer.serialize_newtype_variant("Bound", 2, "Excluded", value)
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
impl Serialize for () {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -442,7 +467,7 @@ where
macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => {
$(
#[cfg(num_nonzero)]
#[cfg(not(no_num_nonzero))]
impl Serialize for num::$T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -456,7 +481,6 @@ macro_rules! nonzero_integers {
}
nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8,
NonZeroU16,
NonZeroU32,
@@ -464,12 +488,26 @@ nonzero_integers! {
NonZeroUsize,
}
#[cfg(not(no_num_nonzero_signed))]
nonzero_integers! {
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
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>
@@ -553,7 +591,7 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(core_duration, feature = "std"))]
#[cfg(any(feature = "std", not(no_core_duration)))]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -578,7 +616,7 @@ impl Serialize for SystemTime {
use super::SerializeStruct;
let duration_since_epoch = self
.duration_since(UNIX_EPOCH)
.expect("SystemTime must be later than UNIX_EPOCH");
.map_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()));
@@ -595,7 +633,7 @@ impl Serialize for SystemTime {
#[cfg(feature = "std")]
macro_rules! serialize_display_bounded_length {
($value:expr, $max:expr, $serializer:expr) => {{
let mut buffer: [u8; $max] = unsafe { mem::uninitialized() };
let mut buffer = [0u8; $max];
let remaining_len = {
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
@@ -607,7 +645,7 @@ macro_rules! serialize_display_bounded_length {
// write! only provides fmt::Formatter to Display implementations, which
// has methods write_str and write_char but no method to write arbitrary
// bytes. Therefore `written` must be valid UTF-8.
let written_str = unsafe { str::from_utf8_unchecked(written) };
let written_str = str::from_utf8(written).expect("must be valid UTF-8");
$serializer.serialize_str(written_str)
}};
}
@@ -636,6 +674,52 @@ impl Serialize for net::IpAddr {
}
}
#[cfg(feature = "std")]
const DEC_DIGITS_LUT: &'static [u8] = b"\
0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
6061626364656667686970717273747576777879\
8081828384858687888990919293949596979899";
#[cfg(feature = "std")]
#[inline]
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
out[0] = b'0' + n;
out[1] = DEC_DIGITS_LUT[d1];
out[2] = DEC_DIGITS_LUT[d1 + 1];
3
} else if n >= 10 {
let d1 = (n << 1) as usize;
out[0] = DEC_DIGITS_LUT[d1];
out[1] = DEC_DIGITS_LUT[d1 + 1];
2
} else {
out[0] = b'0' + n;
1
}
}
#[cfg(feature = "std")]
#[test]
fn test_format_u8() {
let mut i = 0u8;
loop {
let mut buf = [0u8; 3];
let written = format_u8(i, &mut buf);
assert_eq!(i.to_string().as_bytes(), &buf[..written]);
match i.checked_add(1) {
Some(next) => i = next,
None => break,
}
}
}
#[cfg(feature = "std")]
impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -645,7 +729,14 @@ impl Serialize for net::Ipv4Addr {
if serializer.is_human_readable() {
const MAX_LEN: usize = 15;
debug_assert_eq!(MAX_LEN, "101.102.103.104".len());
serialize_display_bounded_length!(self, MAX_LEN, serializer)
let mut buf = [b'.'; MAX_LEN];
let mut written = format_u8(self.octets()[0], &mut buf);
for oct in &self.octets()[1..] {
// Skip over delimiters that we initialized buf with
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
}
// We've only written ASCII bytes to the buffer, so it is valid UTF-8
serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) })
} else {
self.octets().serialize(serializer)
}
@@ -715,10 +806,10 @@ impl Serialize for net::SocketAddrV6 {
S: Serializer,
{
if serializer.is_human_readable() {
const MAX_LEN: usize = 47;
const MAX_LEN: usize = 58;
debug_assert_eq!(
MAX_LEN,
"[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len()
"[1001:1002:1003:1004:1005:1006:1007:1008%4294967295]:65000".len()
);
serialize_display_bounded_length!(self, MAX_LEN, serializer)
} else {
@@ -786,7 +877,6 @@ impl Serialize for OsString {
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<T> Serialize for Wrapping<T>
where
T: Serialize,
@@ -799,3 +889,48 @@ where
self.0.serialize(serializer)
}
}
#[cfg(not(no_core_reverse))]
impl<T> Serialize for Reverse<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl {
($($ty:ident)*) => {
$(
impl Serialize for $ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// Matches the atomic ordering used in libcore for the Debug impl
self.load(Ordering::SeqCst).serialize(serializer)
}
}
)*
}
}
#[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! {
AtomicBool
AtomicI8 AtomicI16 AtomicI32 AtomicIsize
AtomicU8 AtomicU16 AtomicU32 AtomicUsize
}
#[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! {
AtomicI64 AtomicU64
}
+1 -1
View File
@@ -17,7 +17,7 @@ use ser::{
///
/// ```edition2018
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error;
/// # use serde::__private::doc::Error;
/// #
/// # struct MySerializer;
/// #
+46 -47
View File
@@ -30,7 +30,7 @@
//! # The Serializer trait
//!
//! [`Serializer`] implementations are provided by third-party crates, for
//! example [`serde_json`], [`serde_yaml`] and [`bincode`].
//! example [`serde_json`], [`serde_yaml`] and [`postcard`].
//!
//! A partial list of well-maintained formats is given on the [Serde
//! website][data formats].
@@ -56,13 +56,13 @@
//! - PhantomData\<T\>
//! - **Wrapper types**:
//! - Box\<T\>
//! - Rc\<T\>
//! - Arc\<T\>
//! - Cow\<'a, T\>
//! - Cell\<T\>
//! - RefCell\<T\>
//! - Mutex\<T\>
//! - RwLock\<T\>
//! - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - **Collection types**:
//! - BTreeMap\<K, V\>
//! - BTreeSet\<T\>
@@ -84,6 +84,7 @@
//! - PathBuf
//! - Range\<T\>
//! - RangeInclusive\<T\>
//! - Bound\<T\>
//! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**:
@@ -98,7 +99,7 @@
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
//! [`Serialize`]: ../trait.Serialize.html
//! [`Serializer`]: ../trait.Serializer.html
//! [`bincode`]: https://github.com/TyOverby/bincode
//! [`postcard`]: https://github.com/jamesmunns/postcard
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
//! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json
@@ -108,11 +109,19 @@
use lib::*;
mod fmt;
mod impls;
mod impossible;
pub use self::impossible::Impossible;
#[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;
////////////////////////////////////////////////////////////////////////////////
macro_rules! declare_error_trait {
@@ -171,7 +180,7 @@ macro_rules! declare_error_trait {
}
#[cfg(feature = "std")]
declare_error_trait!(Error: Sized + error::Error);
declare_error_trait!(Error: Sized + StdError);
#[cfg(not(feature = "std"))]
declare_error_trait!(Error: Sized + Debug + Display);
@@ -305,7 +314,7 @@ pub trait Serialize {
/// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
///
/// Many Serde serializers produce text or binary data as output, for example
/// JSON or Bincode. This is not a requirement of the `Serializer` trait, and
/// JSON or Postcard. This is not a requirement of the `Serializer` trait, and
/// there are serializers that do not produce text or binary output. One example
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as
@@ -702,7 +711,7 @@ pub trait Serializer: Sized {
///
/// ```edition2018
/// # use serde::ser::{Serializer, SerializeSeq};
/// # use serde::private::ser::Error;
/// # use serde::__private::doc::Error;
/// #
/// # struct MySerializer;
/// #
@@ -1269,10 +1278,21 @@ pub trait Serializer: Sized {
<I as IntoIterator>::Item: Serialize,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
for item in iter {
try!(serializer.serialize_element(&item));
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));
}
}
serializer.end()
}
@@ -1309,10 +1329,21 @@ pub trait Serializer: Sized {
I: IntoIterator<Item = (K, V)>,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iter.len_hint()));
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
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));
}
}
serializer.end()
}
@@ -1351,10 +1382,7 @@ pub trait Serializer: Sized {
where
T: Display,
{
use lib::fmt::Write;
let mut string = String::new();
write!(string, "{}", value).unwrap();
self.serialize_str(&string)
self.serialize_str(&value.to_string())
}
/// Serialize a string produced by an implementation of `Display`.
@@ -1395,7 +1423,7 @@ pub trait Serializer: Sized {
/// Some types have a human-readable form that may be somewhat expensive to
/// construct, as well as a binary form that is compact and efficient.
/// Generally text-based formats like JSON and YAML will prefer to use the
/// human-readable one and binary formats like Bincode will prefer the
/// human-readable one and binary formats like Postcard will prefer the
/// compact one.
///
/// ```edition2018
@@ -1947,35 +1975,6 @@ pub trait SerializeStructVariant {
fn end(self) -> Result<Self::Ok, Self::Error>;
}
trait LenHint: Iterator {
fn len_hint(&self) -> Option<usize>;
}
impl<I> LenHint for I
where
I: Iterator,
{
#[cfg(not(feature = "unstable"))]
fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
#[cfg(feature = "unstable")]
default fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
}
#[cfg(feature = "unstable")]
impl<I> LenHint for I
where
I: ExactSizeIterator,
{
fn len_hint(&self) -> Option<usize> {
Some(self.len())
}
}
fn iterator_len_hint<I>(iter: &I) -> Option<usize>
where
I: Iterator,
+48
View File
@@ -0,0 +1,48 @@
use 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.
///
/// Serde's error traits [`serde::ser::Error`] and [`serde::de::Error`] require
/// [`std::error::Error`] as a supertrait, but only when Serde is built with
/// "std" enabled. Data formats that don't care about no\_std support should
/// generally provide their error types with a `std::error::Error` impl
/// directly:
///
/// ```edition2018
/// #[derive(Debug)]
/// struct MySerError {...}
///
/// impl serde::ser::Error for MySerError {...}
///
/// impl std::fmt::Display for MySerError {...}
///
/// // We don't support no_std!
/// impl std::error::Error for MySerError {}
/// ```
///
/// Data formats that *do* support no\_std may either have a "std" feature of
/// their own:
///
/// ```toml
/// [features]
/// std = ["serde/std"]
/// ```
///
/// ```edition2018
/// #[cfg(feature = "std")]
/// impl std::error::Error for MySerError {}
/// ```
///
/// ... or else provide the std Error impl unconditionally via Serde's
/// re-export:
///
/// ```edition2018
/// impl serde::ser::StdError for MySerError {}
/// ```
pub trait Error: Debug + Display {
/// The underlying cause of this error, if any.
fn source(&self) -> Option<&(Error + 'static)> {
None
}
}
+1
View File
@@ -0,0 +1 @@
msrv = "1.31.0"
+14 -13
View File
@@ -1,19 +1,17 @@
[package]
name = "serde_derive"
version = "1.0.85" # remember to update html_root_url
version = "1.0.142" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
categories = ["no-std"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/derive.html"
keywords = ["serde", "serialization", "no_std"]
homepage = "https://serde.rs"
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
keywords = ["serde", "serialization", "no_std", "derive"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
repository = "https://github.com/serde-rs/serde"
rust-version = "1.31"
[features]
default = []
@@ -24,9 +22,12 @@ name = "serde_derive"
proc-macro = true
[dependencies]
proc-macro2 = "0.4"
quote = "0.6.3"
syn = { version = "0.15.22", features = ["visit"] }
proc-macro2 = "1.0"
quote = "1.0"
syn = "1.0.90"
[dev-dependencies]
serde = { version = "1.0", path = "../serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+36
View File
@@ -0,0 +1,36 @@
use std::env;
use std::process::Command;
use std::str;
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
};
// Underscore const names stabilized in Rust 1.37:
// https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html#using-unnamed-const-items-for-macros
if minor < 37 {
println!("cargo:rustc-cfg=no_underscore_consts");
}
// The ptr::addr_of! macro stabilized in Rust 1.51:
// https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis
if minor < 51 {
println!("cargo:rustc-cfg=no_ptr_addr_of");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
pieces.next()?.parse().ok()
}
+115 -26
View File
@@ -2,10 +2,9 @@ use std::collections::HashSet;
use syn;
use syn::punctuated::{Pair, Punctuated};
use syn::visit::{self, Visit};
use internals::ast::{Container, Data};
use internals::attr;
use internals::{attr, ungroup};
use proc_macro2::Span;
@@ -17,8 +16,8 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
params: generics
.params
.iter()
.map(|param| match *param {
syn::GenericParam::Type(ref param) => syn::GenericParam::Type(syn::TypeParam {
.map(|param| match param {
syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam {
eq_token: None,
default: None,
..param.clone()
@@ -50,8 +49,8 @@ pub fn with_where_predicates_from_fields(
let predicates = cont
.data
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
.filter_map(|field| from_field(&field.attrs))
.flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
@@ -63,8 +62,8 @@ pub fn with_where_predicates_from_variants(
generics: &syn::Generics,
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return generics.clone();
}
@@ -72,8 +71,8 @@ pub fn with_where_predicates_from_variants(
let predicates = variants
.iter()
.flat_map(|variant| from_variant(&variant.attrs))
.flat_map(|predicates| predicates.to_vec());
.filter_map(|variant| from_variant(&variant.attrs))
.flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
@@ -112,10 +111,11 @@ pub fn with_bound(
// parameters.
associated_type_usage: Vec<&'ast syn::TypePath>,
}
impl<'ast> Visit<'ast> for FindTyParams<'ast> {
impl<'ast> FindTyParams<'ast> {
fn visit_field(&mut self, field: &'ast syn::Field) {
if let syn::Type::Path(ref ty) = field.ty {
if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() {
if let syn::Type::Path(ty) = ungroup(&field.ty) {
if let Some(Pair::Punctuated(t, _)) = ty.path.segments.pairs().next() {
if self.all_type_params.contains(&t.ident) {
self.associated_type_usage.push(ty);
}
@@ -126,7 +126,7 @@ pub fn with_bound(
fn visit_path(&mut self, path: &'ast syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.into_value().ident == "PhantomData" {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
@@ -138,7 +138,96 @@ pub fn with_bound(
self.relevant_type_params.insert(id.clone());
}
}
visit::visit_path(self, path);
for segment in &path.segments {
self.visit_path_segment(segment);
}
}
// Everything below is simply traversing the syntax tree.
fn visit_type(&mut self, ty: &'ast syn::Type) {
match ty {
syn::Type::Array(ty) => self.visit_type(&ty.elem),
syn::Type::BareFn(ty) => {
for arg in &ty.inputs {
self.visit_type(&arg.ty);
}
self.visit_return_type(&ty.output);
}
syn::Type::Group(ty) => self.visit_type(&ty.elem),
syn::Type::ImplTrait(ty) => {
for bound in &ty.bounds {
self.visit_type_param_bound(bound);
}
}
syn::Type::Macro(ty) => self.visit_macro(&ty.mac),
syn::Type::Paren(ty) => self.visit_type(&ty.elem),
syn::Type::Path(ty) => {
if let Some(qself) = &ty.qself {
self.visit_type(&qself.ty);
}
self.visit_path(&ty.path);
}
syn::Type::Ptr(ty) => self.visit_type(&ty.elem),
syn::Type::Reference(ty) => self.visit_type(&ty.elem),
syn::Type::Slice(ty) => self.visit_type(&ty.elem),
syn::Type::TraitObject(ty) => {
for bound in &ty.bounds {
self.visit_type_param_bound(bound);
}
}
syn::Type::Tuple(ty) => {
for elem in &ty.elems {
self.visit_type(elem);
}
}
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
fn visit_path_segment(&mut self, segment: &'ast syn::PathSegment) {
self.visit_path_arguments(&segment.arguments);
}
fn visit_path_arguments(&mut self, arguments: &'ast syn::PathArguments) {
match arguments {
syn::PathArguments::None => {}
syn::PathArguments::AngleBracketed(arguments) => {
for arg in &arguments.args {
match arg {
syn::GenericArgument::Type(arg) => self.visit_type(arg),
syn::GenericArgument::Binding(arg) => self.visit_type(&arg.ty),
syn::GenericArgument::Lifetime(_)
| syn::GenericArgument::Constraint(_)
| syn::GenericArgument::Const(_) => {}
}
}
}
syn::PathArguments::Parenthesized(arguments) => {
for argument in &arguments.inputs {
self.visit_type(argument);
}
self.visit_return_type(&arguments.output);
}
}
}
fn visit_return_type(&mut self, return_type: &'ast syn::ReturnType) {
match return_type {
syn::ReturnType::Default => {}
syn::ReturnType::Type(_, output) => self.visit_type(output),
}
}
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
match bound {
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
syn::TypeParamBound::Lifetime(_) => {}
}
}
// Type parameter should not be considered used by a macro path.
@@ -156,12 +245,12 @@ pub fn with_bound(
.collect();
let mut visitor = FindTyParams {
all_type_params: all_type_params,
all_type_params,
relevant_type_params: HashSet::new(),
associated_type_usage: Vec::new(),
};
match cont.data {
Data::Enum(ref variants) => {
match &cont.data {
Data::Enum(variants) => {
for variant in variants.iter() {
let relevant_fields = variant
.fields
@@ -172,7 +261,7 @@ pub fn with_bound(
}
}
}
Data::Struct(_, ref fields) => {
Data::Struct(_, fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visitor.visit_field(field.original);
}
@@ -255,11 +344,11 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
let params = Some(syn::GenericParam::Lifetime(def))
.into_iter()
.chain(generics.params.iter().cloned().map(|mut param| {
match param {
syn::GenericParam::Lifetime(ref mut param) => {
match &mut param {
syn::GenericParam::Lifetime(param) => {
param.bounds.push(bound.clone());
}
syn::GenericParam::Type(ref mut param) => {
syn::GenericParam::Type(param) => {
param
.bounds
.push(syn::TypeParamBound::Lifetime(bound.clone()));
@@ -271,7 +360,7 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
.collect();
syn::Generics {
params: params,
params,
..generics.clone()
}
}
@@ -291,14 +380,14 @@ fn type_of_item(cont: &Container) -> syn::Type {
.generics
.params
.iter()
.map(|param| match *param {
syn::GenericParam::Type(ref param) => {
.map(|param| match param {
syn::GenericParam::Type(param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None,
path: param.ident.clone().into(),
}))
}
syn::GenericParam::Lifetime(ref param) => {
syn::GenericParam::Lifetime(param) => {
syn::GenericArgument::Lifetime(param.lifetime.clone())
}
syn::GenericParam::Const(_) => {
+581 -426
View File
File diff suppressed because it is too large Load Diff
+26 -10
View File
@@ -1,22 +1,38 @@
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Ident, TokenStream};
use quote::format_ident;
use syn;
use try;
pub fn wrap_in_const(trait_: &str, ty: &Ident, code: TokenStream) -> TokenStream {
pub fn wrap_in_const(
serde_path: Option<&syn::Path>,
trait_: &str,
ty: &Ident,
code: TokenStream,
) -> TokenStream {
let try_replacement = try::replacement();
let dummy_const = Ident::new(
&format!("_IMPL_{}_FOR_{}", trait_, unraw(ty)),
Span::call_site(),
);
let dummy_const = if cfg!(no_underscore_consts) {
format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty))
} else {
format_ident!("_")
};
let use_serde = match serde_path {
Some(path) => quote! {
use #path as _serde;
},
None => quote! {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
},
};
quote! {
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
#[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)]
extern crate serde as _serde;
#use_serde
#try_replacement
#code
};
+12 -12
View File
@@ -27,9 +27,9 @@ macro_rules! quote_block {
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
match &self.0 {
Fragment::Expr(expr) => expr.to_tokens(out),
Fragment::Block(block) => {
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
@@ -40,9 +40,9 @@ impl ToTokens for Expr {
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out),
match &self.0 {
Fragment::Expr(expr) => expr.to_tokens(out),
Fragment::Block(block) => block.to_tokens(out),
}
}
}
@@ -52,12 +52,12 @@ impl ToTokens for Stmts {
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => {
match &self.0 {
Fragment::Expr(expr) => {
expr.to_tokens(out);
<Token![,]>::default().to_tokens(out);
}
Fragment::Block(ref block) => {
Fragment::Block(block) => {
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
@@ -66,9 +66,9 @@ impl ToTokens for Match {
impl AsRef<TokenStream> for Fragment {
fn as_ref(&self) -> &TokenStream {
match *self {
Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block,
match self {
Fragment::Expr(expr) => expr,
Fragment::Block(block) => block,
}
}
}
+21 -23
View File
@@ -23,7 +23,7 @@ pub struct Container<'a> {
/// The fields of a struct or enum.
///
/// Analagous to `syn::Data`.
/// Analogous to `syn::Data`.
pub enum Data<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
@@ -67,11 +67,9 @@ impl<'a> Container<'a> {
) -> Option<Container<'a>> {
let mut attrs = attr::Container::from_ast(cx, item);
let mut data = match item.data {
syn::Data::Enum(ref data) => {
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
}
syn::Data::Struct(ref data) => {
let mut data = match &item.data {
syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())),
syn::Data::Struct(data) => {
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
Data::Struct(style, fields)
}
@@ -82,8 +80,8 @@ impl<'a> Container<'a> {
};
let mut has_flatten = false;
match data {
Data::Enum(ref mut variants) => {
match &mut data {
Data::Enum(variants) => {
for variant in variants {
variant.attrs.rename_by_rules(attrs.rename_all_rules());
for field in &mut variant.fields {
@@ -96,7 +94,7 @@ impl<'a> Container<'a> {
}
}
}
Data::Struct(_, ref mut fields) => {
Data::Struct(_, fields) => {
for field in fields {
if field.attrs.flatten() {
has_flatten = true;
@@ -112,8 +110,8 @@ impl<'a> Container<'a> {
let mut item = Container {
ident: item.ident.clone(),
attrs: attrs,
data: data,
attrs,
data,
generics: &item.generics,
original: item,
};
@@ -124,11 +122,11 @@ impl<'a> Container<'a> {
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Data::Enum(ref variants) => {
match self {
Data::Enum(variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Data::Struct(_, ref fields) => Box::new(fields.iter()),
Data::Struct(_, fields) => Box::new(fields.iter()),
}
}
@@ -150,9 +148,9 @@ fn enum_from_ast<'a>(
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
attrs,
style,
fields,
original: variant,
}
})
@@ -165,16 +163,16 @@ fn struct_from_ast<'a>(
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
match *fields {
syn::Fields::Named(ref fields) => (
match fields {
syn::Fields::Named(fields) => (
Style::Struct,
fields_from_ast(cx, &fields.named, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) => (
syn::Fields::Unnamed(fields) => (
Style::Tuple,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
@@ -192,8 +190,8 @@ fn fields_from_ast<'a>(
.iter()
.enumerate()
.map(|(i, field)| Field {
member: match field.ident {
Some(ref ident) => syn::Member::Named(ident.clone()),
member: match &field.ident {
Some(ident) => syn::Member::Named(ident.clone()),
None => syn::Member::Unnamed(i.into()),
},
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
File diff suppressed because it is too large Load Diff
+42 -19
View File
@@ -5,7 +5,7 @@
#[allow(deprecated, unused_imports)]
use std::ascii::AsciiExt;
use std::str::FromStr;
use std::fmt::{self, Debug, Display};
use self::RenameRule::*;
@@ -17,7 +17,7 @@ pub enum RenameRule {
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "UPPERCASE" style.
UPPERCASE,
UpperCase,
/// Rename direct children to "PascalCase" style, as typically used for
/// enum variants.
PascalCase,
@@ -35,13 +35,35 @@ pub enum RenameRule {
ScreamingKebabCase,
}
static RENAME_RULES: &[(&str, RenameRule)] = &[
("lowercase", LowerCase),
("UPPERCASE", UpperCase),
("PascalCase", PascalCase),
("camelCase", CamelCase),
("snake_case", SnakeCase),
("SCREAMING_SNAKE_CASE", ScreamingSnakeCase),
("kebab-case", KebabCase),
("SCREAMING-KEBAB-CASE", ScreamingKebabCase),
];
impl RenameRule {
pub fn from_str(rename_all_str: &str) -> Result<Self, ParseError> {
for (name, rule) in RENAME_RULES {
if rename_all_str == *name {
return Ok(*rule);
}
}
Err(ParseError {
unknown: rename_all_str,
})
}
/// Apply a renaming rule to an enum variant, returning the version expected in the source.
pub fn apply_to_variant(&self, variant: &str) -> String {
match *self {
None | PascalCase => variant.to_owned(),
LowerCase => variant.to_ascii_lowercase(),
UPPERCASE => variant.to_ascii_uppercase(),
UpperCase => variant.to_ascii_uppercase(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
@@ -65,7 +87,7 @@ impl RenameRule {
pub fn apply_to_field(&self, field: &str) -> String {
match *self {
None | LowerCase | SnakeCase => field.to_owned(),
UPPERCASE => field.to_ascii_uppercase(),
UpperCase => field.to_ascii_uppercase(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
@@ -92,21 +114,22 @@ impl RenameRule {
}
}
impl FromStr for RenameRule {
type Err = ();
pub struct ParseError<'a> {
unknown: &'a str,
}
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str {
"lowercase" => Ok(LowerCase),
"UPPERCASE" => Ok(UPPERCASE),
"PascalCase" => Ok(PascalCase),
"camelCase" => Ok(CamelCase),
"snake_case" => Ok(SnakeCase),
"SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
"kebab-case" => Ok(KebabCase),
"SCREAMING-KEBAB-CASE" => Ok(ScreamingKebabCase),
_ => Err(()),
impl<'a> Display for ParseError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("unknown rename rule `rename_all = ")?;
Debug::fmt(self.unknown, f)?;
f.write_str("`, expected one of ")?;
for (i, (name, _rule)) in RENAME_RULES.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
Debug::fmt(name, f)?;
}
Ok(())
}
}
@@ -131,7 +154,7 @@ fn rename_variants() {
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(UPPERCASE.apply_to_variant(original), upper);
assert_eq!(UpperCase.apply_to_variant(original), upper);
assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake);
@@ -163,7 +186,7 @@ fn rename_fields() {
("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(UPPERCASE.apply_to_field(original), upper);
assert_eq!(UpperCase.apply_to_field(original), upper);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
assert_eq!(SnakeCase.apply_to_field(original), original);
+46 -57
View File
@@ -1,6 +1,6 @@
use internals::ast::{Container, Data, Field, Style};
use internals::attr::{Identifier, TagType};
use internals::{Ctxt, Derive};
use internals::{ungroup, Ctxt, Derive};
use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs
@@ -13,6 +13,7 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont);
check_transparent(cx, cont, derive);
check_from_and_try_from(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
@@ -31,8 +32,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
if cont.data.has_getter() && cont.attrs.remote().is_none() {
cx.error_spanned_by(
cont.original,
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
"#[serde(getter = \"...\")] can only be used in structs that have #[serde(remote = \"...\")]",
);
}
}
@@ -41,17 +41,17 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
/// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(ref variants) => {
match &cont.data {
Data::Enum(variants) => {
for variant in variants {
for field in &variant.fields {
check_flatten_field(cx, variant.style, field);
}
}
}
Data::Struct(style, ref fields) => {
Data::Struct(style, fields) => {
for field in fields {
check_flatten_field(cx, style, field);
check_flatten_field(cx, *style, field);
}
}
}
@@ -76,25 +76,6 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
}
_ => {}
}
if field.attrs.skip_serializing() {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] can not be combined with \
#[serde(skip_serializing)]",
);
} else if field.attrs.skip_serializing_if().is_some() {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] can not be combined with \
#[serde(skip_serializing_if = \"...\")]",
);
} else if field.attrs.skip_deserializing() {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] can not be combined with \
#[serde(skip_deserializing)]",
);
}
}
/// The `other` attribute must be used at most once and it must be the last
@@ -104,8 +85,8 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return;
}
@@ -188,8 +169,8 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return;
}
@@ -201,8 +182,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
"variant `{}` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]",
variant.ident
),
);
@@ -215,8 +195,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
"variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing)]",
variant.ident, member
),
);
@@ -226,8 +205,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
"variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, member
),
);
@@ -240,8 +218,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
"variant `{}` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]",
variant.ident
),
);
@@ -254,8 +231,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
"variant `{}` cannot have both #[serde(deserialize_with)] and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, member
),
);
@@ -270,13 +246,13 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => return,
};
let tag = match *cont.attrs.tag() {
TagType::Internal { ref tag } => tag.as_str(),
let tag = match cont.attrs.tag() {
TagType::Internal { tag } => tag.as_str(),
TagType::External | TagType::Adjacent { .. } | TagType::None => return,
};
@@ -284,7 +260,7 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
cont.original,
format!("variant field name `{}` conflicts with internal tag", tag),
)
);
};
for variant in variants {
@@ -317,11 +293,8 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
let (type_tag, content_tag) = match *cont.attrs.tag() {
TagType::Adjacent {
ref tag,
ref content,
} => (tag, content),
let (type_tag, content_tag) = match cont.attrs.tag() {
TagType::Adjacent { tag, content } => (tag, content),
TagType::Internal { .. } | TagType::External | TagType::None => return,
};
@@ -349,6 +322,13 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
);
}
if cont.attrs.type_try_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed with #[serde(try_from = \"...\")]",
);
}
if cont.attrs.type_into().is_some() {
cx.error_spanned_by(
cont.original,
@@ -356,7 +336,7 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
);
}
let fields = match cont.data {
let fields = match &mut cont.data {
Data::Enum(_) => {
cx.error_spanned_by(
cont.original,
@@ -371,7 +351,7 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
);
return;
}
Data::Struct(_, ref mut fields) => fields,
Data::Struct(_, fields) => fields,
};
let mut transparent_field = None;
@@ -409,16 +389,16 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
}
fn member_message(member: &Member) -> String {
match *member {
Member::Named(ref ident) => format!("`{}`", ident),
Member::Unnamed(ref i) => format!("#{}", i.index),
match member {
Member::Named(ident) => format!("`{}`", ident),
Member::Unnamed(i) => format!("#{}", i.index),
}
}
fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ref ty) = *field.ty {
if let Type::Path(ty) = ungroup(field.ty) {
if let Some(seg) = ty.path.segments.last() {
if seg.into_value().ident == "PhantomData" {
if seg.ident == "PhantomData" {
return false;
}
}
@@ -429,3 +409,12 @@ fn allow_transparent(field: &Field, derive: Derive) -> bool {
Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(),
}
}
fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) {
if cont.attrs.type_from().is_some() && cont.attrs.type_try_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(from = \"...\")] and #[serde(try_from = \"...\")] conflict with each other",
);
}
}
+5
View File
@@ -38,6 +38,11 @@ impl Ctxt {
.push(syn::Error::new_spanned(obj.into_token_stream(), msg));
}
/// Add one of Syn's parse errors.
pub fn syn_error(&self, err: syn::Error) {
self.errors.borrow_mut().as_mut().unwrap().push(err);
}
/// Consume this object, producing a formatted error string if there are errors.
pub fn check(self) -> Result<(), Vec<syn::Error>> {
let errors = self.errors.borrow_mut().take().unwrap();
+14
View File
@@ -4,11 +4,25 @@ pub mod attr;
mod ctxt;
pub use self::ctxt::Ctxt;
mod receiver;
pub use self::receiver::replace_receiver;
mod case;
mod check;
mod respan;
mod symbol;
use syn::Type;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
Deserialize,
}
pub fn ungroup(mut ty: &Type) -> &Type {
while let Type::Group(group) = ty {
ty = &group.elem;
}
ty
}
+285
View File
@@ -0,0 +1,285 @@
use internals::respan::respan;
use proc_macro2::Span;
use quote::ToTokens;
use std::mem;
use syn::punctuated::Punctuated;
use syn::{
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
Path, PathArguments, QSelf, ReturnType, Type, TypeParamBound, TypePath, WherePredicate,
};
pub fn replace_receiver(input: &mut DeriveInput) {
let self_ty = {
let ident = &input.ident;
let ty_generics = input.generics.split_for_impl().1;
parse_quote!(#ident #ty_generics)
};
let mut visitor = ReplaceReceiver(&self_ty);
visitor.visit_generics_mut(&mut input.generics);
visitor.visit_data_mut(&mut input.data);
}
struct ReplaceReceiver<'a>(&'a TypePath);
impl ReplaceReceiver<'_> {
fn self_ty(&self, span: Span) -> TypePath {
let tokens = self.0.to_token_stream();
let respanned = respan(tokens, span);
syn::parse2(respanned).unwrap()
}
fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
if path.leading_colon.is_some() || path.segments[0].ident != "Self" {
return;
}
if path.segments.len() == 1 {
self.self_to_expr_path(path);
return;
}
let span = path.segments[0].ident.span();
*qself = Some(QSelf {
lt_token: Token![<](span),
ty: Box::new(Type::Path(self.self_ty(span))),
position: 0,
as_token: None,
gt_token: Token![>](span),
});
path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
let segments = mem::replace(&mut path.segments, Punctuated::new());
path.segments = segments.into_pairs().skip(1).collect();
}
fn self_to_expr_path(&self, path: &mut Path) {
let self_ty = self.self_ty(path.segments[0].ident.span());
let variant = mem::replace(path, self_ty.path);
for segment in &mut path.segments {
if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
bracketed.colon2_token = Some(<Token![::]>::default());
}
}
}
if variant.segments.len() > 1 {
path.segments.push_punct(<Token![::]>::default());
path.segments.extend(variant.segments.into_pairs().skip(1));
}
}
}
impl ReplaceReceiver<'_> {
// `Self` -> `Receiver`
fn visit_type_mut(&mut self, ty: &mut Type) {
let span = if let Type::Path(node) = ty {
if node.qself.is_none() && node.path.is_ident("Self") {
node.path.segments[0].ident.span()
} else {
self.visit_type_path_mut(node);
return;
}
} else {
self.visit_type_mut_impl(ty);
return;
};
*ty = self.self_ty(span).into();
}
// `Self::Assoc` -> `<Receiver>::Assoc`
fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
if ty.qself.is_none() {
self.self_to_qself(&mut ty.qself, &mut ty.path);
}
self.visit_type_path_mut_impl(ty);
}
// `Self::method` -> `<Receiver>::method`
fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
if expr.qself.is_none() {
self.self_to_qself(&mut expr.qself, &mut expr.path);
}
self.visit_expr_path_mut_impl(expr);
}
// Everything below is simply traversing the syntax tree.
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
match ty {
Type::Array(ty) => {
self.visit_type_mut(&mut ty.elem);
self.visit_expr_mut(&mut ty.len);
}
Type::BareFn(ty) => {
for arg in &mut ty.inputs {
self.visit_type_mut(&mut arg.ty);
}
self.visit_return_type_mut(&mut ty.output);
}
Type::Group(ty) => self.visit_type_mut(&mut ty.elem),
Type::ImplTrait(ty) => {
for bound in &mut ty.bounds {
self.visit_type_param_bound_mut(bound);
}
}
Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac),
Type::Paren(ty) => self.visit_type_mut(&mut ty.elem),
Type::Path(ty) => {
if let Some(qself) = &mut ty.qself {
self.visit_type_mut(&mut qself.ty);
}
self.visit_path_mut(&mut ty.path);
}
Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem),
Type::Reference(ty) => self.visit_type_mut(&mut ty.elem),
Type::Slice(ty) => self.visit_type_mut(&mut ty.elem),
Type::TraitObject(ty) => {
for bound in &mut ty.bounds {
self.visit_type_param_bound_mut(bound);
}
}
Type::Tuple(ty) => {
for elem in &mut ty.elems {
self.visit_type_mut(elem);
}
}
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
_ => {}
}
}
fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) {
if let Some(qself) = &mut ty.qself {
self.visit_type_mut(&mut qself.ty);
}
self.visit_path_mut(&mut ty.path);
}
fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) {
if let Some(qself) = &mut expr.qself {
self.visit_type_mut(&mut qself.ty);
}
self.visit_path_mut(&mut expr.path);
}
fn visit_path_mut(&mut self, path: &mut Path) {
for segment in &mut path.segments {
self.visit_path_arguments_mut(&mut segment.arguments);
}
}
fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) {
match arguments {
PathArguments::None => {}
PathArguments::AngleBracketed(arguments) => {
for arg in &mut arguments.args {
match arg {
GenericArgument::Type(arg) => self.visit_type_mut(arg),
GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty),
GenericArgument::Lifetime(_)
| GenericArgument::Constraint(_)
| GenericArgument::Const(_) => {}
}
}
}
PathArguments::Parenthesized(arguments) => {
for argument in &mut arguments.inputs {
self.visit_type_mut(argument);
}
self.visit_return_type_mut(&mut arguments.output);
}
}
}
fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) {
match return_type {
ReturnType::Default => {}
ReturnType::Type(_, output) => self.visit_type_mut(output),
}
}
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
match bound {
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
TypeParamBound::Lifetime(_) => {}
}
}
fn visit_generics_mut(&mut self, generics: &mut Generics) {
for param in &mut generics.params {
match param {
GenericParam::Type(param) => {
for bound in &mut param.bounds {
self.visit_type_param_bound_mut(bound);
}
}
GenericParam::Lifetime(_) | GenericParam::Const(_) => {}
}
}
if let Some(where_clause) = &mut generics.where_clause {
for predicate in &mut where_clause.predicates {
match predicate {
WherePredicate::Type(predicate) => {
self.visit_type_mut(&mut predicate.bounded_ty);
for bound in &mut predicate.bounds {
self.visit_type_param_bound_mut(bound);
}
}
WherePredicate::Lifetime(_) | WherePredicate::Eq(_) => {}
}
}
}
}
fn visit_data_mut(&mut self, data: &mut Data) {
match data {
Data::Struct(data) => {
for field in &mut data.fields {
self.visit_type_mut(&mut field.ty);
}
}
Data::Enum(data) => {
for variant in &mut data.variants {
for field in &mut variant.fields {
self.visit_type_mut(&mut field.ty);
}
}
}
Data::Union(_) => {}
}
}
fn visit_expr_mut(&mut self, expr: &mut Expr) {
match expr {
Expr::Binary(expr) => {
self.visit_expr_mut(&mut expr.left);
self.visit_expr_mut(&mut expr.right);
}
Expr::Call(expr) => {
self.visit_expr_mut(&mut expr.func);
for arg in &mut expr.args {
self.visit_expr_mut(arg);
}
}
Expr::Cast(expr) => {
self.visit_expr_mut(&mut expr.expr);
self.visit_type_mut(&mut expr.ty);
}
Expr::Field(expr) => self.visit_expr_mut(&mut expr.base),
Expr::Index(expr) => {
self.visit_expr_mut(&mut expr.expr);
self.visit_expr_mut(&mut expr.index);
}
Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr),
Expr::Path(expr) => self.visit_expr_path_mut(expr),
Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr),
_ => {}
}
}
fn visit_macro_mut(&mut self, _mac: &mut Macro) {}
}
+16
View File
@@ -0,0 +1,16 @@
use proc_macro2::{Group, Span, TokenStream, TokenTree};
pub(crate) fn respan(stream: TokenStream, span: Span) -> TokenStream {
stream
.into_iter()
.map(|token| respan_token(token, span))
.collect()
}
fn respan_token(mut token: TokenTree, span: Span) -> TokenTree {
if let TokenTree::Group(g) = &mut token {
*g = Group::new(g.delimiter(), respan(g.stream(), span));
}
token.set_span(span);
token
}
+68
View File
@@ -0,0 +1,68 @@
use std::fmt::{self, Display};
use syn::{Ident, Path};
#[derive(Copy, Clone)]
pub struct Symbol(&'static str);
pub const ALIAS: Symbol = Symbol("alias");
pub const BORROW: Symbol = Symbol("borrow");
pub const BOUND: Symbol = Symbol("bound");
pub const CONTENT: Symbol = Symbol("content");
pub const CRATE: Symbol = Symbol("crate");
pub const DEFAULT: Symbol = Symbol("default");
pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields");
pub const DESERIALIZE: Symbol = Symbol("deserialize");
pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with");
pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier");
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 OTHER: Symbol = Symbol("other");
pub const REMOTE: Symbol = Symbol("remote");
pub const RENAME: Symbol = Symbol("rename");
pub const RENAME_ALL: Symbol = Symbol("rename_all");
pub const SERDE: Symbol = Symbol("serde");
pub const SERIALIZE: Symbol = Symbol("serialize");
pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with");
pub const SKIP: Symbol = Symbol("skip");
pub const SKIP_DESERIALIZING: Symbol = Symbol("skip_deserializing");
pub const SKIP_SERIALIZING: Symbol = Symbol("skip_serializing");
pub const SKIP_SERIALIZING_IF: Symbol = Symbol("skip_serializing_if");
pub const TAG: Symbol = Symbol("tag");
pub const TRANSPARENT: Symbol = Symbol("transparent");
pub const TRY_FROM: Symbol = Symbol("try_from");
pub const UNTAGGED: Symbol = Symbol("untagged");
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
pub const WITH: Symbol = Symbol("with");
pub const EXPECTING: Symbol = Symbol("expecting");
impl PartialEq<Symbol> for Ident {
fn eq(&self, word: &Symbol) -> bool {
self == word.0
}
}
impl<'a> PartialEq<Symbol> for &'a Ident {
fn eq(&self, word: &Symbol) -> bool {
*self == word.0
}
}
impl PartialEq<Symbol> for Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl<'a> PartialEq<Symbol> for &'a Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl Display for Symbol {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.0)
}
}
+49 -36
View File
@@ -13,42 +13,55 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.85")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.142")]
#![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
cyclomatic_complexity,
enum_variant_names,
needless_pass_by_value,
redundant_field_names,
too_many_arguments,
trivially_copy_pass_by_ref,
used_underscore_binding,
)
#![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
clippy::branches_sharing_code,
clippy::cognitive_complexity,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
clippy::collapsible_match,
clippy::derive_partial_eq_without_eq,
clippy::enum_variant_names,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
clippy::manual_map,
clippy::match_like_matches_macro,
clippy::needless_pass_by_value,
clippy::too_many_arguments,
clippy::trivially_copy_pass_by_ref,
clippy::used_underscore_binding,
clippy::wildcard_in_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
cast_possible_truncation,
doc_markdown,
enum_glob_use,
filter_map,
indexing_slicing,
items_after_statements,
match_same_arms,
module_name_repetitions,
similar_names,
single_match_else,
unseparated_literal_suffix,
use_self,
)
#![allow(
clippy::cast_possible_truncation,
clippy::checked_conversions,
clippy::doc_markdown,
clippy::enum_glob_use,
clippy::indexing_slicing,
clippy::items_after_statements,
clippy::let_underscore_drop,
clippy::manual_assert,
clippy::map_err_ignore,
clippy::match_same_arms,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
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,
clippy::too_many_lines,
clippy::unseparated_literal_suffix,
clippy::unused_self,
clippy::use_self,
clippy::wildcard_imports
)]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "512"]
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
#[macro_use]
extern crate quote;
@@ -76,16 +89,16 @@ mod try;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&input)
let mut input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&mut input)
.unwrap_or_else(to_compile_errors)
.into()
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&input)
let mut input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&mut input)
.unwrap_or_else(to_compile_errors)
.into()
}
+108 -47
View File
@@ -1,7 +1,7 @@
use proc_macro2::{Span, TokenStream};
use syn::Ident;
use proc_macro2::TokenStream;
use quote::format_ident;
use internals::ast::{Container, Data, Field, Style};
use internals::ast::{Container, Data, Field, Style, Variant};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
@@ -20,8 +20,8 @@ use internals::ast::{Container, Data, Field, Style};
// 8 | enum EnumDef { V }
// | ^
//
pub fn pretend_used(cont: &Container) -> TokenStream {
let pretend_fields = pretend_fields_used(cont);
pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
let pretend_fields = pretend_fields_used(cont, is_packed);
let pretend_variants = pretend_variants_used(cont);
quote! {
@@ -32,51 +32,119 @@ pub fn pretend_used(cont: &Container) -> TokenStream {
// For structs with named fields, expands to:
//
// match None::<&T> {
// Some(T { a: __v0, b: __v1 }) => {}
// _ => {}
// }
//
// For packed structs on sufficiently new rustc, expands to:
//
// match None::<&T> {
// Some(__v @ T { a: _, b: _ }) => {
// let _ = addr_of!(__v.a);
// let _ = addr_of!(__v.b);
// }
// _ => {}
// }
//
// For packed structs on older rustc, we assume Sized and !Drop, and expand to:
//
// match None::<T> {
// Some(T { a: ref __v0, b: ref __v1 }) => {}
// Some(T { a: __v0, b: __v1 }) => {}
// _ => {}
// }
//
// For enums, expands to the following but only including struct variants:
//
// match None::<T> {
// Some(T::A { a: ref __v0 }) => {}
// Some(T::B { b: ref __v0 }) => {}
// match None::<&T> {
// Some(T::A { a: __v0 }) => {}
// Some(T::B { b: __v0 }) => {}
// _ => {}
// }
//
// The `ref` is important in case the user has written a Drop impl on their
// type. Rust does not allow destructuring a struct or enum that has a Drop
// impl.
fn pretend_fields_used(cont: &Container) -> TokenStream {
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) => {
if is_packed {
pretend_fields_used_struct_packed(cont, fields)
} else {
pretend_fields_used_struct(cont, fields)
}
}
Data::Struct(_, _) => quote!(),
}
}
fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = &variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
Data::Struct(_, _) => {
return quote!();
}
};
let members = fields.iter().map(|field| &field.member);
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
quote! {
match _serde::export::None::<#type_ident #ty_generics> {
match _serde::__private::None::<&#type_ident #ty_generics> {
_serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
_ => {}
}
}
}
fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
#[cfg(not(no_ptr_addr_of))]
{
quote! {
match _serde::__private::None::<&#type_ident #ty_generics> {
_serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
#(
let _ = _serde::__private::ptr::addr_of!(__v.#members);
)*
}
_ => {}
}
}
}
#[cfg(no_ptr_addr_of)]
{
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
quote! {
match _serde::__private::None::<#type_ident #ty_generics> {
_serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
_ => {}
}
}
}
}
fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
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,
})
.collect::<Vec<_>>();
quote! {
match _serde::__private::None::<&#type_ident #ty_generics> {
#(
_serde::export::Some(#patterns) => {}
_serde::__private::Some(#patterns) => {}
)*
_ => {}
}
@@ -93,8 +161,8 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
// }
//
fn pretend_variants_used(cont: &Container) -> TokenStream {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
@@ -107,7 +175,7 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.map(|i| format_ident!("__v{}", i))
.collect::<Vec<_>>();
let pat = match variant.style {
@@ -120,8 +188,8 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
match _serde::__private::None {
_serde::__private::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
@@ -131,10 +199,3 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
quote!(#(#cases)*)
}
fn struct_pattern(fields: &[Field]) -> TokenStream {
let members = fields.iter().map(|field| &field.member);
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#members: ref #placeholders),* })
}
+132 -94
View File
@@ -6,31 +6,36 @@ use bound;
use dummy;
use fragment::{Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, Ctxt, Derive};
use internals::{attr, replace_receiver, Ctxt, Derive};
use pretend;
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
pub fn expand_derive_serialize(
input: &mut syn::DeriveInput,
) -> Result<TokenStream, Vec<syn::Error>> {
replace_receiver(input);
let ctxt = Ctxt::new();
let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) {
Some(cont) => cont,
None => return Err(ctxt.check().unwrap_err()),
};
precondition(&ctxt, &cont);
try!(ctxt.check());
ctxt.check()?;
let ident = &cont.ident;
let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let body = Stmts(serialize_body(&cont, &params));
let serde = cont.attrs.serde_path();
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
let used = pretend::pretend_used(&cont);
let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
__S: #serde::Serializer,
{
#used
#body
@@ -40,10 +45,10 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
} else {
quote! {
#[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
__S: #serde::Serializer,
{
#body
}
@@ -51,7 +56,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
}
};
Ok(dummy::wrap_in_const("SERIALIZE", ident, impl_block))
Ok(dummy::wrap_in_const(
cont.attrs.custom_serde_path(),
"SERIALIZE",
ident,
impl_block,
))
}
fn precondition(cx: &Ctxt, cont: &Container) {
@@ -81,6 +91,9 @@ struct Parameters {
/// Type has a `serde(remote = "...")` attribute.
is_remote: bool,
/// Type has a repr(packed) attribute.
is_packed: bool,
}
impl Parameters {
@@ -97,20 +110,23 @@ impl Parameters {
None => cont.ident.clone().into(),
};
let is_packed = cont.attrs.is_packed();
let generics = build_generics(cont);
Parameters {
self_var: self_var,
this: this,
generics: generics,
is_remote: is_remote,
self_var,
this,
generics,
is_remote,
is_packed,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.to_string()
self.this.segments.last().unwrap().ident.to_string()
}
}
@@ -158,15 +174,13 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
} else if let Some(type_into) = cont.attrs.type_into() {
serialize_into(params, type_into)
} else {
match cont.data {
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, ref fields) => {
serialize_struct(params, fields, &cont.attrs)
}
Data::Struct(Style::Tuple, ref fields) => {
match &cont.data {
Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs),
Data::Struct(Style::Tuple, fields) => {
serialize_tuple_struct(params, fields, &cont.attrs)
}
Data::Struct(Style::Newtype, ref fields) => {
Data::Struct(Style::Newtype, fields) => {
serialize_newtype_struct(params, &fields[0], &cont.attrs)
}
Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
@@ -175,8 +189,8 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
}
fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
let fields = match cont.data {
Data::Struct(_, ref fields) => fields,
let fields = match &cont.data {
Data::Struct(_, fields) => fields,
Data::Enum(_) => unreachable!(),
};
@@ -201,7 +215,7 @@ fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
let self_var = &params.self_var;
quote_block! {
_serde::Serialize::serialize(
&_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
&_serde::__private::Into::<#type_into>::into(_serde::__private::Clone::clone(#self_var)),
__serializer)
}
}
@@ -253,7 +267,7 @@ fn serialize_tuple_struct(
let mut serialized_fields = fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.filter(|(_, field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
@@ -289,37 +303,38 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
}
}
fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream {
match cattrs.tag() {
attr::TagType::Internal { tag } => {
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));
}
}
_ => quote! {},
}
}
fn serialize_struct_as_struct(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
let mut serialize_fields =
let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
let type_name = cattrs.name().serialize_name();
let additional_field_count: usize = match *cattrs.tag() {
attr::TagType::Internal { ref tag } => {
let func = StructTrait::SerializeStruct.serialize_field(Span::call_site());
serialize_fields.insert(
0,
quote! {
try!(#func(&mut __serde_state, #tag, #type_name));
},
);
1
}
_ => 0,
};
let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct);
let tag_field_exists = !tag_field.is_empty();
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some() || additional_field_count > 0);
let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
let len = serialized_fields
.map(|field| match field.attrs.skip_serializing_if() {
@@ -330,12 +345,13 @@ fn serialize_struct_as_struct(
}
})
.fold(
quote!(#additional_field_count),
quote!(#tag_field_exists as usize),
|sum, expr| quote!(#sum + #expr),
);
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
#tag_field
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
@@ -349,15 +365,18 @@ fn serialize_struct_as_map(
let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap);
let tag_field_exists = !tag_field.is_empty();
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
let len = if cattrs.has_flatten() {
quote!(_serde::export::None)
quote!(_serde::__private::None)
} else {
let len = serialized_fields
.map(|field| match field.attrs.skip_serializing_if() {
@@ -367,12 +386,16 @@ fn serialize_struct_as_map(
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote!(_serde::export::Some(#len))
.fold(
quote!(#tag_field_exists as usize),
|sum, expr| quote!(#sum + #expr),
);
quote!(_serde::__private::Some(#len))
};
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
#tag_field
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -414,7 +437,7 @@ fn serialize_variant(
variant_ident
);
let skipped_err = quote! {
_serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
_serde::__private::Err(_serde::ser::Error::custom(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
@@ -452,17 +475,16 @@ fn serialize_variant(
}
};
let body = Match(match *cattrs.tag() {
let body = Match(match cattrs.tag() {
attr::TagType::External => {
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
}
attr::TagType::Internal { ref tag } => {
attr::TagType::Internal { tag } => {
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
attr::TagType::Adjacent {
ref tag,
ref content,
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
attr::TagType::Adjacent { tag, content } => {
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
}
attr::TagType::None => serialize_untagged_variant(params, variant, cattrs),
});
@@ -494,7 +516,7 @@ fn serialize_externally_tagged_variant(
};
}
match variant.style {
match effective_style(variant) {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit_variant(
@@ -526,17 +548,17 @@ fn serialize_externally_tagged_variant(
}
Style::Tuple => serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
type_name,
variant_index,
variant_name,
},
params,
&variant.fields,
),
Style::Struct => serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
variant_index,
variant_name,
},
params,
&variant.fields,
@@ -560,7 +582,7 @@ fn serialize_internally_tagged_variant(
if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, variant);
return quote_expr! {
_serde::private::ser::serialize_tagged_newtype(
_serde::__private::ser::serialize_tagged_newtype(
__serializer,
#enum_ident_str,
#variant_ident_str,
@@ -571,7 +593,7 @@ fn serialize_internally_tagged_variant(
};
}
match variant.style {
match effective_style(variant) {
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
@@ -589,7 +611,7 @@ fn serialize_internally_tagged_variant(
}
let span = field.original.span();
let func = quote_spanned!(span=> _serde::private::ser::serialize_tagged_newtype);
let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype);
quote_expr! {
#func(
__serializer,
@@ -602,10 +624,7 @@ fn serialize_internally_tagged_variant(
}
}
Style::Struct => serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
StructVariant::InternallyTagged { tag, variant_name },
params,
&variant.fields,
&type_name,
@@ -631,7 +650,7 @@ fn serialize_adjacently_tagged_variant(
_serde::Serialize::serialize(#ser, __serializer)
}
} else {
match variant.style {
match effective_style(variant) {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
@@ -700,14 +719,16 @@ fn serialize_adjacently_tagged_variant(
quote_block! {
struct __AdjacentlyTagged #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
phantom: _serde::__private::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
// Elements that have skip_serializing will be unused.
#[allow(unused_variables)]
let (#(#fields_ident,)*) = self.data;
#inner
}
@@ -720,7 +741,7 @@ fn serialize_adjacently_tagged_variant(
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
}));
_serde::ser::SerializeStruct::end(__struct)
}
@@ -738,7 +759,7 @@ fn serialize_untagged_variant(
};
}
match variant.style {
match effective_style(variant) {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit(__serializer)
@@ -789,7 +810,7 @@ fn serialize_tuple_variant(
let mut serialized_fields = fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.filter(|(_, field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
@@ -856,9 +877,9 @@ fn serialize_struct_variant<'a>(
}
let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant,
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
(StructTrait::SerializeStruct)
StructTrait::SerializeStruct
}
};
@@ -961,18 +982,18 @@ fn serialize_struct_variant_with_flatten<'a>(
quote_block! {
struct __EnumFlatten #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
phantom: _serde::__private::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let (#(#members,)*) = self.data;
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
_serde::__private::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -985,7 +1006,7 @@ fn serialize_struct_variant_with_flatten<'a>(
#variant_name,
&__EnumFlatten {
data: (#(#members,)*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
})
}
}
@@ -993,7 +1014,7 @@ fn serialize_struct_variant_with_flatten<'a>(
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
_serde::__private::None));
try!(_serde::ser::SerializeMap::serialize_entry(
&mut __serde_state,
#tag,
@@ -1007,7 +1028,7 @@ fn serialize_struct_variant_with_flatten<'a>(
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
_serde::__private::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -1024,7 +1045,7 @@ fn serialize_tuple_struct_visitor(
fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.filter(|(_, field)| !field.attrs.skip_serializing())
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(&format!("__field{}", i), Span::call_site());
@@ -1078,7 +1099,7 @@ fn serialize_struct_visitor(
let mut field_expr = if is_enum {
quote!(#member)
} else {
get_member(params, field, &member)
get_member(params, field, member)
};
let key_expr = field.attrs.name().serialize_name();
@@ -1096,7 +1117,7 @@ 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)));
try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state)));
}
} else {
let func = struct_trait.serialize_field(span);
@@ -1148,9 +1169,9 @@ fn wrap_serialize_variant_with(
.fields
.iter()
.map(|field| {
let id = match field.member {
Member::Named(ref ident) => ident.clone(),
Member::Unnamed(ref member) => {
let id = match &field.member {
Member::Named(ident) => ident.clone(),
Member::Unnamed(member) => {
Ident::new(&format!("__field{}", member.index), Span::call_site())
}
};
@@ -1191,11 +1212,11 @@ fn wrap_serialize_with(
quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause {
values: (#(&'__a #field_tys, )*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
phantom: _serde::__private::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
@@ -1205,7 +1226,7 @@ fn wrap_serialize_with(
&__SerializeWith {
values: (#(#field_exprs, )*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
}
})
}
@@ -1227,15 +1248,25 @@ fn mut_if(is_mut: bool) -> Option<TokenStream> {
fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => quote!(&#self_var.#member),
(false, None) => {
if params.is_packed {
quote!(&{#self_var.#member})
} else {
quote!(&#self_var.#member)
}
}
(true, None) => {
let inner = quote!(&#self_var.#member);
let inner = if params.is_packed {
quote!(&{#self_var.#member})
} else {
quote!(&#self_var.#member)
};
let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(#inner))
quote!(_serde::__private::ser::constrain::<#ty>(#inner))
}
(true, Some(getter)) => {
let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(&#getter(#self_var)))
quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var)))
}
(false, Some(_)) => {
unreachable!("getter is only allowed for remote impls");
@@ -1243,6 +1274,13 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStrea
}
}
fn effective_style(variant: &Variant) -> Style {
match variant.style {
Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit,
other => other,
}
}
enum StructTrait {
SerializeMap,
SerializeStruct,
+3 -3
View File
@@ -13,9 +13,9 @@ pub fn replacement() -> TokenStream {
macro_rules! try {
(#dollar __expr:expr) => {
match #dollar __expr {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
+1
View File
@@ -0,0 +1 @@
msrv = "1.31.0"
+11 -11
View File
@@ -1,23 +1,23 @@
[package]
name = "serde_derive_internals"
version = "0.24.1" # remember to update html_root_url
version = "0.26.0" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.rs/serde_derive_internals"
homepage = "https://serde.rs"
include = ["lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"]
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/serde-rs/serde"
rust-version = "1.31"
[lib]
path = "lib.rs"
[dependencies]
proc-macro2 = "0.4"
quote = "0.6.3"
syn = { version = "0.15", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0.90", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+12
View File
@@ -0,0 +1,12 @@
use std::path::Path;
fn main() {
// 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
// repo.
let mod_behind_symlink = Path::new("src/mod.rs");
if !mod_behind_symlink.exists() {
println!("cargo:rustc-cfg=serde_build_from_git");
}
}
+39 -10
View File
@@ -1,12 +1,40 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.24.1")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(
feature = "cargo-clippy",
allow(
cyclomatic_complexity,
redundant_field_names,
trivially_copy_pass_by_ref
)
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.26.0")]
#![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints
#![allow(
clippy::cognitive_complexity,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
clippy::collapsible_match,
clippy::derive_partial_eq_without_eq,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
clippy::manual_map,
clippy::missing_panics_doc,
clippy::redundant_field_names,
clippy::result_unit_err,
clippy::should_implement_trait,
clippy::trivially_copy_pass_by_ref,
clippy::wildcard_in_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![allow(
clippy::doc_markdown,
clippy::enum_glob_use,
clippy::items_after_statements,
clippy::let_underscore_drop,
clippy::manual_assert,
clippy::match_same_arms,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
clippy::match_wildcard_for_single_variants,
clippy::missing_errors_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::similar_names,
clippy::struct_excessive_bools,
clippy::too_many_lines,
clippy::unused_self,
clippy::wildcard_imports
)]
#[macro_use]
@@ -15,7 +43,8 @@ extern crate syn;
extern crate proc_macro2;
extern crate quote;
#[path = "src/mod.rs"]
#[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
#[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
mod internals;
pub use internals::*;
+1
View File
@@ -0,0 +1 @@
msrv = "1.13.0"
+11 -9
View File
@@ -1,15 +1,18 @@
[package]
name = "serde_test"
version = "1.0.85" # remember to update html_root_url
version = "1.0.142" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
build = "build.rs"
categories = ["development-tools::testing"]
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"]
homepage = "https://serde.rs"
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
keywords = ["serde", "serialization", "testing"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
repository = "https://github.com/serde-rs/serde"
rust-version = "1.13"
[dependencies]
serde = { version = "1.0.60", path = "../serde" }
@@ -18,6 +21,5 @@ serde = { version = "1.0.60", path = "../serde" }
serde = { version = "1.0", path = "../serde" }
serde_derive = { version = "1.0", path = "../serde_derive" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+48
View File
@@ -0,0 +1,48 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
};
// #[track_caller] stabilized in Rust 1.46:
// https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller
if minor >= 46 {
println!("cargo:rustc-cfg=track_caller");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
u32::from_str(next).ok()
}
+7 -10
View File
@@ -12,7 +12,6 @@ use std::fmt::Debug;
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
@@ -28,8 +27,8 @@ use std::fmt::Debug;
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
#[cfg_attr(track_caller, track_caller)]
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Serialize + Deserialize<'de> + PartialEq + Debug,
@@ -44,7 +43,6 @@ where
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_ser_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
@@ -60,9 +58,9 @@ where
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
#[cfg_attr(track_caller, track_caller)]
pub fn assert_ser_tokens<T: ?Sized>(value: &T, tokens: &[Token])
where
T: Serialize,
{
@@ -114,7 +112,8 @@ where
/// assert_ser_tokens_error(&example, expected, error);
/// }
/// ```
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: &str)
#[cfg_attr(track_caller, track_caller)]
pub fn assert_ser_tokens_error<T: ?Sized>(value: &T, tokens: &[Token], error: &str)
where
T: Serialize,
{
@@ -135,7 +134,6 @@ where
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_de_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
@@ -151,8 +149,8 @@ where
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
#[cfg_attr(track_caller, track_caller)]
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Deserialize<'de> + PartialEq + Debug,
@@ -190,7 +188,6 @@ where
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_de_tokens_error, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// #[serde(deny_unknown_fields)]
/// struct S {
@@ -205,8 +202,8 @@ where
/// ],
/// "unknown field `x`, expected `a` or `b`",
/// );
/// # }
/// ```
#[cfg_attr(track_caller, track_caller)]
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
where
T: Deserialize<'de>,
+11
View File
@@ -777,6 +777,17 @@ macro_rules! impl_deserializer {
{
self.0.next_value_seed($wrapper(seed))
}
fn next_entry_seed<K, V>(
&mut self,
kseed: K,
vseed: V,
) -> Result<Option<(K::Value, V::Value)>, D::Error>
where
K: DeserializeSeed<'de>,
V: DeserializeSeed<'de>,
{
self.0.next_entry_seed($wrapper(kseed), $wrapper(vseed))
}
fn size_hint(&self) -> Option<usize> {
self.0.size_hint()
}
+37 -11
View File
@@ -89,11 +89,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
let value = visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
end: end,
},));
})?;
assert_next_token!(self, end);
Ok(value)
}
@@ -107,11 +107,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(visitor.visit_map(DeserializerMapVisitor {
let value = visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
end: end,
},));
})?;
assert_next_token!(self, end);
Ok(value)
}
@@ -168,14 +168,42 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
self.next_token();
visitor.visit_str(variant)
}
(Token::BorrowedStr(variant), Token::Unit) => {
self.next_token();
visitor.visit_borrowed_str(variant)
}
(Token::String(variant), Token::Unit) => {
self.next_token();
visitor.visit_string(variant.to_string())
}
(Token::Bytes(variant), Token::Unit) => {
self.next_token();
visitor.visit_bytes(variant)
}
(Token::BorrowedBytes(variant), Token::Unit) => {
self.next_token();
visitor.visit_borrowed_bytes(variant)
}
(Token::ByteBuf(variant), Token::Unit) => {
self.next_token();
visitor.visit_byte_buf(variant.to_vec())
}
(Token::U8(variant), Token::Unit) => {
self.next_token();
visitor.visit_u8(variant)
}
(Token::U16(variant), Token::Unit) => {
self.next_token();
visitor.visit_u16(variant)
}
(Token::U32(variant), Token::Unit) => {
self.next_token();
visitor.visit_u32(variant)
}
(Token::U64(variant), Token::Unit) => {
self.next_token();
visitor.visit_u64(variant)
}
(variant, Token::Unit) => unexpected!(variant),
(variant, _) => {
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
@@ -250,9 +278,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
{
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
_ => {
unexpected!(self.next_token());
}
_ => self.deserialize_any(visitor),
}
}
@@ -456,11 +482,11 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
| Token::TupleVariant { variant: v, .. }
| Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
let value = seed.deserialize(de)?;
Ok((value, self))
}
_ => {
let value = try!(seed.deserialize(&mut *self.de));
let value = seed.deserialize(&mut *self.de)?;
Ok((value, self))
}
}
@@ -613,7 +639,7 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
len: None,
end: Token::TupleVariantEnd,
};
try!(seed.deserialize(SeqAccessDeserializer::new(visitor)))
seed.deserialize(SeqAccessDeserializer::new(visitor))?
};
assert_next_token!(self.de, Token::TupleVariantEnd);
Ok(value)
@@ -625,7 +651,7 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
len: None,
end: Token::StructVariantEnd,
};
try!(seed.deserialize(MapAccessDeserializer::new(visitor)))
seed.deserialize(MapAccessDeserializer::new(visitor))?
};
assert_next_token!(self.de, Token::StructVariantEnd);
Ok(value)
+9 -3
View File
@@ -144,19 +144,25 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.85")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.142")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))]
// Ignored clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
cloned_instead_of_copied,
doc_link_with_quotes, // https://github.com/rust-lang/rust-clippy/issues/8961
empty_line_after_outer_attr,
manual_assert,
missing_docs_in_private_items,
missing_panics_doc,
module_name_repetitions,
must_use_candidate,
redundant_field_names,
too_many_lines,
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
use_debug,
use_self
)
+18 -18
View File
@@ -32,18 +32,18 @@ impl<'a> Serializer<'a> {
}
macro_rules! assert_next_token {
($ser:expr, $expected:ident) => {
assert_next_token!($ser, stringify!($expected), Token::$expected, true);
};
($ser:expr, $expected:ident($v:expr)) => {
($ser:expr, $actual:ident) => {{
assert_next_token!($ser, stringify!($actual), Token::$actual, true);
}};
($ser:expr, $actual:ident($v:expr)) => {{
assert_next_token!(
$ser,
format_args!(concat!(stringify!($expected), "({:?})"), $v),
Token::$expected(v),
format_args!(concat!(stringify!($actual), "({:?})"), $v),
Token::$actual(v),
v == $v
);
};
($ser:expr, $expected:ident { $($k:ident),* }) => {
}};
($ser:expr, $actual:ident { $($k:ident),* }) => {{
let compare = ($($k,)*);
let field_format = || {
use std::fmt::Write;
@@ -55,21 +55,21 @@ macro_rules! assert_next_token {
};
assert_next_token!(
$ser,
format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
Token::$expected { $($k),* },
format_args!(concat!(stringify!($actual), " {{ {}}}"), field_format()),
Token::$actual { $($k),* },
($($k,)*) == compare
);
};
($ser:expr, $expected:expr, $pat:pat, $guard:expr) => {
}};
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
match $ser.next_token() {
Some($pat) if $guard => {}
Some(other) => {
Some(expected) => {
panic!("expected Token::{} but serialized as {}",
$expected, other);
expected, $actual);
}
None => {
panic!("expected Token::{} after end of serialized tokens",
$expected);
panic!("expected end of tokens, but {} was serialized",
$actual);
}
}
};
@@ -427,7 +427,7 @@ impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
where
T: Serialize,
{
try!(key.serialize(&mut **self));
key.serialize(&mut **self)?;
value.serialize(&mut **self)
}
@@ -449,7 +449,7 @@ impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
where
T: Serialize,
{
try!(key.serialize(&mut *self.ser));
key.serialize(&mut *self.ser)?;
value.serialize(&mut *self.ser)
}
+12 -5
View File
@@ -2,19 +2,26 @@
name = "serde_test_suite"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
edition = "2018"
publish = false
[features]
expandtest = []
unstable = ["serde/unstable"]
compiletest = ["compiletest_rs"]
[dependencies]
serde = { path = "../serde" }
[build-dependencies]
toolchain_find = "0.2"
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "0.3.16"
macrotest = "=1.0.9"
prettyplease = "=0.1.14"
rustversion = "1.0"
serde = { path = "../serde", features = ["rc", "derive"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.3", optional = true, features = ["stable"] }
trybuild = { version = "1.0.49", features = ["diff"] }
+25
View File
@@ -0,0 +1,25 @@
use std::process::{Command, ExitStatus, Stdio};
fn has_cargo_expand() -> bool {
let cargo_expand = if cfg!(windows) {
"cargo-expand.exe"
} else {
"cargo-expand"
};
Command::new(cargo_expand)
.arg("--version")
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.as_ref()
.map(ExitStatus::success)
.unwrap_or(false)
}
fn main() {
if cfg!(feature = "expandtest") && has_cargo_expand() {
println!("cargo:rustc-cfg=expandtest");
}
}
-11
View File
@@ -1,11 +0,0 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
-3
View File
@@ -1,3 +0,0 @@
#![feature(/*=============================================]
#![=== Serde test suite requires a nightly compiler. ===]
#![====================================================*/)]
+1
View File
@@ -1,6 +1,7 @@
[package]
name = "serde_derive_tests_no_std"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
edition = "2018"
publish = false
+6 -17
View File
@@ -1,20 +1,9 @@
#![cfg(feature = "compiletest")]
use compiletest_rs as compiletest;
#[cfg_attr(target_os = "emscripten", ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[cfg_attr(miri, ignore)]
#[allow(unused_attributes)]
#[test]
fn ui() {
compiletest::run_tests(&compiletest::Config {
mode: compiletest::common::Mode::Ui,
src_base: std::path::PathBuf::from("tests/ui"),
target_rustcflags: Some(String::from(
"\
--edition=2018 \
-L deps/target/debug/deps \
-Z unstable-options \
--extern serde_derive \
",
)),
..Default::default()
});
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/**/*.rs");
}
File diff suppressed because it is too large Load Diff
+13
View File
@@ -0,0 +1,13 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
enum DeEnum<B, C, D> {
Unit,
Seq(i8, B, C, D),
Map { a: i8, b: B, c: C, d: D },
// Make sure we can support more than one variant.
_Unit2,
_Seq2(i8, B, C, D),
_Map2 { a: i8, b: B, c: C, d: D },
}
+448
View File
@@ -0,0 +1,448 @@
use serde::{Deserialize, Serialize};
trait AssociatedType {
type X;
}
impl AssociatedType for i32 {
type X = i32;
}
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
phantom: PhantomData<T>,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_struct(
__serializer,
"DefaultTyParam",
false as usize + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
"phantom",
&self.phantom,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de>
for DefaultTyParam<T> {
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"phantom" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"phantom" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, T: AssociatedType<X = i32>> {
marker: _serde::__private::PhantomData<DefaultTyParam<T>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T: AssociatedType<X = i32>> _serde::de::Visitor<'de>
for __Visitor<'de, T> {
type Value = DefaultTyParam<T>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct DefaultTyParam",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
PhantomData<T>,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct DefaultTyParam with 1 element",
),
);
}
};
_serde::__private::Ok(DefaultTyParam {
phantom: __field0,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<PhantomData<T>> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"phantom",
),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
PhantomData<T>,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("phantom") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(DefaultTyParam {
phantom: __field0,
})
}
}
const FIELDS: &'static [&'static str] = &["phantom"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DefaultTyParam",
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<DefaultTyParam<T>>,
lifetime: _serde::__private::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::__private::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"phantom" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"phantom" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'place, T: AssociatedType<X = i32> + 'place> {
place: &'place mut DefaultTyParam<T>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<
'de,
'place,
T: AssociatedType<X = i32> + 'place,
> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T> {
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct DefaultTyParam",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.phantom),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct DefaultTyParam with 1 element",
),
);
}
_serde::__private::Ok(())
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: bool = false;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if __field0 {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"phantom",
),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::__private::de::InPlaceSeed(&mut self.place.phantom),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
__field0 = true;
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
if !__field0 {
self
.place
.phantom = match _serde::__private::de::missing_field(
"phantom",
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
_serde::__private::Ok(())
}
}
const FIELDS: &'static [&'static str] = &["phantom"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DefaultTyParam",
FIELDS,
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
@@ -0,0 +1,14 @@
use serde::{Deserialize, Serialize};
trait AssociatedType {
type X;
}
impl AssociatedType for i32 {
type X = i32;
}
#[derive(Serialize, Deserialize)]
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
phantom: PhantomData<T>,
}
+621
View File
@@ -0,0 +1,621 @@
use serde::{Deserialize, Serialize};
pub enum GenericEnum<T, U> {
Unit,
NewType(T),
Seq(T, U),
Map { x: T, y: U },
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T, U> _serde::Serialize for GenericEnum<T, U>
where
T: _serde::Serialize,
U: _serde::Serialize,
{
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {
GenericEnum::Unit => {
_serde::Serializer::serialize_unit_variant(
__serializer,
"GenericEnum",
0u32,
"Unit",
)
}
GenericEnum::NewType(ref __field0) => {
_serde::Serializer::serialize_newtype_variant(
__serializer,
"GenericEnum",
1u32,
"NewType",
__field0,
)
}
GenericEnum::Seq(ref __field0, ref __field1) => {
let mut __serde_state = match _serde::Serializer::serialize_tuple_variant(
__serializer,
"GenericEnum",
2u32,
"Seq",
0 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field0,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
GenericEnum::Map { ref x, ref y } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"GenericEnum",
3u32,
"Map",
0 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"x",
x,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"y",
y,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum<T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"variant identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3),
_ => {
_serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 4",
),
)
}
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"Unit" => _serde::__private::Ok(__Field::__field0),
"NewType" => _serde::__private::Ok(__Field::__field1),
"Seq" => _serde::__private::Ok(__Field::__field2),
"Map" => _serde::__private::Ok(__Field::__field3),
_ => {
_serde::__private::Err(
_serde::de::Error::unknown_variant(__value, VARIANTS),
)
}
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"Unit" => _serde::__private::Ok(__Field::__field0),
b"NewType" => _serde::__private::Ok(__Field::__field1),
b"Seq" => _serde::__private::Ok(__Field::__field2),
b"Map" => _serde::__private::Ok(__Field::__field3),
_ => {
let __value = &_serde::__private::from_utf8_lossy(__value);
_serde::__private::Err(
_serde::de::Error::unknown_variant(__value, VARIANTS),
)
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<GenericEnum<T, U>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericEnum<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"enum GenericEnum",
)
}
fn visit_enum<__A>(
self,
__data: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<'de>,
{
match match _serde::de::EnumAccess::variant(__data) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
(__Field::__field0, __variant) => {
match _serde::de::VariantAccess::unit_variant(__variant) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::__private::Ok(GenericEnum::Unit)
}
(__Field::__field1, __variant) => {
_serde::__private::Result::map(
_serde::de::VariantAccess::newtype_variant::<T>(__variant),
GenericEnum::NewType,
)
}
(__Field::__field2, __variant) => {
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<GenericEnum<T, U>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de>
for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericEnum<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple variant GenericEnum::Seq",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple variant GenericEnum::Seq with 2 elements",
),
);
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
U,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"tuple variant GenericEnum::Seq with 2 elements",
),
);
}
};
_serde::__private::Ok(GenericEnum::Seq(__field0, __field1))
}
}
_serde::de::VariantAccess::tuple_variant(
__variant,
2usize,
__Visitor {
marker: _serde::__private::PhantomData::<GenericEnum<T, U>>,
lifetime: _serde::__private::PhantomData,
},
)
}
(__Field::__field3, __variant) => {
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"x" => _serde::__private::Ok(__Field::__field0),
"y" => _serde::__private::Ok(__Field::__field1),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"x" => _serde::__private::Ok(__Field::__field0),
b"y" => _serde::__private::Ok(__Field::__field1),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<GenericEnum<T, U>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de>
for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericEnum<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct variant GenericEnum::Map",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct variant GenericEnum::Map with 2 elements",
),
);
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
U,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"struct variant GenericEnum::Map with 2 elements",
),
);
}
};
_serde::__private::Ok(GenericEnum::Map {
x: __field0,
y: __field1,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<T> = _serde::__private::None;
let mut __field1: _serde::__private::Option<U> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<
__Field,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("x"),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<T>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field1 => {
if _serde::__private::Option::is_some(&__field1) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("y"),
);
}
__field1 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<U>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("x") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field1 = match __field1 {
_serde::__private::Some(__field1) => __field1,
_serde::__private::None => {
match _serde::__private::de::missing_field("y") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(GenericEnum::Map {
x: __field0,
y: __field1,
})
}
}
const FIELDS: &'static [&'static str] = &["x", "y"];
_serde::de::VariantAccess::struct_variant(
__variant,
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<GenericEnum<T, U>>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
}
}
const VARIANTS: &'static [&'static str] = &["Unit", "NewType", "Seq", "Map"];
_serde::Deserializer::deserialize_enum(
__deserializer,
"GenericEnum",
VARIANTS,
__Visitor {
marker: _serde::__private::PhantomData::<GenericEnum<T, U>>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
+9
View File
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub enum GenericEnum<T, U> {
Unit,
NewType(T),
Seq(T, U),
Map { x: T, y: U },
}
+640
View File
@@ -0,0 +1,640 @@
use serde::{Deserialize, Serialize};
pub struct GenericStruct<T> {
x: T,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T> _serde::Serialize for GenericStruct<T>
where
T: _serde::Serialize,
{
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_struct(
__serializer,
"GenericStruct",
false as usize + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
"x",
&self.x,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T> _serde::Deserialize<'de> for GenericStruct<T>
where
T: _serde::Deserialize<'de>,
{
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"x" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"x" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<GenericStruct<T>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
type Value = GenericStruct<T>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct GenericStruct",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct GenericStruct with 1 element",
),
);
}
};
_serde::__private::Ok(GenericStruct { x: __field0 })
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<T> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("x"),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<T>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("x") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(GenericStruct { x: __field0 })
}
}
const FIELDS: &'static [&'static str] = &["x"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"GenericStruct",
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<GenericStruct<T>>,
lifetime: _serde::__private::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::__private::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"x" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"x" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'place, T: 'place>
where
T: _serde::Deserialize<'de>,
{
place: &'place mut GenericStruct<T>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'place, T: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, T>
where
T: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct GenericStruct",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.x),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct GenericStruct with 1 element",
),
);
}
_serde::__private::Ok(())
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: bool = false;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if __field0 {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("x"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::__private::de::InPlaceSeed(&mut self.place.x),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
__field0 = true;
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
if !__field0 {
self
.place
.x = match _serde::__private::de::missing_field("x") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
_serde::__private::Ok(())
}
}
const FIELDS: &'static [&'static str] = &["x"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"GenericStruct",
FIELDS,
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
pub struct GenericNewTypeStruct<T>(T);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T> _serde::Serialize for GenericNewTypeStruct<T>
where
T: _serde::Serialize,
{
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
_serde::Serializer::serialize_newtype_struct(
__serializer,
"GenericNewTypeStruct",
&self.0,
)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct<T>
where
T: _serde::Deserialize<'de>,
{
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<GenericNewTypeStruct<T>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
type Value = GenericNewTypeStruct<T>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple struct GenericNewTypeStruct",
)
}
#[inline]
fn visit_newtype_struct<__E>(
self,
__e: __E,
) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<'de>,
{
let __field0: T = match <T as _serde::Deserialize>::deserialize(
__e,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::__private::Ok(GenericNewTypeStruct(__field0))
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericNewTypeStruct with 1 element",
),
);
}
};
_serde::__private::Ok(GenericNewTypeStruct(__field0))
}
}
_serde::Deserializer::deserialize_newtype_struct(
__deserializer,
"GenericNewTypeStruct",
__Visitor {
marker: _serde::__private::PhantomData::<GenericNewTypeStruct<T>>,
lifetime: _serde::__private::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::__private::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, 'place, T: 'place>
where
T: _serde::Deserialize<'de>,
{
place: &'place mut GenericNewTypeStruct<T>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'place, T: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, T>
where
T: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple struct GenericNewTypeStruct",
)
}
#[inline]
fn visit_newtype_struct<__E>(
self,
__e: __E,
) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<'de>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.0),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericNewTypeStruct with 1 element",
),
);
}
_serde::__private::Ok(())
}
}
_serde::Deserializer::deserialize_newtype_struct(
__deserializer,
"GenericNewTypeStruct",
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct GenericStruct<T> {
x: T,
}
#[derive(Serialize, Deserialize)]
pub struct GenericNewTypeStruct<T>(T);
+187
View File
@@ -0,0 +1,187 @@
use serde::{Deserialize, Serialize};
pub struct GenericTupleStruct<T, U>(T, U);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct<T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<GenericTupleStruct<T, U>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericTupleStruct<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple struct GenericTupleStruct",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericTupleStruct with 2 elements",
),
);
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
U,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"tuple struct GenericTupleStruct with 2 elements",
),
);
}
};
_serde::__private::Ok(GenericTupleStruct(__field0, __field1))
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"GenericTupleStruct",
2usize,
__Visitor {
marker: _serde::__private::PhantomData::<GenericTupleStruct<T, U>>,
lifetime: _serde::__private::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::__private::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, 'place, T: 'place, U: 'place>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
place: &'place mut GenericTupleStruct<T, U>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'place, T: 'place, U: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple struct GenericTupleStruct",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.0),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericTupleStruct with 2 elements",
),
);
}
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.1),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"tuple struct GenericTupleStruct with 2 elements",
),
);
}
_serde::__private::Ok(())
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"GenericTupleStruct",
2usize,
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
@@ -0,0 +1,4 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
pub struct GenericTupleStruct<T, U>(T, U);
+643
View File
@@ -0,0 +1,643 @@
use serde::{Deserialize, Serialize};
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a> _serde::Serialize for Lifetimes<'a> {
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {
Lifetimes::LifetimeSeq(ref __field0) => {
_serde::Serializer::serialize_newtype_variant(
__serializer,
"Lifetimes",
0u32,
"LifetimeSeq",
__field0,
)
}
Lifetimes::NoLifetimeSeq(ref __field0) => {
_serde::Serializer::serialize_newtype_variant(
__serializer,
"Lifetimes",
1u32,
"NoLifetimeSeq",
__field0,
)
}
Lifetimes::LifetimeMap { ref a } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"Lifetimes",
2u32,
"LifetimeMap",
0 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
Lifetimes::NoLifetimeMap { ref a } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"Lifetimes",
3u32,
"NoLifetimeMap",
0 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> {
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"variant identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3),
_ => {
_serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 4",
),
)
}
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"LifetimeSeq" => _serde::__private::Ok(__Field::__field0),
"NoLifetimeSeq" => _serde::__private::Ok(__Field::__field1),
"LifetimeMap" => _serde::__private::Ok(__Field::__field2),
"NoLifetimeMap" => _serde::__private::Ok(__Field::__field3),
_ => {
_serde::__private::Err(
_serde::de::Error::unknown_variant(__value, VARIANTS),
)
}
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"LifetimeSeq" => _serde::__private::Ok(__Field::__field0),
b"NoLifetimeSeq" => _serde::__private::Ok(__Field::__field1),
b"LifetimeMap" => _serde::__private::Ok(__Field::__field2),
b"NoLifetimeMap" => _serde::__private::Ok(__Field::__field3),
_ => {
let __value = &_serde::__private::from_utf8_lossy(__value);
_serde::__private::Err(
_serde::de::Error::unknown_variant(__value, VARIANTS),
)
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'a> {
marker: _serde::__private::PhantomData<Lifetimes<'a>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> {
type Value = Lifetimes<'a>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"enum Lifetimes",
)
}
fn visit_enum<__A>(
self,
__data: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<'de>,
{
match match _serde::de::EnumAccess::variant(__data) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
(__Field::__field0, __variant) => {
_serde::__private::Result::map(
_serde::de::VariantAccess::newtype_variant::<
&'a i32,
>(__variant),
Lifetimes::LifetimeSeq,
)
}
(__Field::__field1, __variant) => {
_serde::__private::Result::map(
_serde::de::VariantAccess::newtype_variant::<
i32,
>(__variant),
Lifetimes::NoLifetimeSeq,
)
}
(__Field::__field2, __variant) => {
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'a> {
marker: _serde::__private::PhantomData<Lifetimes<'a>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'a> _serde::de::Visitor<'de>
for __Visitor<'de, 'a> {
type Value = Lifetimes<'a>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct variant Lifetimes::LifetimeMap",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
&'a i32,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct variant Lifetimes::LifetimeMap with 1 element",
),
);
}
};
_serde::__private::Ok(Lifetimes::LifetimeMap {
a: __field0,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<&'a i32> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<
__Field,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("a"),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<
&'a i32,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("a") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(Lifetimes::LifetimeMap {
a: __field0,
})
}
}
const FIELDS: &'static [&'static str] = &["a"];
_serde::de::VariantAccess::struct_variant(
__variant,
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<Lifetimes<'a>>,
lifetime: _serde::__private::PhantomData,
},
)
}
(__Field::__field3, __variant) => {
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'a> {
marker: _serde::__private::PhantomData<Lifetimes<'a>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'a> _serde::de::Visitor<'de>
for __Visitor<'de, 'a> {
type Value = Lifetimes<'a>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct variant Lifetimes::NoLifetimeMap",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
i32,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct variant Lifetimes::NoLifetimeMap with 1 element",
),
);
}
};
_serde::__private::Ok(Lifetimes::NoLifetimeMap {
a: __field0,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<i32> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<
__Field,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("a"),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<i32>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("a") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(Lifetimes::NoLifetimeMap {
a: __field0,
})
}
}
const FIELDS: &'static [&'static str] = &["a"];
_serde::de::VariantAccess::struct_variant(
__variant,
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<Lifetimes<'a>>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
}
}
const VARIANTS: &'static [&'static str] = &[
"LifetimeSeq",
"NoLifetimeSeq",
"LifetimeMap",
"NoLifetimeMap",
];
_serde::Deserializer::deserialize_enum(
__deserializer,
"Lifetimes",
VARIANTS,
__Visitor {
marker: _serde::__private::PhantomData::<Lifetimes<'a>>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
+9
View File
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
+686
View File
@@ -0,0 +1,686 @@
use serde::{Deserialize, Serialize};
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
a: &'a A,
b: &'b mut B,
c: C,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C>
where
A: _serde::Serialize,
B: _serde::Serialize,
C: _serde::Serialize,
{
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_struct(
__serializer,
"SerNamedMap",
false as usize + 1 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
"a",
&self.a,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
"b",
&self.b,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
"c",
&self.c,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
struct DeNamedMap<A, B, C> {
a: A,
b: B,
c: C,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap<A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::__private::Ok(__Field::__field0),
"b" => _serde::__private::Ok(__Field::__field1),
"c" => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::__private::Ok(__Field::__field0),
b"b" => _serde::__private::Ok(__Field::__field1),
b"c" => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<DeNamedMap<A, B, C>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, A, B, C> _serde::de::Visitor<'de> for __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = DeNamedMap<A, B, C>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct DeNamedMap",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
A,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct DeNamedMap with 3 elements",
),
);
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
B,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"struct DeNamedMap with 3 elements",
),
);
}
};
let __field2 = match match _serde::de::SeqAccess::next_element::<
C,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
2usize,
&"struct DeNamedMap with 3 elements",
),
);
}
};
_serde::__private::Ok(DeNamedMap {
a: __field0,
b: __field1,
c: __field2,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::__private::Option<A> = _serde::__private::None;
let mut __field1: _serde::__private::Option<B> = _serde::__private::None;
let mut __field2: _serde::__private::Option<C> = _serde::__private::None;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("a"),
);
}
__field0 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<A>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field1 => {
if _serde::__private::Option::is_some(&__field1) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("b"),
);
}
__field1 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<B>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
__Field::__field2 => {
if _serde::__private::Option::is_some(&__field2) {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("c"),
);
}
__field2 = _serde::__private::Some(
match _serde::de::MapAccess::next_value::<C>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None => {
match _serde::__private::de::missing_field("a") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field1 = match __field1 {
_serde::__private::Some(__field1) => __field1,
_serde::__private::None => {
match _serde::__private::de::missing_field("b") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
let __field2 = match __field2 {
_serde::__private::Some(__field2) => __field2,
_serde::__private::None => {
match _serde::__private::de::missing_field("c") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
};
_serde::__private::Ok(DeNamedMap {
a: __field0,
b: __field1,
c: __field2,
})
}
}
const FIELDS: &'static [&'static str] = &["a", "b", "c"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DeNamedMap",
FIELDS,
__Visitor {
marker: _serde::__private::PhantomData::<DeNamedMap<A, B, C>>,
lifetime: _serde::__private::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::__private::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::__private::Ok(__Field::__field0),
"b" => _serde::__private::Ok(__Field::__field1),
"c" => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::__private::Ok(__Field::__field0),
b"b" => _serde::__private::Ok(__Field::__field1),
b"c" => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'place, A: 'place, B: 'place, C: 'place>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
place: &'place mut DeNamedMap<A, B, C>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'place, A: 'place, B: 'place, C: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"struct DeNamedMap",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.a),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"struct DeNamedMap with 3 elements",
),
);
}
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.b),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"struct DeNamedMap with 3 elements",
),
);
}
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.c),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
2usize,
&"struct DeNamedMap with 3 elements",
),
);
}
_serde::__private::Ok(())
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: bool = false;
let mut __field1: bool = false;
let mut __field2: bool = false;
while let _serde::__private::Some(__key)
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
match __key {
__Field::__field0 => {
if __field0 {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("a"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::__private::de::InPlaceSeed(&mut self.place.a),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
__field0 = true;
}
__Field::__field1 => {
if __field1 {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("b"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::__private::de::InPlaceSeed(&mut self.place.b),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
__field1 = true;
}
__Field::__field2 => {
if __field2 {
return _serde::__private::Err(
<__A::Error as _serde::de::Error>::duplicate_field("c"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::__private::de::InPlaceSeed(&mut self.place.c),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
__field2 = true;
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
}
}
if !__field0 {
self
.place
.a = match _serde::__private::de::missing_field("a") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
if !__field1 {
self
.place
.b = match _serde::__private::de::missing_field("b") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
if !__field2 {
self
.place
.c = match _serde::__private::de::missing_field("c") {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
}
_serde::__private::Ok(())
}
}
const FIELDS: &'static [&'static str] = &["a", "b", "c"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DeNamedMap",
FIELDS,
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
+15
View File
@@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
a: &'a A,
b: &'b mut B,
c: C,
}
#[derive(Deserialize)]
struct DeNamedMap<A, B, C> {
a: A,
b: B,
c: C,
}
+288
View File
@@ -0,0 +1,288 @@
use serde::{Deserialize, Serialize};
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C>
where
A: _serde::Serialize,
B: _serde::Serialize,
C: _serde::Serialize,
{
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_tuple_struct(
__serializer,
"SerNamedTuple",
0 + 1 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleStruct::serialize_field(
&mut __serde_state,
&self.0,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleStruct::serialize_field(
&mut __serde_state,
&self.1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleStruct::serialize_field(
&mut __serde_state,
&self.2,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
}
};
struct DeNamedTuple<A, B, C>(A, B, C);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple<A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
marker: _serde::__private::PhantomData<DeNamedTuple<A, B, C>>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, A, B, C> _serde::de::Visitor<'de> for __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = DeNamedTuple<A, B, C>;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple struct DeNamedTuple",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
A,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple struct DeNamedTuple with 3 elements",
),
);
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
B,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"tuple struct DeNamedTuple with 3 elements",
),
);
}
};
let __field2 = match match _serde::de::SeqAccess::next_element::<
C,
>(&mut __seq) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
2usize,
&"tuple struct DeNamedTuple with 3 elements",
),
);
}
};
_serde::__private::Ok(DeNamedTuple(__field0, __field1, __field2))
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"DeNamedTuple",
3usize,
__Visitor {
marker: _serde::__private::PhantomData::<DeNamedTuple<A, B, C>>,
lifetime: _serde::__private::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::__private::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, 'place, A: 'place, B: 'place, C: 'place>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
place: &'place mut DeNamedTuple<A, B, C>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de, 'place, A: 'place, B: 'place, C: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"tuple struct DeNamedTuple",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.0),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
0usize,
&"tuple struct DeNamedTuple with 3 elements",
),
);
}
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.1),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
1usize,
&"tuple struct DeNamedTuple with 3 elements",
),
);
}
if let _serde::__private::None
= match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.2),
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
} {
return _serde::__private::Err(
_serde::de::Error::invalid_length(
2usize,
&"tuple struct DeNamedTuple with 3 elements",
),
);
}
_serde::__private::Ok(())
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"DeNamedTuple",
3usize,
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
+7
View File
@@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
#[derive(Deserialize)]
struct DeNamedTuple<A, B, C>(A, B, C);
+61
View File
@@ -0,0 +1,61 @@
use serde::{Deserialize, Serialize};
struct NamedUnit;
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl _serde::Serialize for NamedUnit {
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
_serde::Serializer::serialize_unit_struct(__serializer, "NamedUnit")
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for NamedUnit {
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor;
impl<'de> _serde::de::Visitor<'de> for __Visitor {
type Value = NamedUnit;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"unit struct NamedUnit",
)
}
#[inline]
fn visit_unit<__E>(self) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::__private::Ok(NamedUnit)
}
}
_serde::Deserializer::deserialize_unit_struct(
__deserializer,
"NamedUnit",
__Visitor,
)
}
}
};
+4
View File
@@ -0,0 +1,4 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct NamedUnit;
+270
View File
@@ -0,0 +1,270 @@
use serde::Serialize;
enum SerEnum<'a, B: 'a, C: 'a, D>
where
D: 'a,
{
Unit,
Seq(i8, B, &'a C, &'a mut D),
Map { a: i8, b: B, c: &'a C, d: &'a mut D },
_Unit2,
_Seq2(i8, B, &'a C, &'a mut D),
_Map2 { a: i8, b: B, c: &'a C, d: &'a mut D },
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D>
where
D: 'a,
B: _serde::Serialize,
C: _serde::Serialize,
D: _serde::Serialize,
{
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {
SerEnum::Unit => {
_serde::Serializer::serialize_unit_variant(
__serializer,
"SerEnum",
0u32,
"Unit",
)
}
SerEnum::Seq(ref __field0, ref __field1, ref __field2, ref __field3) => {
let mut __serde_state = match _serde::Serializer::serialize_tuple_variant(
__serializer,
"SerEnum",
1u32,
"Seq",
0 + 1 + 1 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field0,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field2,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field3,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
SerEnum::Map { ref a, ref b, ref c, ref d } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"SerEnum",
2u32,
"Map",
0 + 1 + 1 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"b",
b,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"c",
c,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"d",
d,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
SerEnum::_Unit2 => {
_serde::Serializer::serialize_unit_variant(
__serializer,
"SerEnum",
3u32,
"_Unit2",
)
}
SerEnum::_Seq2(
ref __field0,
ref __field1,
ref __field2,
ref __field3,
) => {
let mut __serde_state = match _serde::Serializer::serialize_tuple_variant(
__serializer,
"SerEnum",
4u32,
"_Seq2",
0 + 1 + 1 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field0,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field2,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field3,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
SerEnum::_Map2 { ref a, ref b, ref c, ref d } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"SerEnum",
5u32,
"_Map2",
0 + 1 + 1 + 1 + 1,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"b",
b,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"c",
c,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"d",
d,
) {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
}
}
};
+16
View File
@@ -0,0 +1,16 @@
use serde::Serialize;
#[derive(Serialize)]
enum SerEnum<'a, B: 'a, C: 'a, D>
where
D: 'a,
{
Unit,
Seq(i8, B, &'a C, &'a mut D),
Map { a: i8, b: B, c: &'a C, d: &'a mut D },
// Make sure we can support more than one variant.
_Unit2,
_Seq2(i8, B, &'a C, &'a mut D),
_Map2 { a: i8, b: B, c: &'a C, d: &'a mut D },
}
+149
View File
@@ -0,0 +1,149 @@
use serde::{Deserialize, Serialize};
enum Void {}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl _serde::Serialize for Void {
fn serialize<__S>(
&self,
__serializer: __S,
) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {}
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for Void {
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(
__formatter,
"variant identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
_ => {
_serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 0",
),
)
}
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
_ => {
_serde::__private::Err(
_serde::de::Error::unknown_variant(__value, VARIANTS),
)
}
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
_ => {
let __value = &_serde::__private::from_utf8_lossy(__value);
_serde::__private::Err(
_serde::de::Error::unknown_variant(__value, VARIANTS),
)
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de> {
marker: _serde::__private::PhantomData<Void>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = Void;
fn expecting(
&self,
__formatter: &mut _serde::__private::Formatter,
) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, "enum Void")
}
fn visit_enum<__A>(
self,
__data: __A,
) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<'de>,
{
_serde::__private::Result::map(
_serde::de::EnumAccess::variant::<__Field>(__data),
|(__impossible, _)| match __impossible {},
)
}
}
const VARIANTS: &'static [&'static str] = &[];
_serde::Deserializer::deserialize_enum(
__deserializer,
"Void",
VARIANTS,
__Visitor {
marker: _serde::__private::PhantomData::<Void>,
lifetime: _serde::__private::PhantomData,
},
)
}
}
};
+4
View File
@@ -0,0 +1,4 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
enum Void {}
+9
View File
@@ -0,0 +1,9 @@
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(not(expandtest), ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[cfg_attr(miri, ignore)]
#[allow(unused_attributes)]
#[test]
fn expandtest() {
macrotest::expand("tests/expand/*.rs");
}
+52 -66
View File
@@ -1,93 +1,79 @@
#![allow(unused_macro_rules)]
use serde_test::Token;
use std::iter;
macro_rules! btreeset {
() => {
BTreeSet::new()
};
($($value:expr),+) => {
{
let mut set = BTreeSet::new();
$(set.insert($value);)+
set
}
}
($($value:expr),+) => {{
let mut set = BTreeSet::new();
$(set.insert($value);)+
set
}};
}
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
($($key:expr => $value:expr),+) => {{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}};
}
macro_rules! hashset {
() => {
HashSet::new()
};
($($value:expr),+) => {
{
let mut set = HashSet::new();
$(set.insert($value);)+
set
}
};
($hasher:ident @ $($value:expr),+) => {
{
use std::hash::BuildHasherDefault;
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
$(set.insert($value);)+
set
}
}
($($value:expr),+) => {{
let mut set = HashSet::new();
$(set.insert($value);)+
set
}};
($hasher:ident @ $($value:expr),+) => {{
use std::hash::BuildHasherDefault;
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
$(set.insert($value);)+
set
}};
}
macro_rules! hashmap {
() => {
HashMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = HashMap::new();
$(map.insert($key, $value);)+
map
}
};
($hasher:ident @ $($key:expr => $value:expr),+) => {
{
use std::hash::BuildHasherDefault;
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
$(map.insert($key, $value);)+
map
}
($($key:expr => $value:expr),+) => {{
let mut map = HashMap::new();
$(map.insert($key, $value);)+
map
}};
($hasher:ident @ $($key:expr => $value:expr),+) => {{
use std::hash::BuildHasherDefault;
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
$(map.insert($key, $value);)+
map
}};
}
pub trait SingleTokenIntoIterator {
fn into_iter(self) -> iter::Once<Token>;
}
impl SingleTokenIntoIterator for Token {
fn into_iter(self) -> iter::Once<Token> {
iter::once(self)
}
}
macro_rules! seq_impl {
(seq $first:expr,) => {
seq_impl!(seq $first)
};
($first:expr,) => {
seq_impl!($first)
};
(seq $first:expr) => {
$first.into_iter()
};
($first:expr) => {
Some($first).into_iter()
};
(seq $first:expr , $( $elem: tt)*) => {
$first.into_iter().chain(seq!( $($elem)* ))
};
($first:expr , $($elem: tt)*) => {
Some($first).into_iter().chain(seq!( $($elem)* ))
}
}
macro_rules! seq {
($($tt: tt)*) => {
seq_impl!($($tt)*).collect::<Vec<_>>()
};
($($elem:expr),* $(,)?) => {{
use crate::macros::SingleTokenIntoIterator;
let mut vec = Vec::new();
$(<Vec<Token> as Extend<Token>>::extend(&mut vec, $elem.into_iter());)*
vec
}};
}
+247 -27
View File
@@ -1,9 +1,19 @@
#![allow(clippy::cast_lossless, clippy::trivially_copy_pass_by_ref)]
#![allow(
clippy::cast_lossless,
clippy::derive_partial_eq_without_eq,
clippy::from_over_into,
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
clippy::nonstandard_macro_braces,
clippy::too_many_lines,
clippy::trivially_copy_pass_by_ref,
clippy::type_repetition_in_bounds
)]
use serde::de::{self, MapAccess, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fmt;
use std::marker::PhantomData;
@@ -574,7 +584,11 @@ fn test_rename_struct() {
);
assert_de_tokens(
&AliasStruct { a1: 1, a2: 2, a4: 3 },
&AliasStruct {
a1: 1,
a2: 2,
a4: 3,
},
&[
Token::Struct {
name: "AliasStruct",
@@ -591,7 +605,11 @@ fn test_rename_struct() {
);
assert_de_tokens(
&AliasStruct { a1: 1, a2: 2, a4: 3 },
&AliasStruct {
a1: 1,
a2: 2,
a4: 3,
},
&[
Token::Struct {
name: "AliasStruct",
@@ -665,7 +683,7 @@ enum AliasEnum {
b: i8,
#[serde(alias = "e", rename = "f")]
d: i8,
}
},
}
#[test]
@@ -756,11 +774,7 @@ fn test_rename_enum() {
);
assert_de_tokens(
&AliasEnum::SailorMoon {
a: 0,
b: 1,
d: 2,
},
&AliasEnum::SailorMoon { a: 0, b: 1, d: 2 },
&[
Token::StructVariant {
name: "AliasEnum",
@@ -778,11 +792,7 @@ fn test_rename_enum() {
);
assert_de_tokens(
&AliasEnum::SailorMoon {
a: 0,
b: 1,
d: 2,
},
&AliasEnum::SailorMoon { a: 0, b: 1, d: 2 },
&[
Token::StructVariant {
name: "AliasEnum",
@@ -803,13 +813,11 @@ fn test_rename_enum() {
#[test]
fn test_unknown_field_rename_enum() {
assert_de_tokens_error::<AliasEnum>(
&[
Token::StructVariant {
name: "AliasEnum",
variant: "SailorMoon",
len: 3,
},
],
&[Token::StructVariant {
name: "AliasEnum",
variant: "SailorMoon",
len: 3,
}],
"unknown variant `SailorMoon`, expected `sailor_moon`",
);
@@ -1590,14 +1598,35 @@ impl From<Option<u32>> for EnumToU32 {
}
}
#[derive(Clone, Deserialize, PartialEq, Debug)]
#[serde(try_from = "u32")]
enum TryFromU32 {
One,
Two,
}
impl TryFrom<u32> for TryFromU32 {
type Error = String;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
1 => Ok(TryFromU32::One),
2 => Ok(TryFromU32::Two),
_ => Err("out of range".to_owned()),
}
}
}
#[test]
fn test_from_into_traits() {
assert_ser_tokens::<EnumToU32>(&EnumToU32::One, &[Token::Some, Token::U32(1)]);
assert_ser_tokens::<EnumToU32>(&EnumToU32::Nothing, &[Token::None]);
assert_de_tokens::<EnumToU32>(&EnumToU32::Two, &[Token::Some, Token::U32(2)]);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(Some(5)), &[Token::None]);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(None), &[Token::None]);
assert_de_tokens::<StructFromEnum>(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]);
assert_ser_tokens(&EnumToU32::One, &[Token::Some, Token::U32(1)]);
assert_ser_tokens(&EnumToU32::Nothing, &[Token::None]);
assert_de_tokens(&EnumToU32::Two, &[Token::Some, Token::U32(2)]);
assert_ser_tokens(&StructFromEnum(Some(5)), &[Token::None]);
assert_ser_tokens(&StructFromEnum(None), &[Token::None]);
assert_de_tokens(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]);
assert_de_tokens(&TryFromU32::Two, &[Token::U32(2)]);
assert_de_tokens_error::<TryFromU32>(&[Token::U32(5)], "out of range");
}
#[test]
@@ -1947,6 +1976,29 @@ fn test_flatten_map_twice() {
);
}
#[test]
fn test_flatten_unit() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Response<T> {
#[serde(flatten)]
data: T,
status: usize,
}
assert_tokens(
&Response {
data: (),
status: 0,
},
&[
Token::Map { len: None },
Token::Str("status"),
Token::U64(0),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_unsupported_type() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -2590,3 +2642,171 @@ fn test_flatten_any_after_flatten_struct() {
],
);
}
#[test]
fn test_expecting_message() {
#[derive(Deserialize, PartialEq, Debug)]
#[serde(expecting = "something strange...")]
struct Unit;
#[derive(Deserialize)]
#[serde(expecting = "something strange...")]
struct Newtype(bool);
#[derive(Deserialize)]
#[serde(expecting = "something strange...")]
struct Tuple(u32, bool);
#[derive(Deserialize)]
#[serde(expecting = "something strange...")]
struct Struct {
question: String,
answer: u32,
}
assert_de_tokens_error::<Unit>(
&[Token::Str("Unit")],
r#"invalid type: string "Unit", expected something strange..."#,
);
assert_de_tokens_error::<Newtype>(
&[Token::Str("Newtype")],
r#"invalid type: string "Newtype", expected something strange..."#,
);
assert_de_tokens_error::<Tuple>(
&[Token::Str("Tuple")],
r#"invalid type: string "Tuple", expected something strange..."#,
);
assert_de_tokens_error::<Struct>(
&[Token::Str("Struct")],
r#"invalid type: string "Struct", expected something strange..."#,
);
}
#[test]
fn test_expecting_message_externally_tagged_enum() {
#[derive(Deserialize)]
#[serde(expecting = "something strange...")]
enum Enum {
ExternallyTagged,
}
assert_de_tokens_error::<Enum>(
&[Token::Str("ExternallyTagged")],
r#"invalid type: string "ExternallyTagged", expected something strange..."#,
);
// 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"#,
);
}
#[test]
fn test_expecting_message_internally_tagged_enum() {
#[derive(Deserialize)]
#[serde(tag = "tag")]
#[serde(expecting = "something strange...")]
enum Enum {
InternallyTagged,
}
assert_de_tokens_error::<Enum>(
&[Token::Str("InternallyTagged")],
r#"invalid type: string "InternallyTagged", expected something strange..."#,
);
// 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"#,
);
}
#[test]
fn test_expecting_message_adjacently_tagged_enum() {
#[derive(Deserialize)]
#[serde(tag = "tag", content = "content")]
#[serde(expecting = "something strange...")]
enum Enum {
AdjacentlyTagged,
}
assert_de_tokens_error::<Enum>(
&[Token::Str("AdjacentlyTagged")],
r#"invalid type: string "AdjacentlyTagged", expected something strange..."#,
);
assert_de_tokens_error::<Enum>(
&[Token::Map { len: None }, Token::Unit],
r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#,
);
// 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"#,
);
}
#[test]
fn test_expecting_message_untagged_tagged_enum() {
#[derive(Deserialize)]
#[serde(untagged)]
#[serde(expecting = "something strange...")]
enum Enum {
Untagged,
}
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
}
#[test]
fn test_expecting_message_identifier_enum() {
#[derive(Deserialize)]
#[serde(field_identifier)]
#[serde(expecting = "something strange...")]
enum FieldEnum {
Field,
}
#[derive(Deserialize)]
#[serde(variant_identifier)]
#[serde(expecting = "something strange...")]
enum VariantEnum {
Variant,
}
assert_de_tokens_error::<FieldEnum>(
&[Token::Unit],
r#"invalid type: unit value, expected something strange..."#,
);
assert_de_tokens_error::<FieldEnum>(
&[
Token::Enum { name: "FieldEnum" },
Token::Str("Unknown"),
Token::None,
],
r#"invalid type: map, expected something strange..."#,
);
assert_de_tokens_error::<VariantEnum>(
&[Token::Unit],
r#"invalid type: unit value, expected something strange..."#,
);
assert_de_tokens_error::<VariantEnum>(
&[
Token::Enum {
name: "VariantEnum",
},
Token::Str("Unknown"),
Token::None,
],
r#"invalid type: map, expected something strange..."#,
);
}
+30
View File
@@ -1,3 +1,9 @@
#![allow(
clippy::derive_partial_eq_without_eq,
clippy::items_after_statements,
clippy::used_underscore_binding
)]
use serde::{Deserialize, Deserializer};
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
@@ -90,6 +96,30 @@ fn test_struct() {
);
}
#[test]
fn test_field_identifier() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier)]
enum FieldStr<'a> {
#[serde(borrow)]
Str(&'a str),
}
assert_de_tokens(&FieldStr::Str("value"), &[Token::BorrowedStr("value")]);
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier)]
enum FieldBytes<'a> {
#[serde(borrow)]
Bytes(&'a [u8]),
}
assert_de_tokens(
&FieldBytes::Bytes(b"value"),
&[Token::BorrowedBytes(b"value")],
);
}
#[test]
fn test_cow() {
#[derive(Deserialize)]
+1881 -925
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

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