Compare commits

...

177 Commits

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2923:21
         |
    2923 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2923 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-07-30 16:15:29 -07:00
David Tolnay 02c34e490b Resolve redundant_field_names clippy lint from PR 2448
warning: redundant field names in struct initialization
        --> serde/src/private/ser.rs:1278:13
         |
    1278 |             map: map,
         |             ^^^^^^^^ help: replace it with: `map`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
         = note: `-W clippy::redundant-field-names` implied by `-W clippy::all`
2023-07-30 16:07:27 -07:00
David Tolnay 427c839b3d Merge pull request #2448 from Mingun/ser-flatten-enums
Implement serialization of tuple variants of flatten enums
2023-07-30 16:02:37 -07:00
David Tolnay 48aa054f53 Release 1.0.178 2023-07-28 16:09:39 -07:00
David Tolnay 3616860203 Delete broken symlink from precompiled derive sources 2023-07-28 16:09:22 -07:00
David Tolnay 861b0dfea2 Consistently list StdError under 'Re-exports' heading of rustdoc 2023-07-28 16:06:49 -07:00
David Tolnay 8b3d71ae2d Merge pull request #2541 from dtolnay/de-core-error
Fix `serde::de::StdError` in no-std unstable build
2023-07-28 16:05:14 -07:00
David Tolnay ff5442cd9e Add no-std unstable build in CI 2023-07-28 16:00:07 -07:00
David Tolnay 92d686f9a5 Fix serde::de::StdError in no-std unstable build 2023-07-28 15:58:57 -07:00
David Tolnay 7b09cccd77 Merge pull request #2539 from dtolnay/questionmark
Replace `try!` with `?` in serde_derive
2023-07-27 19:20:15 -07:00
David Tolnay 6f1f38d046 Replace 'try!' with '?' in serde_derive 2023-07-27 19:16:11 -07:00
David Tolnay db8f06467b Eliminate workaround for pre-1.17 rustc in serde_derive
The oldest compiler supported by serde_derive by this point is 1.56.
2023-07-27 19:05:57 -07:00
David Tolnay 91ec1c290f Enforce question mark not used in serde crate yet
Question mark regresses compile time by 6.5–7.5%.
2023-07-27 19:02:11 -07:00
David Tolnay 0676673ca5 Release 1.0.177 2023-07-27 10:51:22 -07:00
David Tolnay 7a4335d664 Merge pull request #2536 from jplatte/jplatte/error-span
Update error span for attribute / data kind mismatches
2023-07-27 10:50:26 -07:00
Jonas Platte 31a0e73489 Update error span for attribute / data kind mismatches 2023-07-27 10:47:45 +02:00
David Tolnay 74fe70855f Ignore return_self_not_must_use pedantic clippy lint
warning: missing `#[must_use]` attribute on a method returning `Self`
       --> serde_derive_internals/src/attr.rs:204:5
        |
    204 | /     pub fn or(self, other_rules: Self) -> Self {
    205 | |         Self {
    206 | |             serialize: self.serialize.or(other_rules.serialize),
    207 | |             deserialize: self.deserialize.or(other_rules.deserialize),
    208 | |         }
    209 | |     }
        | |_____^
        |
        = help: consider adding the `#[must_use]` attribute to the method or directly to the `Self` type
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use
        = note: `-W clippy::return-self-not-must-use` implied by `-W clippy::pedantic`

    warning: missing `#[must_use]` attribute on a method returning `Self`
       --> serde_derive_internals/src/case.rs:112:5
        |
    112 | /     pub fn or(self, rule_b: Self) -> Self {
    113 | |         match self {
    114 | |             None => rule_b,
    115 | |             _ => self,
    116 | |         }
    117 | |     }
        | |_____^
        |
        = help: consider adding the `#[must_use]` attribute to the method or directly to the `Self` type
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use
2023-07-27 00:51:57 -07:00
David Tolnay e74925bc43 Merge pull request #1695 from jplatte/rename_all_fields
Add #[serde(rename_all_fields = "foo")] attribute
2023-07-27 00:45:45 -07:00
Jonas Platte 56be1c203e Pass RenameRule, RenameAllRules by value 2023-07-27 09:19:42 +02:00
Jonas Platte 2f9bf4d3eb Add #[serde(rename_all_fields = "foo")] attribute 2023-07-27 09:19:42 +02:00
David Tolnay ad94aed753 Merge pull request #2535 from dtolnay/baretrait
Restore bare_trait_objects lint within serde_derive code
2023-07-26 14:26:02 -07:00
David Tolnay 30db83fc44 Restore bare_trait_objects lint within serde_derive code 2023-07-26 14:18:25 -07:00
David Tolnay b0f7b00e1f Resolve manual_string_new pedantic clippy lint
warning: empty String is being created manually
        --> test_suite/tests/test_annotations.rs:2280:29
         |
    2280 |     let data = Data::C { t: "".to_string() };
         |                             ^^^^^^^^^^^^^^ help: consider using: `String::new()`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new
         = note: `-W clippy::manual-string-new` implied by `-W clippy::pedantic`
2023-07-26 13:46:28 -07:00
David Tolnay 7255e192d8 Delete unused statement from PR 2266 test 2023-07-26 13:45:49 -07:00
David Tolnay 2102e1aa42 Format PR 2266 tests with rustfmt 2023-07-26 13:41:56 -07:00
David Tolnay 85d5c1fd38 Release 1.0.176 2023-07-26 13:37:44 -07:00
David Tolnay b789286bc3 Merge pull request #2266 from flisky/master
fix: don't check skipped variant with internal tag
2023-07-26 13:36:33 -07:00
David Tolnay a6a8a334f7 Add CI on macOS for the non-precompiled codepath 2023-07-26 01:03:20 -07:00
David Tolnay 78a11a27b6 Skip an extra trip through filesystem on the critical path 2023-07-26 00:58:34 -07:00
David Tolnay d2d7bad04a Improve error message on missing serde_derive exe 2023-07-26 00:52:09 -07:00
David Tolnay b978854258 Eliminate parse_macro_input conflict in precompiled mode 2023-07-26 00:44:55 -07:00
David Tolnay 0fb672a1ef Eliminate #[macro_use] from serde_derive 2023-07-25 23:23:24 -07:00
David Tolnay dd9913675d Ungroup imports 2023-07-25 23:06:34 -07:00
David Tolnay 11677ad926 Merge pull request #2533 from dtolnay/test
Move serde_test out to serde-rs/test
2023-07-25 22:52:36 -07:00
David Tolnay 25a53f10db Move serde_test out to serde-rs/test 2023-07-25 22:48:39 -07:00
David Tolnay 26e2ef001c Delete deprecated AsciiExt extension trait import
This has been superseded by inherent methods since Rust 1.26.
2023-07-25 21:07:33 -07:00
David Tolnay 30f79b3b2e Eliminate 2015-style module system imports from serde_derive 2023-07-25 20:56:19 -07:00
David Tolnay 89f84c2915 Merge pull request #2532 from dtolnay/macrouse
Delete unused serde_derive #[macro_use]
2023-07-25 18:55:14 -07:00
David Tolnay 6882285be0 Move extern crate proc_macro into each possible lib.rs
This makes it slightly more convenient to use the following as a
Reindeer fixup for those that prefer to build from source:

    extra_mapped_srcs = { "src/lib_from_source.rs" = "src/lib.rs" }

    [platform_fixups.'cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))']
    extra_deps = [":proc-macro2", ":quote", ":syn"]

as opposed to checking in a whole new file containing the `extern crate
proc_macro` + `include!("lib_from_source.rs")`.
2023-07-25 18:54:41 -07:00
David Tolnay 3260bc5896 Delete unused serde_derive #[macro_use]
In old versions of rustc (1.15 through 1.29) it would cause a warning if
this #[macro_use] was not present.

    warning: proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
       --> serde/src/lib.rs:340:1
        |
    340 | extern crate serde_derive;
        | ^^^^^^^^^^^^^^^^^^^^^^^^^^

These days serde_derive requires a newer compiler than that, so the
bogus warning would never occur.
2023-07-25 18:47:52 -07:00
Mingun f709fc05b0 Do not run the code when results are not used 2023-07-23 15:23:39 +05:00
Mingun 089aae1292 Eliminate even more allocations 2023-07-23 15:23:39 +05:00
Mingun 855acaf112 Eliminate additional allocations for flattening aliases 2023-07-23 15:23:38 +05:00
Mingun 7ca7720262 Slightly reduced number of allocations 2023-07-23 15:23:37 +05:00
Mingun 78fea3aa4a Show possible aliases in the expected message
Fixes tests
2023-07-23 15:23:37 +05:00
Mingun 1efb8b6a53 Add tests for aliases
failures (2):
    field_identifier::unknown
    variant_identifier::unknown
2023-07-23 15:23:36 +05:00
Mingun bc1960b106 Add tests for unknown field / variant 2023-07-23 15:23:33 +05:00
Mingun 967023b755 Group field_identifier and variant_identifier tests in sub-modules
(review this commit with "ignore whitespace changes" option on)
2023-07-23 15:21:22 +05:00
Mingun bb51e68f16 Keep aliases sorted 2023-07-23 15:21:21 +05:00
Mingun 4e5e55bf1c Remove custom implementations of SeqDeserializer and MapDeserializer for enums
Those deserializers are used to deserialize tuple or struct variants from Content
which is used by internally tagged enums and by flatten

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

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

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

now can be serialized to JSON as

  { "enum_field": [1, 2] }

Deserialization already works

Fixes (1):
    flatten::enum_::externally_tagged::tuple
2023-07-11 22:00:10 +05:00
Mingun 993966600e Implement tests for crate::private::de::content::VariantDeserializer
failures (1):
    flatten::enum_::externally_tagged::tuple
2023-07-11 21:59:22 +05:00
Mingun 5b96cf1bde Use traditional order for enum variants (Unit, Newtype, Tuple, Struct) and names for tag and content fields 2023-07-11 21:58:43 +05:00
Mingun f3d50e5209 Use FromIterator to fill HashMap 2023-07-11 21:58:14 +05:00
Mingun ab21d4d017 Merge assert_de_tokens and assert_ser_tokens into assert_tokens 2023-07-11 21:57:49 +05:00
Mingun f7c5d93e6a Pull up types from function into module, unify style 2023-07-11 21:57:22 +05:00
Mingun 52a7d40e6e Rename test types so their names reflects, what's tested 2023-07-11 21:56:53 +05:00
Mingun 348bc6b257 Move flatten enum tests to a dedicated module
(review with "ignore whitespace" option on and editor that shows line moves,
for example, TortoiseGitMerge)
2023-07-11 21:56:22 +05:00
Yin Jifeng 983347484e fix: don't check skipped variant with internal tag 2022-08-23 20:19:34 +08:00
118 changed files with 2196 additions and 6659 deletions
+27 -34
View File
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable
@@ -27,7 +27,7 @@ jobs:
runs-on: windows-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
@@ -40,14 +40,12 @@ jobs:
rust: [stable, beta]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- 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)' || ''}}
@@ -58,12 +56,13 @@ jobs:
os: [ubuntu, windows]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cd serde && cargo build
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build --no-default-features --features alloc
- run: cd serde && cargo build --no-default-features --features rc,alloc
- run: cd serde && cargo build --no-default-features --features unstable
- run: cd serde && cargo test --features derive,rc,unstable
- run: cd test_suite/no_std && cargo build
if: matrix.os != 'windows'
@@ -78,42 +77,23 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
rust: [1.31.0, 1.34.0]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build
- run: cd serde_test && cargo build
more:
name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [1.27.0, 1.28.0]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
# Work around failing to parse manifest because editions are unstable.
- run: sed -i /test_suite/d Cargo.toml
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build
derive:
name: Rust 1.56.0
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.56.0
- run: cd serde && cargo check --no-default-features
- run: cd serde && cargo check
@@ -124,7 +104,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.36.0
- run: cd serde && cargo build --no-default-features --features alloc
@@ -133,23 +113,36 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cargo generate-lockfile -Z minimal-versions
- run: cargo check --locked --workspace
doc:
name: Documentation
runs-on: ubuntu-latest
timeout-minutes: 45
env:
RUSTDOCFLAGS: -Dwarnings
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/install@cargo-docs-rs
- run: cargo docs-rs -p serde
- run: cargo docs-rs -p serde_derive
- run: cargo docs-rs -p serde_derive_internals
clippy:
name: Clippy
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@clippy
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- 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
@@ -158,7 +151,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@miri
- run: cargo miri setup
- run: cd serde && cargo miri test --features derive,rc,unstable
@@ -174,6 +167,6 @@ jobs:
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: dtolnay/install@cargo-outdated
- run: cargo outdated --workspace --exit-code 1
+3 -1
View File
@@ -3,6 +3,8 @@ members = [
"serde",
"serde_derive",
"serde_derive_internals",
"serde_test",
"test_suite",
]
[patch.crates-io]
serde = { path = "serde" }
+3 -3
View File
@@ -1,12 +1,12 @@
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.19+]][Rust 1.19] [![serde_derive: rustc 1.56+]][Rust 1.56]
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.31+]][Rust 1.31] [![serde_derive: rustc 1.56+]][Rust 1.56]
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
[serde: rustc 1.19+]: https://img.shields.io/badge/serde-rustc_1.19+-lightgray.svg
[serde: rustc 1.31+]: https://img.shields.io/badge/serde-rustc_1.31+-lightgray.svg
[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg
[Rust 1.19]: https://blog.rust-lang.org/2017/07/20/Rust-1.19.html
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
-1
View File
@@ -1 +0,0 @@
/serde_derive/serde_derive-x86_64-unknown-linux-gnu
-14
View File
@@ -1,14 +0,0 @@
[workspace]
members = ["bin", "proc-macro2"]
resolver = "2"
[patch.crates-io]
proc-macro2 = { path = "proc-macro2" }
[profile.precompiled]
inherits = "release"
codegen-units = 1
lto = true
opt-level = "z"
panic = "abort"
strip = true
-17
View File
@@ -1,17 +0,0 @@
[package]
name = "serde_derive"
version = "1.0.175"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[lib]
doctest = false
[[bin]]
name = "serde_derive"
path = "main.rs"
[dependencies]
proc-macro2 = "1"
quote = { version = "1", default-features = false }
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "full", "parsing", "printing"] }
-4
View File
@@ -1,4 +0,0 @@
fn main() {
println!("cargo:rustc-cfg=precompiled");
println!("cargo:rustc-cfg=feature=\"deserialize_in_place\"");
}
-45
View File
@@ -1,45 +0,0 @@
extern crate proc_macro2;
use proc_macro2::watt;
use proc_macro2::watt::buffer::InputBuffer;
use std::alloc::{GlobalAlloc, Layout, System};
use std::io::{self, Read, Write};
use std::sync::atomic::Ordering;
struct MonotonicAllocator;
#[global_allocator]
static ALLOCATOR: MonotonicAllocator = MonotonicAllocator;
unsafe impl GlobalAlloc for MonotonicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
System.alloc(layout)
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
// Leak: this cuts 3% of code size from the precompiled macro binary.
// There is no way that serde_derive would fill up all memory on the
// host. When the subprocess exits, operating system will clean this up.
}
}
fn main() {
let mut buf = Vec::new();
io::stdin().read_to_end(&mut buf).unwrap();
let mut buf = InputBuffer::new(&buf);
let derive = match buf.read_u8() {
0 => serde_derive::derive_serialize,
1 => serde_derive::derive_deserialize,
2 => {
serde_derive::DESERIALIZE_IN_PLACE.store(true, Ordering::Relaxed);
serde_derive::derive_deserialize
}
_ => unreachable!(),
};
let input = watt::load(&mut buf);
let output = derive(input);
let bytes = watt::linearize(output);
io::stdout().write_all(&bytes).unwrap();
}
-1
View File
@@ -1 +0,0 @@
../../serde_derive/src
-21
View File
@@ -1,21 +0,0 @@
#!/bin/bash
cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null
set -e -x
# TODO: Sanitize host filesystem paths. https://github.com/rust-lang/cargo/issues/12137
cargo +nightly build \
--manifest-path bin/Cargo.toml \
--bin serde_derive \
--profile precompiled \
-Z unstable-options \
-Z build-std=std,panic_abort \
-Z build-std-features=panic_immediate_abort \
--target x86_64-unknown-linux-musl \
--out-dir serde_derive
rm -f serde_derive/serde_derive-x86_64-unknown-linux-gnu
mv serde_derive/serde_derive{,-x86_64-unknown-linux-gnu}
#upx --best --lzma serde_derive/serde_derive-x86_64-unknown-linux-gnu
-8
View File
@@ -1,8 +0,0 @@
[package]
name = "proc-macro2"
version = "1.0.66"
edition = "2021"
publish = false
[dependencies]
proc-macro2 = { package = "proc-macro2-fallback", version = "1" }
-815
View File
@@ -1,815 +0,0 @@
#[doc(hidden)]
pub mod watt;
use crate::extra::DelimSpan;
use crate::watt::Identity;
use std::cmp::Ordering;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::ops::RangeBounds;
use std::str::FromStr;
pub use proc_macro2::{Delimiter, Spacing};
#[derive(Copy, Clone)]
pub struct Span {
lo: u32,
hi: u32,
}
impl Span {
pub fn call_site() -> Self {
Span { lo: 0, hi: 0 }
}
pub fn join(&self, other: Self) -> Option<Self> {
Some(Span {
lo: self.lo,
hi: other.hi,
})
}
}
#[derive(Clone)]
pub enum TokenTree {
Group(Group),
Ident(Ident),
Punct(Punct),
Literal(Literal),
}
impl TokenTree {
pub fn span(&self) -> Span {
match self {
TokenTree::Group(group) => group.span(),
TokenTree::Ident(ident) => ident.span(),
TokenTree::Punct(punct) => punct.span(),
TokenTree::Literal(literal) => literal.span(),
}
}
pub fn set_span(&mut self, span: Span) {
match self {
TokenTree::Group(group) => group.set_span(span),
TokenTree::Ident(ident) => ident.set_span(span),
TokenTree::Punct(punct) => punct.set_span(span),
TokenTree::Literal(literal) => literal.set_span(span),
}
}
}
impl From<Group> for TokenTree {
fn from(group: Group) -> Self {
TokenTree::Group(group)
}
}
impl From<Ident> for TokenTree {
fn from(ident: Ident) -> Self {
TokenTree::Ident(ident)
}
}
impl From<Punct> for TokenTree {
fn from(punct: Punct) -> Self {
TokenTree::Punct(punct)
}
}
impl From<Literal> for TokenTree {
fn from(literal: Literal) -> Self {
TokenTree::Literal(literal)
}
}
impl Debug for TokenTree {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
TokenTree::Group(group) => Debug::fmt(group, formatter),
TokenTree::Ident(ident) => {
let mut debug = formatter.debug_struct("Ident");
debug.field("sym", &format_args!("{}", ident));
debug.finish()
}
TokenTree::Punct(punct) => Debug::fmt(punct, formatter),
TokenTree::Literal(literal) => Debug::fmt(literal, formatter),
}
}
}
#[derive(Clone)]
pub struct Group {
delimiter: Delimiter,
stream: Vec<TokenTree>,
span: Span,
span_open: Span,
span_close: Span,
identity: u32,
}
impl Group {
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
Group {
delimiter,
stream: stream.content,
span: Span::call_site(),
span_open: Span::call_site(),
span_close: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn stream(&self) -> TokenStream {
TokenStream {
content: self.stream.clone(),
}
}
pub fn delimiter(&self) -> Delimiter {
self.delimiter
}
pub fn span(&self) -> Span {
self.span
}
pub fn span_open(&self) -> Span {
self.span_open
}
pub fn span_close(&self) -> Span {
self.span_close
}
pub fn delim_span(&self) -> DelimSpan {
DelimSpan {
join: self.span,
open: self.span_open,
close: self.span_close,
}
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
}
impl Display for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let (open, close) = match self.delimiter {
Delimiter::Parenthesis => ("(", ")"),
Delimiter::Brace => ("{ ", "}"),
Delimiter::Bracket => ("[", "]"),
Delimiter::None => ("", ""),
};
formatter.write_str(open)?;
display_tokens(&self.stream, formatter)?;
if self.delimiter == Delimiter::Brace && !self.stream.is_empty() {
formatter.write_str(" ")?;
}
formatter.write_str(close)?;
Ok(())
}
}
impl Debug for Group {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let mut debug = formatter.debug_struct("Group");
debug.field("delimiter", &self.delimiter);
debug.field("stream", &self.stream);
debug.finish()
}
}
#[derive(Clone)]
pub struct Ident {
fallback: proc_macro2::Ident,
span: Span,
identity: u32,
}
impl Ident {
pub fn new(string: &str, span: Span) -> Self {
Ident {
fallback: proc_macro2::Ident::new(string, proc_macro2::Span::call_site()),
span,
identity: Identity::NOVEL,
}
}
pub fn new_raw(string: &str, span: Span) -> Self {
Ident {
fallback: proc_macro2::Ident::new_raw(string, proc_macro2::Span::call_site()),
span,
identity: Identity::NOVEL,
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
}
impl Display for Ident {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.fallback, formatter)
}
}
impl Debug for Ident {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
impl Eq for Ident {}
impl PartialEq for Ident {
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.fallback, &other.fallback)
}
}
impl<T> PartialEq<T> for Ident
where
T: ?Sized + AsRef<str>,
{
fn eq(&self, other: &T) -> bool {
PartialEq::eq(&self.fallback, other)
}
}
impl Ord for Ident {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.fallback, &other.fallback)
}
}
impl PartialOrd for Ident {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.fallback, &other.fallback)
}
}
impl Hash for Ident {
fn hash<H: Hasher>(&self, hasher: &mut H) {
Hash::hash(&self.fallback, hasher);
}
}
#[derive(Clone)]
pub struct Punct {
fallback: proc_macro2::Punct,
span: Span,
identity: u32,
}
impl Punct {
pub fn new(ch: char, spacing: Spacing) -> Self {
Punct {
fallback: proc_macro2::Punct::new(ch, spacing),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn as_char(&self) -> char {
self.fallback.as_char()
}
pub fn spacing(&self) -> Spacing {
self.fallback.spacing()
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
}
impl Display for Punct {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.fallback, formatter)
}
}
impl Debug for Punct {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
#[derive(Clone)]
pub struct Literal {
fallback: proc_macro2::Literal,
span: Span,
identity: u32,
}
impl Literal {
pub fn u8_suffixed(n: u8) -> Self {
Literal {
fallback: proc_macro2::Literal::u8_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u16_suffixed(n: u16) -> Self {
Literal {
fallback: proc_macro2::Literal::u16_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u32_suffixed(n: u32) -> Self {
Literal {
fallback: proc_macro2::Literal::u32_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u64_suffixed(n: u64) -> Self {
Literal {
fallback: proc_macro2::Literal::u64_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u128_suffixed(n: u128) -> Self {
Literal {
fallback: proc_macro2::Literal::u128_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn usize_suffixed(n: usize) -> Self {
Literal {
fallback: proc_macro2::Literal::usize_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i8_suffixed(n: i8) -> Self {
Literal {
fallback: proc_macro2::Literal::i8_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i16_suffixed(n: i16) -> Self {
Literal {
fallback: proc_macro2::Literal::i16_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i32_suffixed(n: i32) -> Self {
Literal {
fallback: proc_macro2::Literal::i32_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i64_suffixed(n: i64) -> Self {
Literal {
fallback: proc_macro2::Literal::i64_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i128_suffixed(n: i128) -> Self {
Literal {
fallback: proc_macro2::Literal::i128_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn isize_suffixed(n: isize) -> Self {
Literal {
fallback: proc_macro2::Literal::isize_suffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u8_unsuffixed(n: u8) -> Self {
Literal {
fallback: proc_macro2::Literal::u8_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u16_unsuffixed(n: u16) -> Self {
Literal {
fallback: proc_macro2::Literal::u16_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u32_unsuffixed(n: u32) -> Self {
Literal {
fallback: proc_macro2::Literal::u32_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u64_unsuffixed(n: u64) -> Self {
Literal {
fallback: proc_macro2::Literal::u64_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn u128_unsuffixed(n: u128) -> Self {
Literal {
fallback: proc_macro2::Literal::u128_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn usize_unsuffixed(n: usize) -> Self {
Literal {
fallback: proc_macro2::Literal::usize_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i8_unsuffixed(n: i8) -> Self {
Literal {
fallback: proc_macro2::Literal::i8_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i16_unsuffixed(n: i16) -> Self {
Literal {
fallback: proc_macro2::Literal::i16_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i32_unsuffixed(n: i32) -> Self {
Literal {
fallback: proc_macro2::Literal::i32_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i64_unsuffixed(n: i64) -> Self {
Literal {
fallback: proc_macro2::Literal::i64_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn i128_unsuffixed(n: i128) -> Self {
Literal {
fallback: proc_macro2::Literal::i128_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn isize_unsuffixed(n: isize) -> Self {
Literal {
fallback: proc_macro2::Literal::isize_unsuffixed(n),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f64_unsuffixed(f: f64) -> Self {
Literal {
fallback: proc_macro2::Literal::f64_unsuffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f64_suffixed(f: f64) -> Self {
Literal {
fallback: proc_macro2::Literal::f64_suffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f32_unsuffixed(f: f32) -> Self {
Literal {
fallback: proc_macro2::Literal::f32_unsuffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn f32_suffixed(f: f32) -> Self {
Literal {
fallback: proc_macro2::Literal::f32_suffixed(f),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn string(string: &str) -> Self {
Literal {
fallback: proc_macro2::Literal::string(string),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn character(ch: char) -> Self {
Literal {
fallback: proc_macro2::Literal::character(ch),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn byte_string(s: &[u8]) -> Self {
Literal {
fallback: proc_macro2::Literal::byte_string(s),
span: Span::call_site(),
identity: Identity::NOVEL,
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn set_span(&mut self, span: Span) {
self.span = span;
self.identity |= Identity::RESPANNED;
}
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
let _ = range;
None
}
}
impl FromStr for Literal {
type Err = LexError;
fn from_str(repr: &str) -> Result<Self, Self::Err> {
let fallback = match proc_macro2::Literal::from_str(repr) {
Ok(literal) => literal,
Err(error) => {
return Err(LexError {
fallback: error,
span: Span::call_site(),
});
}
};
Ok(Literal {
fallback,
span: Span::call_site(),
identity: Identity::NOVEL,
})
}
}
impl Display for Literal {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.fallback, formatter)
}
}
impl Debug for Literal {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
#[derive(Clone)]
pub struct TokenStream {
content: Vec<TokenTree>,
}
impl TokenStream {
pub fn new() -> Self {
TokenStream {
content: Vec::new(),
}
}
pub fn is_empty(&self) -> bool {
self.content.is_empty()
}
}
impl IntoIterator for TokenStream {
type Item = TokenTree;
type IntoIter = token_stream::IntoIter;
fn into_iter(self) -> Self::IntoIter {
token_stream::IntoIter {
iter: self.content.into_iter(),
}
}
}
impl Extend<TokenStream> for TokenStream {
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
self.content.extend(streams.into_iter().flatten());
}
}
impl Extend<TokenTree> for TokenStream {
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
self.content.extend(streams);
}
}
impl FromIterator<TokenStream> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
let content = streams.into_iter().flatten().collect();
TokenStream { content }
}
}
impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
let content = streams.into_iter().collect();
TokenStream { content }
}
}
impl FromStr for TokenStream {
type Err = LexError;
fn from_str(string: &str) -> Result<Self, Self::Err> {
let fallback = match proc_macro2::TokenStream::from_str(string) {
Ok(token_stream) => token_stream,
Err(error) => {
return Err(LexError {
fallback: error,
span: Span::call_site(),
});
}
};
fn convert_token_stream(stream: proc_macro2::TokenStream) -> TokenStream {
TokenStream {
content: stream.into_iter().map(convert_token_tree).collect(),
}
}
fn convert_token_tree(token: proc_macro2::TokenTree) -> TokenTree {
match token {
proc_macro2::TokenTree::Group(group) => TokenTree::Group(Group::new(
group.delimiter(),
convert_token_stream(group.stream()),
)),
proc_macro2::TokenTree::Ident(ident) => TokenTree::Ident(Ident {
fallback: ident,
span: Span::call_site(),
identity: Identity::NOVEL,
}),
proc_macro2::TokenTree::Punct(punct) => TokenTree::Punct(Punct {
fallback: punct,
span: Span::call_site(),
identity: Identity::NOVEL,
}),
proc_macro2::TokenTree::Literal(literal) => TokenTree::Literal(Literal {
fallback: literal,
span: Span::call_site(),
identity: Identity::NOVEL,
}),
}
}
Ok(convert_token_stream(fallback))
}
}
fn display_tokens(tokens: &[TokenTree], formatter: &mut fmt::Formatter) -> fmt::Result {
let mut joint = false;
for (i, token) in tokens.iter().enumerate() {
if i != 0 && !joint {
write!(formatter, " ")?;
}
joint = false;
match token {
TokenTree::Group(group) => Display::fmt(group, formatter),
TokenTree::Ident(ident) => Display::fmt(ident, formatter),
TokenTree::Punct(punct) => {
joint = punct.spacing() == Spacing::Joint;
Display::fmt(punct, formatter)
}
TokenTree::Literal(literal) => Display::fmt(literal, formatter),
}?;
}
Ok(())
}
impl Display for TokenStream {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
display_tokens(&self.content, formatter)
}
}
impl Debug for TokenStream {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("TokenStream ")?;
formatter.debug_list().entries(&self.content).finish()
}
}
pub struct LexError {
fallback: proc_macro2::LexError,
span: Span,
}
impl LexError {
pub fn span(&self) -> Span {
self.span
}
}
impl Debug for LexError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.fallback, formatter)
}
}
pub mod token_stream {
use super::*;
#[derive(Clone)]
pub struct IntoIter {
pub(crate) iter: <Vec<TokenTree> as IntoIterator>::IntoIter,
}
impl Iterator for IntoIter {
type Item = TokenTree;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
}
pub mod extra {
use crate::Span;
#[derive(Copy, Clone)]
pub struct DelimSpan {
pub(crate) join: Span,
pub(crate) open: Span,
pub(crate) close: Span,
}
impl DelimSpan {
pub fn join(&self) -> Span {
self.join
}
pub fn open(&self) -> Span {
self.open
}
pub fn close(&self) -> Span {
self.close
}
}
}
@@ -1,69 +0,0 @@
use std::str;
pub struct OutputBuffer {
bytes: Vec<u8>,
}
impl OutputBuffer {
pub fn new() -> Self {
OutputBuffer { bytes: Vec::new() }
}
pub fn write_u8(&mut self, value: u8) {
self.bytes.push(value);
}
pub fn write_u16(&mut self, value: u16) {
self.bytes.extend_from_slice(&value.to_le_bytes());
}
pub fn write_u32(&mut self, value: u32) {
self.bytes.extend_from_slice(&value.to_le_bytes());
}
pub fn write_str(&mut self, value: &str) {
self.bytes.extend_from_slice(value.as_bytes());
}
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
}
pub struct InputBuffer<'a> {
bytes: &'a [u8],
}
impl<'a> InputBuffer<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
InputBuffer { bytes }
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
pub fn read_u8(&mut self) -> u8 {
let (first, rest) = self.bytes.split_first().unwrap();
self.bytes = rest;
*first
}
pub fn read_u16(&mut self) -> u16 {
let (value, rest) = self.bytes.split_at(2);
self.bytes = rest;
u16::from_le_bytes([value[0], value[1]])
}
pub fn read_u32(&mut self) -> u32 {
let (value, rest) = self.bytes.split_at(4);
self.bytes = rest;
u32::from_le_bytes([value[0], value[1], value[2], value[3]])
}
pub fn read_str(&mut self, len: usize) -> &'a str {
let (string, rest) = self.bytes.split_at(len);
self.bytes = rest;
str::from_utf8(string).unwrap()
}
}
@@ -1,17 +0,0 @@
pub enum Bytecode {}
impl Bytecode {
pub const GROUP_PARENTHESIS: u8 = 0;
pub const GROUP_BRACE: u8 = 1;
pub const GROUP_BRACKET: u8 = 2;
pub const GROUP_NONE: u8 = 3;
pub const IDENT: u8 = 4;
pub const PUNCT_ALONE: u8 = 5;
pub const PUNCT_JOINT: u8 = 6;
pub const LITERAL: u8 = 7;
pub const LOAD_GROUP: u8 = 8;
pub const LOAD_IDENT: u8 = 9;
pub const LOAD_PUNCT: u8 = 10;
pub const LOAD_LITERAL: u8 = 11;
pub const SET_SPAN: u8 = 12;
}
-205
View File
@@ -1,205 +0,0 @@
pub mod buffer;
pub mod bytecode;
use crate::watt::buffer::{InputBuffer, OutputBuffer};
use crate::watt::bytecode::Bytecode;
use crate::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::str::FromStr;
pub enum Kind {
Group(Delimiter),
Ident,
Punct(Spacing),
Literal,
}
pub enum Identity {}
impl Identity {
pub const RESPANNED: u32 = 1 << 31;
pub const NOVEL: u32 = u32::MAX;
}
impl Span {
fn is_call_site(&self) -> bool {
self.lo == 0 && self.hi == 0
}
}
fn post_increment(counter: &mut u32) -> impl FnMut() -> u32 + '_ {
|| {
let value = *counter;
*counter += 1;
value
}
}
pub fn load(buf: &mut InputBuffer) -> TokenStream {
let mut span_counter = 1;
let mut next_span = post_increment(&mut span_counter);
let mut next_span = || {
let next = next_span();
Span { lo: next, hi: next }
};
let [mut group_counter, mut ident_counter, mut punct_counter, mut literal_counter] = [0; 4];
let mut next_group = post_increment(&mut group_counter);
let mut next_ident = post_increment(&mut ident_counter);
let mut next_punct = post_increment(&mut punct_counter);
let mut next_literal = post_increment(&mut literal_counter);
let mut trees = Vec::new();
while !buf.is_empty() {
match match buf.read_u8() {
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
Bytecode::IDENT => Kind::Ident,
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
Bytecode::LITERAL => Kind::Literal,
_ => unreachable!(),
} {
Kind::Group(delimiter) => {
let len = buf.read_u32();
let stream = trees.drain(trees.len() - len as usize..).collect();
trees.push(TokenTree::Group(Group {
delimiter,
stream,
span: next_span(),
span_open: next_span(),
span_close: next_span(),
identity: next_group(),
}));
}
Kind::Ident => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let ident = if let Some(repr) = repr.strip_prefix("r#") {
proc_macro2::Ident::new_raw(repr, proc_macro2::Span::call_site())
} else if repr == "$crate" {
proc_macro2::Ident::new("crate", proc_macro2::Span::call_site())
} else {
proc_macro2::Ident::new(repr, proc_macro2::Span::call_site())
};
trees.push(TokenTree::Ident(Ident {
fallback: ident,
span: next_span(),
identity: next_ident(),
}));
}
Kind::Punct(spacing) => {
let ch = buf.read_u8();
assert!(ch.is_ascii());
let punct = proc_macro2::Punct::new(ch as char, spacing);
trees.push(TokenTree::Punct(Punct {
fallback: punct,
span: next_span(),
identity: next_punct(),
}));
}
Kind::Literal => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let literal = proc_macro2::Literal::from_str(repr).unwrap();
trees.push(TokenTree::Literal(Literal {
fallback: literal,
span: next_span(),
identity: next_literal(),
}));
}
}
}
TokenStream { content: trees }
}
pub fn linearize(tokens: TokenStream) -> Vec<u8> {
let mut buf = OutputBuffer::new();
for token in &tokens.content {
linearize_token(token, &mut buf);
}
buf.into_bytes()
}
fn linearize_token(token: &TokenTree, buf: &mut OutputBuffer) {
let needs_span;
match token {
TokenTree::Group(group) => {
if group.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_GROUP);
buf.write_u32(group.identity & !Identity::RESPANNED);
needs_span = group.identity >= Identity::RESPANNED;
} else {
let len = group.stream.len();
assert!(len <= u32::MAX as usize);
for token in &group.stream {
linearize_token(token, buf);
}
buf.write_u8(match group.delimiter {
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
Delimiter::Brace => Bytecode::GROUP_BRACE,
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
Delimiter::None => Bytecode::GROUP_NONE,
});
buf.write_u32(len as u32);
needs_span = !group.span.is_call_site();
}
}
TokenTree::Ident(ident) => {
if ident.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_IDENT);
buf.write_u32(ident.identity & !Identity::RESPANNED);
needs_span = ident.identity >= Identity::RESPANNED;
} else {
buf.write_u8(Bytecode::IDENT);
let repr = ident.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
linearize_span(ident.span, buf);
needs_span = false;
}
}
TokenTree::Punct(punct) => {
if punct.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_PUNCT);
buf.write_u32(punct.identity & !Identity::RESPANNED);
needs_span = punct.identity >= Identity::RESPANNED;
} else {
buf.write_u8(match punct.spacing() {
Spacing::Alone => Bytecode::PUNCT_ALONE,
Spacing::Joint => Bytecode::PUNCT_JOINT,
});
let ch = punct.as_char();
assert!(ch.is_ascii());
buf.write_u8(ch as u8);
needs_span = !punct.span.is_call_site();
}
}
TokenTree::Literal(literal) => {
if literal.identity < Identity::NOVEL {
buf.write_u8(Bytecode::LOAD_LITERAL);
buf.write_u32(literal.identity & !Identity::RESPANNED);
needs_span = literal.identity >= Identity::RESPANNED;
} else {
buf.write_u8(Bytecode::LITERAL);
let repr = literal.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
needs_span = !literal.span.is_call_site();
}
}
}
if needs_span {
buf.write_u8(Bytecode::SET_SPAN);
linearize_span(token.span(), buf);
}
}
fn linearize_span(span: Span, buf: &mut OutputBuffer) {
buf.write_u32(span.lo);
buf.write_u32(span.hi);
}
-36
View File
@@ -1,36 +0,0 @@
[package]
name = "serde_derive"
version = "1.0.175"
authors = ["David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"]
description = "Implementation of #[derive(Serialize, Deserialize)]"
documentation = "https://serde.rs/derive.html"
edition = "2015"
homepage = "https://serde.rs"
include = ["serde_derive-x86_64-unknown-linux-gnu", "src", "LICENSE-APACHE", "LICENSE-MIT"]
keywords = ["serde", "serialization", "no_std", "derive"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
repository = "https://github.com/serde-rs/serde"
rust-version = "1.56"
[features]
default = []
deserialize_in_place = []
[lib]
proc-macro = true
[target.'cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))'.dependencies]
proc-macro2 = "1"
quote = "1"
syn = "2.0.25"
[dev-dependencies]
serde = { version = "1", path = "../../serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
[workspace]
-1
View File
@@ -1 +0,0 @@
../../LICENSE-APACHE
-1
View File
@@ -1 +0,0 @@
../../LICENSE-MIT
-1
View File
@@ -1 +0,0 @@
../../README.md
-1
View File
@@ -1 +0,0 @@
../../crates-io.md
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/bound.rs
-1
View File
@@ -1 +0,0 @@
../../proc-macro2/src/watt/buffer.rs
-1
View File
@@ -1 +0,0 @@
../../proc-macro2/src/watt/bytecode.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/de.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/dummy.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/fragment.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/internals/
-25
View File
@@ -1,25 +0,0 @@
//! This crate provides Serde's two derive macros.
//!
//! ```edition2021
//! # use serde_derive::{Deserialize, Serialize};
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.175")]
#![allow(unknown_lints, bare_trait_objects)]
extern crate proc_macro;
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
include!("lib_from_source.rs");
#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))]
include!("lib_precompiled.rs");
@@ -1,39 +0,0 @@
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate proc_macro2;
mod internals;
use proc_macro::TokenStream;
use syn::DeriveInput;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod de;
mod dummy;
mod pretend;
mod ser;
mod this;
mod try;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&mut input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&mut input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
@@ -1,219 +0,0 @@
mod buffer;
mod bytecode;
use crate::buffer::{InputBuffer, OutputBuffer};
use crate::bytecode::Bytecode;
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::io::{Read, Write};
use std::iter::FromIterator;
use std::process::{Command, ExitStatus, Stdio};
use std::str::FromStr;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
derive(0, input)
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
derive(1 + cfg!(feature = "deserialize_in_place") as u8, input)
}
fn derive(select: u8, input: TokenStream) -> TokenStream {
let mut memory = TokenMemory::default();
let mut buf = OutputBuffer::new();
buf.write_u8(select);
memory.spans.push(Span::call_site());
for token in input {
memory.linearize_token(token, &mut buf);
}
let path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/serde_derive-x86_64-unknown-linux-gnu",
);
let mut child = Command::new(path)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("failed to spawn process");
let mut stdin = child.stdin.take().unwrap();
let mut buf = buf.into_bytes();
stdin.write_all(&buf).unwrap();
drop(stdin);
let mut stdout = child.stdout.take().unwrap();
buf.clear();
stdout.read_to_end(&mut buf).unwrap();
let success = child.wait().as_ref().map_or(true, ExitStatus::success);
if !success || buf.is_empty() {
panic!();
}
let mut buf = InputBuffer::new(&buf);
memory.receive(&mut buf)
}
#[derive(Default)]
struct TokenMemory {
spans: Vec<Span>,
groups: Vec<Group>,
idents: Vec<Ident>,
puncts: Vec<Punct>,
literals: Vec<Literal>,
}
enum Kind {
Group(Delimiter),
Ident,
Punct(Spacing),
Literal,
}
impl TokenMemory {
// Depth-first post-order traversal.
fn linearize_token(&mut self, token: TokenTree, buf: &mut OutputBuffer) {
match token {
TokenTree::Group(group) => {
let mut len = 0usize;
for token in group.stream() {
self.linearize_token(token, buf);
len += 1;
}
assert!(len <= u32::MAX as usize);
buf.write_u8(match group.delimiter() {
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
Delimiter::Brace => Bytecode::GROUP_BRACE,
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
Delimiter::None => Bytecode::GROUP_NONE,
});
buf.write_u32(len as u32);
self.spans
.extend([group.span(), group.span_open(), group.span_close()]);
self.groups.push(group);
}
TokenTree::Ident(ident) => {
buf.write_u8(Bytecode::IDENT);
let repr = ident.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
self.spans.push(ident.span());
self.idents.push(ident);
}
TokenTree::Punct(punct) => {
buf.write_u8(match punct.spacing() {
Spacing::Alone => Bytecode::PUNCT_ALONE,
Spacing::Joint => Bytecode::PUNCT_JOINT,
});
let ch = punct.as_char();
assert!(ch.is_ascii());
buf.write_u8(ch as u8);
self.spans.push(punct.span());
self.puncts.push(punct);
}
TokenTree::Literal(literal) => {
buf.write_u8(Bytecode::LITERAL);
let repr = literal.to_string();
assert!(repr.len() <= u16::MAX as usize);
buf.write_u16(repr.len() as u16);
buf.write_str(&repr);
self.spans.push(literal.span());
self.literals.push(literal);
}
}
}
fn receive(&self, buf: &mut InputBuffer) -> TokenStream {
let mut trees = Vec::new();
while !buf.is_empty() {
match match buf.read_u8() {
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
Bytecode::IDENT => Kind::Ident,
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
Bytecode::LITERAL => Kind::Literal,
Bytecode::LOAD_GROUP => {
let identity = buf.read_u32();
let group = self.groups[identity as usize].clone();
trees.push(TokenTree::Group(group));
continue;
}
Bytecode::LOAD_IDENT => {
let identity = buf.read_u32();
let ident = self.idents[identity as usize].clone();
trees.push(TokenTree::Ident(ident));
continue;
}
Bytecode::LOAD_PUNCT => {
let identity = buf.read_u32();
let punct = self.puncts[identity as usize].clone();
trees.push(TokenTree::Punct(punct));
continue;
}
Bytecode::LOAD_LITERAL => {
let identity = buf.read_u32();
let literal = self.literals[identity as usize].clone();
trees.push(TokenTree::Literal(literal));
continue;
}
Bytecode::SET_SPAN => {
trees.last_mut().unwrap().set_span(self.read_span(buf));
continue;
}
_ => unreachable!(),
} {
Kind::Group(delimiter) => {
let len = buf.read_u32();
let stream = trees.drain(trees.len() - len as usize..).collect();
let group = Group::new(delimiter, stream);
trees.push(TokenTree::Group(group));
}
Kind::Ident => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let span = self.read_span(buf);
let ident = if let Some(repr) = repr.strip_prefix("r#") {
Ident::new_raw(repr, span)
} else {
Ident::new(repr, span)
};
trees.push(TokenTree::Ident(ident));
}
Kind::Punct(spacing) => {
let ch = buf.read_u8();
assert!(ch.is_ascii());
let punct = Punct::new(ch as char, spacing);
trees.push(TokenTree::Punct(punct));
}
Kind::Literal => {
let len = buf.read_u16();
let repr = buf.read_str(len as usize);
let literal = Literal::from_str(repr).unwrap();
trees.push(TokenTree::Literal(literal));
}
}
}
TokenStream::from_iter(trees)
}
fn read_span(&self, buf: &mut InputBuffer) -> Span {
let lo = buf.read_u32();
let hi = buf.read_u32();
let span = self.spans[lo as usize];
if lo == hi {
span
} else {
#[cfg(any())] // FIXME
return span.join(self.spans[hi as usize]).unwrap_or(span);
span
}
}
}
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/pretend.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/ser.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/this.rs
-1
View File
@@ -1 +0,0 @@
../../../serde_derive/src/try.rs
+12 -3
View File
@@ -1,20 +1,21 @@
[package]
name = "serde"
version = "1.0.175" # remember to update html_root_url and serde_derive dependency
version = "1.0.189" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
categories = ["encoding", "no-std", "no-std::no-alloc"]
description = "A generic serialization/deserialization framework"
documentation = "https://docs.rs/serde"
edition = "2018"
homepage = "https://serde.rs"
keywords = ["serde", "serialization", "no_std"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
repository = "https://github.com/serde-rs/serde"
rust-version = "1.19"
rust-version = "1.31"
[dependencies]
serde_derive = { version = "=1.0.175", optional = true, path = "../serde_derive" }
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1", path = "../serde_derive" }
@@ -30,6 +31,14 @@ features = ["derive"]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
# This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's
# version in lockstep with serde's, even if someone depends on the two crates
# separately with serde's "derive" feature disabled. Every serde_derive release
# is compatible with exactly one serde release because the generated code
# involves nonpublic APIs which are not bound by semver.
[target.'cfg(any())'.dependencies]
serde_derive = { version = "=1.0.189", path = "../serde_derive" }
### FEATURES #################################################################
-62
View File
@@ -16,68 +16,6 @@ fn main() {
let target = env::var("TARGET").unwrap();
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
// std::collections::Bound was stabilized in Rust 1.17
// but it was moved to core::ops later in Rust 1.26:
// https://doc.rust-lang.org/core/ops/enum.Bound.html
if minor < 26 {
println!("cargo:rustc-cfg=no_ops_bound");
if minor < 17 {
println!("cargo:rustc-cfg=no_collections_bound");
}
}
// core::cmp::Reverse stabilized in Rust 1.19:
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
if minor < 19 {
println!("cargo:rustc-cfg=no_core_reverse");
}
// CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20:
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
// https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path
if minor < 20 {
println!("cargo:rustc-cfg=no_de_boxed_c_str");
println!("cargo:rustc-cfg=no_de_boxed_path");
}
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
if minor < 21 {
println!("cargo:rustc-cfg=no_de_rc_dst");
}
// Duration available in core since Rust 1.25:
// https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
if minor < 25 {
println!("cargo:rustc-cfg=no_core_duration");
}
// 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
//
// Disabled on Emscripten targets before Rust 1.40 since
// Emscripten did not support 128-bit integers until Rust 1.40
// (https://github.com/rust-lang/rust/pull/65251)
if minor < 26 || emscripten && minor < 40 {
println!("cargo:rustc-cfg=no_integer128");
}
// Inclusive ranges methods stabilized in Rust 1.27:
// https://github.com/rust-lang/rust/pull/50758
// Also Iterator::try_for_each:
// https://blog.rust-lang.org/2018/06/21/Rust-1.27.html#library-stabilizations
if minor < 27 {
println!("cargo:rustc-cfg=no_range_inclusive");
println!("cargo:rustc-cfg=no_iterator_try_fold");
}
// Non-zero integers stabilized in Rust 1.28:
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
if minor < 28 {
println!("cargo:rustc-cfg=no_num_nonzero");
}
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
// stabilized in Rust 1.34:
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
+2 -2
View File
@@ -1,5 +1,5 @@
use lib::fmt::{self, Write};
use lib::str;
use crate::lib::fmt::{self, Write};
use crate::lib::str;
pub(super) struct Buf<'a> {
bytes: &'a mut [u8],
+13 -17
View File
@@ -1,6 +1,6 @@
use lib::*;
use crate::lib::*;
use de::{
use crate::de::{
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};
@@ -129,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
Ok(IgnoredAny)
}
serde_if_integer128! {
#[inline]
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
@@ -143,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
Ok(IgnoredAny)
}
serde_if_integer128! {
#[inline]
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
@@ -197,7 +193,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: SeqAccess<'de>,
{
while let Some(IgnoredAny) = try!(seq.next_element()) {
while let Some(IgnoredAny) = tri!(seq.next_element()) {
// Gobble
}
Ok(IgnoredAny)
@@ -208,7 +204,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: MapAccess<'de>,
{
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) {
// Gobble
}
Ok(IgnoredAny)
@@ -227,7 +223,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: EnumAccess<'de>,
{
try!(data.variant::<IgnoredAny>()).1.newtype_variant()
tri!(data.variant::<IgnoredAny>()).1.newtype_variant()
}
}
+121 -165
View File
@@ -1,16 +1,14 @@
use lib::*;
use crate::lib::*;
use de::{
Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
use crate::de::{
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, Unexpected, VariantAccess,
Visitor,
};
#[cfg(any(feature = "std", feature = "alloc", not(no_core_duration)))]
use de::MapAccess;
use seed::InPlaceSeed;
use crate::seed::InPlaceSeed;
#[cfg(any(feature = "std", feature = "alloc"))]
use __private::size_hint;
use crate::de::size_hint;
////////////////////////////////////////////////////////////////////////////////
@@ -84,7 +82,7 @@ macro_rules! impl_deserialize_num {
($primitive:ident, $nonzero:ident $(cfg($($cfg:tt)*))*, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => {
impl_deserialize_num!($primitive, $deserialize $($method!($($val : $visit)*);)*);
#[cfg(all(not(no_num_nonzero), $($($cfg)*)*))]
$(#[cfg($($cfg)*)])*
impl<'de> Deserialize<'de> for num::$nonzero {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@@ -366,64 +364,62 @@ impl_deserialize_num! {
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
}
serde_if_integer128! {
macro_rules! num_128 {
($ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
macro_rules! num_128 {
($ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if v as i128 >= Self::Value::min_value() as i128
&& v as u128 <= Self::Value::max_value() as u128
{
if v as i128 >= Self::Value::min_value() as i128
&& v as u128 <= Self::Value::max_value() as u128
{
Ok(v as Self::Value)
} else {
Err(Error::invalid_value(
Unexpected::Other(stringify!($ty)),
&self,
))
}
Ok(v as Self::Value)
} else {
Err(Error::invalid_value(
Unexpected::Other(stringify!($ty)),
&self,
))
}
};
}
};
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if v as i128 >= $primitive::min_value() as i128
&& v as u128 <= $primitive::max_value() as u128
{
if v as i128 >= $primitive::min_value() as i128
&& v as u128 <= $primitive::max_value() as u128
{
if let Some(nonzero) = Self::Value::new(v as $primitive) {
Ok(nonzero)
} else {
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
}
if let Some(nonzero) = Self::Value::new(v as $primitive) {
Ok(nonzero)
} else {
Err(Error::invalid_value(
Unexpected::Other(stringify!($ty)),
&self,
))
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
}
} else {
Err(Error::invalid_value(
Unexpected::Other(stringify!($ty)),
&self,
))
}
};
}
}
};
}
impl_deserialize_num! {
i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), deserialize_i128
num_self!(i128:visit_i128);
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
num_128!(u128:visit_u128);
}
impl_deserialize_num! {
i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), deserialize_i128
num_self!(i128:visit_i128);
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
num_128!(u128:visit_u128);
}
impl_deserialize_num! {
u128, NonZeroU128, deserialize_u128
num_self!(u128:visit_u128);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
num_128!(i128:visit_i128);
}
impl_deserialize_num! {
u128, NonZeroU128, deserialize_u128
num_self!(u128:visit_u128);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
num_128!(i128:visit_i128);
}
////////////////////////////////////////////////////////////////////////////////
@@ -684,7 +680,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
let capacity = size_hint::cautious::<u8>(seq.size_hint());
let mut values = Vec::<u8>::with_capacity(capacity);
while let Some(value) = try!(seq.next_element()) {
while let Some(value) = tri!(seq.next_element()) {
values.push(value);
}
@@ -747,13 +743,9 @@ macro_rules! forwarded_impl {
}
}
#[cfg(all(
any(feature = "std", all(not(no_core_cstr), feature = "alloc")),
not(no_de_boxed_c_str)
))]
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
#[cfg(not(no_core_reverse))]
forwarded_impl!((T), Reverse<T>, Reverse);
////////////////////////////////////////////////////////////////////////////////
@@ -901,7 +893,7 @@ macro_rules! seq_impl {
{
let mut values = $with_capacity;
while let Some(value) = try!($access.next_element()) {
while let Some(value) = tri!($access.next_element()) {
$insert(&mut values, value);
}
@@ -939,7 +931,7 @@ macro_rules! seq_impl {
$reserve(&mut self.0, size_hint::cautious::<T>($access.size_hint()));
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
while let Some(value) = try!($access.next_element()) {
while let Some(value) = tri!($access.next_element()) {
$insert(&mut self.0, value);
}
@@ -1039,7 +1031,7 @@ where
let capacity = size_hint::cautious::<T>(seq.size_hint());
let mut values = Vec::<T>::with_capacity(capacity);
while let Some(value) = try!(seq.next_element()) {
while let Some(value) = tri!(seq.next_element()) {
values.push(value);
}
@@ -1081,7 +1073,7 @@ where
for i in 0..self.0.len() {
let next = {
let next_place = InPlaceSeed(&mut self.0[i]);
try!(seq.next_element_seed(next_place))
tri!(seq.next_element_seed(next_place))
};
if next.is_none() {
self.0.truncate(i);
@@ -1089,7 +1081,7 @@ where
}
}
while let Some(value) = try!(seq.next_element()) {
while let Some(value) = tri!(seq.next_element()) {
self.0.push(value);
}
@@ -1161,7 +1153,7 @@ macro_rules! array_impls {
A: SeqAccess<'de>,
{
Ok([$(
match try!(seq.next_element()) {
match tri!(seq.next_element()) {
Some(val) => val,
None => return Err(Error::invalid_length($n, &self)),
}
@@ -1186,7 +1178,7 @@ macro_rules! array_impls {
{
let mut fail_idx = None;
for (idx, dest) in self.0[..].iter_mut().enumerate() {
if try!(seq.next_element_seed(InPlaceSeed(dest))).is_none() {
if tri!(seq.next_element_seed(InPlaceSeed(dest))).is_none() {
fail_idx = Some(idx);
break;
}
@@ -1284,7 +1276,7 @@ macro_rules! tuple_impls {
A: SeqAccess<'de>,
{
$(
let $name = match try!(seq.next_element()) {
let $name = match tri!(seq.next_element()) {
Some(value) => value,
None => return Err(Error::invalid_length($n, &self)),
};
@@ -1318,7 +1310,7 @@ macro_rules! tuple_impls {
A: SeqAccess<'de>,
{
$(
if try!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() {
if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() {
return Err(Error::invalid_length($n, &self));
}
)+
@@ -1395,7 +1387,7 @@ macro_rules! map_impl {
{
let mut values = $with_capacity;
while let Some((key, value)) = try!($access.next_entry()) {
while let Some((key, value)) = tri!($access.next_entry()) {
values.insert(key, value);
}
@@ -1541,7 +1533,7 @@ macro_rules! deserialize_enum {
where
A: EnumAccess<'de>,
{
match try!(data.variant()) {
match tri!(data.variant()) {
$(
($name_kind :: $variant, v) => v.newtype_variant().map($name :: $variant),
)*
@@ -1561,7 +1553,7 @@ impl<'de> Deserialize<'de> for net::IpAddr {
if deserializer.is_human_readable() {
deserializer.deserialize_str(FromStrVisitor::new("IP address"))
} else {
use lib::net::IpAddr;
use crate::lib::net::IpAddr;
deserialize_enum! {
IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
"`V4` or `V6`",
@@ -1604,7 +1596,7 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
if deserializer.is_human_readable() {
deserializer.deserialize_str(FromStrVisitor::new("socket address"))
} else {
use lib::net::SocketAddr;
use crate::lib::net::SocketAddr;
deserialize_enum! {
SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
"`V4` or `V6`",
@@ -1714,7 +1706,7 @@ impl<'de> Deserialize<'de> for PathBuf {
}
}
#[cfg(all(feature = "std", not(no_de_boxed_path)))]
#[cfg(feature = "std")]
forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path);
////////////////////////////////////////////////////////////////////////////////
@@ -1748,7 +1740,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
{
use std::os::unix::ffi::OsStringExt;
match try!(data.variant()) {
match tri!(data.variant()) {
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec),
(OsStringKind::Windows, _) => Err(Error::custom(
"cannot deserialize Windows OS string on Unix",
@@ -1763,7 +1755,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
{
use std::os::windows::ffi::OsStringExt;
match try!(data.variant()) {
match tri!(data.variant()) {
(OsStringKind::Windows, v) => v
.newtype_variant::<Vec<u16>>()
.map(|vec| OsString::from_wide(&vec)),
@@ -1795,29 +1787,8 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
#[cfg(any(feature = "std", feature = "alloc"))]
forwarded_impl!((), Box<str>, String::into_boxed_str);
#[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Arc` will not attempt to
/// deduplicate `Arc` references to the same data. Every deserialized `Arc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
(T), Arc<T>, Arc::new
}
#[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Rc` will not attempt to
/// deduplicate `Rc` references to the same data. Every deserialized `Rc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
(T), Rc<T>, Rc::new
}
#[cfg(all(feature = "std", any(unix, windows)))]
forwarded_impl!((), Box<OsStr>, OsString::into_boxed_os_str);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
@@ -1849,7 +1820,7 @@ where
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
tri!(Option::<T>::deserialize(deserializer));
Ok(RcWeak::new())
}
}
@@ -1867,18 +1838,14 @@ where
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
tri!(Option::<T>::deserialize(deserializer));
Ok(ArcWeak::new())
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
macro_rules! box_forwarded_impl {
(
$(#[doc = $doc:tt])*
@@ -1899,11 +1866,7 @@ macro_rules! box_forwarded_impl {
};
}
#[cfg(all(
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
@@ -1915,11 +1878,7 @@ box_forwarded_impl! {
Rc
}
#[cfg(all(
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
@@ -1963,7 +1922,6 @@ forwarded_impl!((T), RwLock<T>, RwLock::new);
// secs: u64,
// nanos: u32,
// }
#[cfg(any(feature = "std", not(no_core_duration)))]
impl<'de> Deserialize<'de> for Duration {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@@ -2011,7 +1969,7 @@ impl<'de> Deserialize<'de> for Duration {
b"secs" => Ok(Field::Secs),
b"nanos" => Ok(Field::Nanos),
_ => {
let value = ::__private::from_utf8_lossy(value);
let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS))
}
}
@@ -2046,19 +2004,19 @@ impl<'de> Deserialize<'de> for Duration {
where
A: SeqAccess<'de>,
{
let secs: u64 = match try!(seq.next_element()) {
let secs: u64 = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let nanos: u32 = match try!(seq.next_element()) {
let nanos: u32 = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
try!(check_overflow(secs, nanos));
tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
@@ -2068,19 +2026,19 @@ impl<'de> Deserialize<'de> for Duration {
{
let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None;
while let Some(key) = try!(map.next_key()) {
while let Some(key) = tri!(map.next_key()) {
match key {
Field::Secs => {
if secs.is_some() {
return Err(<A::Error as Error>::duplicate_field("secs"));
}
secs = Some(try!(map.next_value()));
secs = Some(tri!(map.next_value()));
}
Field::Nanos => {
if nanos.is_some() {
return Err(<A::Error as Error>::duplicate_field("nanos"));
}
nanos = Some(try!(map.next_value()));
nanos = Some(tri!(map.next_value()));
}
}
}
@@ -2092,7 +2050,7 @@ impl<'de> Deserialize<'de> for Duration {
Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos")),
};
try!(check_overflow(secs, nanos));
tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
}
@@ -2184,19 +2142,19 @@ impl<'de> Deserialize<'de> for SystemTime {
where
A: SeqAccess<'de>,
{
let secs: u64 = match try!(seq.next_element()) {
let secs: u64 = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let nanos: u32 = match try!(seq.next_element()) {
let nanos: u32 = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
try!(check_overflow(secs, nanos));
tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
@@ -2206,7 +2164,7 @@ impl<'de> Deserialize<'de> for SystemTime {
{
let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None;
while let Some(key) = try!(map.next_key()) {
while let Some(key) = tri!(map.next_key()) {
match key {
Field::Secs => {
if secs.is_some() {
@@ -2214,7 +2172,7 @@ impl<'de> Deserialize<'de> for SystemTime {
"secs_since_epoch",
));
}
secs = Some(try!(map.next_value()));
secs = Some(tri!(map.next_value()));
}
Field::Nanos => {
if nanos.is_some() {
@@ -2222,7 +2180,7 @@ impl<'de> Deserialize<'de> for SystemTime {
"nanos_since_epoch",
));
}
nanos = Some(try!(map.next_value()));
nanos = Some(tri!(map.next_value()));
}
}
}
@@ -2234,13 +2192,13 @@ impl<'de> Deserialize<'de> for SystemTime {
Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
};
try!(check_overflow(secs, nanos));
tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos))
}
}
const FIELDS: &[&str] = &["secs_since_epoch", "nanos_since_epoch"];
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
let duration = tri!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
#[cfg(not(no_systemtime_checked_add))]
let ret = UNIX_EPOCH
.checked_add(duration)
@@ -2269,7 +2227,7 @@ where
where
D: Deserializer<'de>,
{
let (start, end) = try!(deserializer.deserialize_struct(
let (start, end) = tri!(deserializer.deserialize_struct(
"Range",
range::FIELDS,
range::RangeVisitor {
@@ -2281,7 +2239,6 @@ where
}
}
#[cfg(not(no_range_inclusive))]
impl<'de, Idx> Deserialize<'de> for RangeInclusive<Idx>
where
Idx: Deserialize<'de>,
@@ -2290,7 +2247,7 @@ where
where
D: Deserializer<'de>,
{
let (start, end) = try!(deserializer.deserialize_struct(
let (start, end) = tri!(deserializer.deserialize_struct(
"RangeInclusive",
range::FIELDS,
range::RangeVisitor {
@@ -2303,9 +2260,9 @@ where
}
mod range {
use lib::*;
use crate::lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["start", "end"];
@@ -2351,7 +2308,7 @@ mod range {
b"start" => Ok(Field::Start),
b"end" => Ok(Field::End),
_ => {
let value = ::__private::from_utf8_lossy(value);
let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS))
}
}
@@ -2381,13 +2338,13 @@ mod range {
where
A: SeqAccess<'de>,
{
let start: Idx = match try!(seq.next_element()) {
let start: Idx = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let end: Idx = match try!(seq.next_element()) {
let end: Idx = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
@@ -2402,19 +2359,19 @@ mod range {
{
let mut start: Option<Idx> = None;
let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
while let Some(key) = tri!(map.next_key()) {
match key {
Field::Start => {
if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start"));
}
start = Some(try!(map.next_value()));
start = Some(tri!(map.next_value()));
}
Field::End => {
if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end"));
}
end = Some(try!(map.next_value()));
end = Some(tri!(map.next_value()));
}
}
}
@@ -2448,7 +2405,7 @@ where
where
D: Deserializer<'de>,
{
let start = try!(deserializer.deserialize_struct(
let start = tri!(deserializer.deserialize_struct(
"RangeFrom",
range_from::FIELDS,
range_from::RangeFromVisitor {
@@ -2461,9 +2418,9 @@ where
}
mod range_from {
use lib::*;
use crate::lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["end"];
@@ -2506,7 +2463,7 @@ mod range_from {
match value {
b"end" => Ok(Field::End),
_ => {
let value = ::__private::from_utf8_lossy(value);
let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS))
}
}
@@ -2536,7 +2493,7 @@ mod range_from {
where
A: SeqAccess<'de>,
{
let end: Idx = match try!(seq.next_element()) {
let end: Idx = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
@@ -2550,13 +2507,13 @@ mod range_from {
A: MapAccess<'de>,
{
let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
while let Some(key) = tri!(map.next_key()) {
match key {
Field::End => {
if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end"));
}
end = Some(try!(map.next_value()));
end = Some(tri!(map.next_value()));
}
}
}
@@ -2586,7 +2543,7 @@ where
where
D: Deserializer<'de>,
{
let end = try!(deserializer.deserialize_struct(
let end = tri!(deserializer.deserialize_struct(
"RangeTo",
range_to::FIELDS,
range_to::RangeToVisitor {
@@ -2599,9 +2556,9 @@ where
}
mod range_to {
use lib::*;
use crate::lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["start"];
@@ -2644,7 +2601,7 @@ mod range_to {
match value {
b"start" => Ok(Field::Start),
_ => {
let value = ::__private::from_utf8_lossy(value);
let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS))
}
}
@@ -2674,7 +2631,7 @@ mod range_to {
where
A: SeqAccess<'de>,
{
let start: Idx = match try!(seq.next_element()) {
let start: Idx = match tri!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
@@ -2688,13 +2645,13 @@ mod range_to {
A: MapAccess<'de>,
{
let mut start: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
while let Some(key) = tri!(map.next_key()) {
match key {
Field::Start => {
if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start"));
}
start = Some(try!(map.next_value()));
start = Some(tri!(map.next_value()));
}
}
}
@@ -2709,7 +2666,6 @@ mod range_to {
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<'de, T> Deserialize<'de> for Bound<T>
where
T: Deserialize<'de>,
@@ -2801,7 +2757,7 @@ where
where
A: EnumAccess<'de>,
{
match try!(data.variant()) {
match tri!(data.variant()) {
(Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded),
(Field::Included, v) => v.newtype_variant().map(Bound::Included),
(Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded),
@@ -2910,7 +2866,7 @@ where
where
A: EnumAccess<'de>,
{
match try!(data.variant()) {
match tri!(data.variant()) {
(Field::Ok, v) => v.newtype_variant().map(Ok),
(Field::Err, v) => v.newtype_variant().map(Err),
}
+64 -69
View File
@@ -112,26 +112,28 @@
//! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats
use lib::*;
use crate::lib::*;
////////////////////////////////////////////////////////////////////////////////
pub mod value;
#[cfg(not(no_integer128))]
mod format;
mod ignored_any;
mod impls;
mod utf8;
pub(crate) mod size_hint;
pub use self::ignored_any::IgnoredAny;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use crate::std_error::Error as StdError;
#[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(no_inline)]
pub use core::error::Error as StdError;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
////////////////////////////////////////////////////////////////////////////////
@@ -566,7 +568,7 @@ pub trait Deserialize<'de>: Sized {
D: Deserializer<'de>,
{
// Default implementation just delegates to `deserialize` impl.
*place = try!(Deserialize::deserialize(deserializer));
*place = tri!(Deserialize::deserialize(deserializer));
Ok(())
}
}
@@ -946,18 +948,15 @@ pub trait Deserializer<'de>: Sized {
where
V: Visitor<'de>;
serde_if_integer128! {
/// Hint that the `Deserialize` type is expecting an `i128` value.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>
{
let _ = visitor;
Err(Error::custom("i128 is not supported"))
}
/// Hint that the `Deserialize` type is expecting an `i128` value.
///
/// The default behavior unconditionally returns an error.
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let _ = visitor;
Err(Error::custom("i128 is not supported"))
}
/// Hint that the `Deserialize` type is expecting a `u8` value.
@@ -980,18 +979,15 @@ pub trait Deserializer<'de>: Sized {
where
V: Visitor<'de>;
serde_if_integer128! {
/// Hint that the `Deserialize` type is expecting an `u128` value.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>
{
let _ = visitor;
Err(Error::custom("u128 is not supported"))
}
/// Hint that the `Deserialize` type is expecting an `u128` value.
///
/// The default behavior unconditionally returns an error.
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let _ = visitor;
Err(Error::custom("u128 is not supported"))
}
/// Hint that the `Deserialize` type is expecting a `f32` value.
@@ -1226,11 +1222,11 @@ pub trait Deserializer<'de>: Sized {
#[doc(hidden)]
fn __deserialize_content<V>(
self,
_: ::actually_private::T,
_: crate::actually_private::T,
visitor: V,
) -> Result<::private::de::Content<'de>, Self::Error>
) -> Result<crate::__private::de::Content<'de>, Self::Error>
where
V: Visitor<'de, Value = ::private::de::Content<'de>>,
V: Visitor<'de, Value = crate::__private::de::Content<'de>>,
{
self.deserialize_any(visitor)
}
@@ -1363,20 +1359,20 @@ pub trait Visitor<'de>: Sized {
Err(Error::invalid_type(Unexpected::Signed(v), &self))
}
serde_if_integer128! {
/// The input contains a `i128`.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default implementation fails with a type error.
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
let mut buf = [0u8; 58];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
}
/// The input contains a `i128`.
///
/// The default implementation fails with a type error.
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
let mut buf = [0u8; 58];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
Err(Error::invalid_type(
Unexpected::Other(writer.as_str()),
&self,
))
}
/// The input contains a `u8`.
@@ -1425,20 +1421,20 @@ pub trait Visitor<'de>: Sized {
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
}
serde_if_integer128! {
/// The input contains a `u128`.
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default implementation fails with a type error.
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
let mut buf = [0u8; 57];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
}
/// The input contains a `u128`.
///
/// The default implementation fails with a type error.
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: Error,
{
let mut buf = [0u8; 57];
let mut writer = format::Buf::new(&mut buf);
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
Err(Error::invalid_type(
Unexpected::Other(writer.as_str()),
&self,
))
}
/// The input contains an `f32`.
@@ -1474,7 +1470,7 @@ pub trait Visitor<'de>: Sized {
where
E: Error,
{
self.visit_str(utf8::encode(v).as_str())
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
}
/// The input contains a string. The lifetime of the string is ephemeral and
@@ -1551,7 +1547,6 @@ pub trait Visitor<'de>: Sized {
where
E: Error,
{
let _ = v;
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
}
@@ -1831,9 +1826,9 @@ pub trait MapAccess<'de> {
K: DeserializeSeed<'de>,
V: DeserializeSeed<'de>,
{
match try!(self.next_key_seed(kseed)) {
match tri!(self.next_key_seed(kseed)) {
Some(key) => {
let value = try!(self.next_value_seed(vseed));
let value = tri!(self.next_value_seed(vseed));
Ok(Some((key, value)))
}
None => Ok(None),
@@ -2281,12 +2276,12 @@ impl Display for OneOf {
1 => write!(formatter, "`{}`", self.names[0]),
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
_ => {
try!(write!(formatter, "one of "));
tri!(write!(formatter, "one of "));
for (i, alt) in self.names.iter().enumerate() {
if i > 0 {
try!(write!(formatter, ", "));
tri!(write!(formatter, ", "));
}
try!(write!(formatter, "`{}`", alt));
tri!(write!(formatter, "`{}`", alt));
}
Ok(())
}
+1 -1
View File
@@ -1,4 +1,4 @@
use de::{Deserialize, DeserializeSeed, Deserializer};
use crate::de::{Deserialize, DeserializeSeed, Deserializer};
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
///
@@ -1,4 +1,4 @@
use lib::*;
use crate::lib::*;
pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
-46
View File
@@ -1,46 +0,0 @@
use lib::*;
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode(c: char) -> Encode {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
Encode { buf, pos }
}
pub struct Encode {
buf: [u8; 4],
pos: usize,
}
impl Encode {
pub fn as_str(&self) -> &str {
str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
+19 -21
View File
@@ -21,12 +21,11 @@
//! }
//! ```
use lib::*;
use crate::lib::*;
use self::private::{First, Second};
use __private::size_hint;
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use ser;
use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use crate::ser;
////////////////////////////////////////////////////////////////////////////////
@@ -293,20 +292,17 @@ primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8);
primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16);
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64);
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64);
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64);
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64);
primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
serde_if_integer128! {
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
}
/// A deserializer holding a `u32`.
pub struct U32Deserializer<E> {
value: u32,
@@ -937,8 +933,8 @@ where
where
V: de::Visitor<'de>,
{
let v = try!(visitor.visit_seq(&mut self));
try!(self.end());
let v = tri!(visitor.visit_seq(&mut self));
tri!(self.end());
Ok(v)
}
@@ -1162,8 +1158,8 @@ where
where
V: de::Visitor<'de>,
{
let value = try!(visitor.visit_map(&mut self));
try!(self.end());
let value = tri!(visitor.visit_map(&mut self));
tri!(self.end());
Ok(value)
}
@@ -1171,8 +1167,8 @@ where
where
V: de::Visitor<'de>,
{
let value = try!(visitor.visit_seq(&mut self));
try!(self.end());
let value = tri!(visitor.visit_seq(&mut self));
tri!(self.end());
Ok(value)
}
@@ -1236,8 +1232,8 @@ where
{
match self.next_pair() {
Some((key, value)) => {
let key = try!(kseed.deserialize(key.into_deserializer()));
let value = try!(vseed.deserialize(value.into_deserializer()));
let key = tri!(kseed.deserialize(key.into_deserializer()));
let value = tri!(vseed.deserialize(value.into_deserializer()));
Ok(Some((key, value)))
}
None => Ok(None),
@@ -1341,7 +1337,7 @@ where
V: de::Visitor<'de>,
{
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
let pair = try!(visitor.visit_seq(&mut pair_visitor));
let pair = tri!(visitor.visit_seq(&mut pair_visitor));
if pair_visitor.1.is_none() {
Ok(pair)
} else {
@@ -1501,7 +1497,7 @@ where
where
T: de::DeserializeSeed<'de>,
{
match try!(self.map.next_key_seed(seed)) {
match tri!(self.map.next_key_seed(seed)) {
Some(key) => Ok((key, private::map_as_enum(self.map))),
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
}
@@ -1546,9 +1542,11 @@ where
////////////////////////////////////////////////////////////////////////////////
mod private {
use lib::*;
use crate::lib::*;
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
use crate::de::{
self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor,
};
pub struct UnitOnly<E> {
marker: PhantomData<E>,
+3 -76
View File
@@ -1,82 +1,9 @@
/// Conditional compilation depending on whether Serde is built with support for
/// 128-bit integers.
///
/// Data formats that wish to support Rust compiler versions older than 1.26
/// (or targets that lack 128-bit integers) may place the i128 / u128 methods
/// of their Serializer and Deserializer behind this macro.
///
/// Data formats that require a minimum Rust compiler version of at least 1.26,
/// or do not target platforms that lack 128-bit integers, do not need to
/// bother with this macro and may assume support for 128-bit integers.
///
/// ```edition2021
/// # use serde::__private::doc::Error;
/// #
/// # struct MySerializer;
/// #
/// use serde::{serde_if_integer128, Serializer};
///
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
///
/// /* ... */
///
/// serde_if_integer128! {
/// fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
///
/// fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
/// /* ... */
/// # unimplemented!()
/// }
/// }
/// #
/// # serde::__serialize_unimplemented! {
/// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant seq
/// # tuple tuple_struct tuple_variant map struct struct_variant
/// # }
/// }
/// ```
///
/// When Serde is built with support for 128-bit integers, this macro expands
/// transparently into just the input tokens.
///
/// ```edition2021
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {
/// $($tt)*
/// };
/// }
/// ```
///
/// When built without support for 128-bit integers, this macro expands to
/// nothing.
///
/// ```edition2021
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {};
/// }
/// ```
#[cfg(not(no_integer128))]
// No longer used. Old versions of serde used this macro for supporting targets
// that did not yet have 128-bit integer support.
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {
$($tt)*
};
}
#[cfg(no_integer128)]
#[macro_export]
#[doc(hidden)]
macro_rules! serde_if_integer128 {
($($tt:tt)*) => {};
}
+53 -73
View File
@@ -63,6 +63,7 @@
//! and from DynamoDB.
//! - [Hjson], a syntax extension to JSON designed around human reading and
//! editing. *(deserialization only)*
//! - [CSV], Comma-separated values is a tabular text file format.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Postcard]: https://github.com/jamesmunns/postcard
@@ -89,11 +90,12 @@
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
//! [Hjson]: https://github.com/Canop/deser-hjson
//! [CSV]: https://docs.rs/csv
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.175")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.189")]
// 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
@@ -102,53 +104,51 @@
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(error_in_core, never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
unnested_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
semicolon_if_nothing_returned,
// not available in our oldest supported compiler
empty_enum,
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_sign_loss,
// things are often more readable this way
cast_lossless,
module_name_repetitions,
option_if_let_else,
single_match_else,
type_complexity,
use_self,
zero_prefixed_literal,
// correctly used
derive_partial_eq_without_eq,
enum_glob_use,
explicit_auto_deref,
let_underscore_untyped,
map_err_ignore,
new_without_default,
result_unit_err,
wildcard_imports,
// not practical
needless_pass_by_value,
similar_names,
too_many_lines,
// preference
doc_markdown,
unseparated_literal_suffix,
// false positive
needless_doctest_main,
// noisy
missing_errors_doc,
must_use_candidate,
)
#![allow(
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
clippy::unnested_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
clippy::semicolon_if_nothing_returned,
// not available in our oldest supported compiler
clippy::empty_enum,
clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
// integer and float ser/de requires these sorts of casts
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
// things are often more readable this way
clippy::cast_lossless,
clippy::module_name_repetitions,
clippy::option_if_let_else,
clippy::single_match_else,
clippy::type_complexity,
clippy::use_self,
clippy::zero_prefixed_literal,
// correctly used
clippy::derive_partial_eq_without_eq,
clippy::enum_glob_use,
clippy::explicit_auto_deref,
clippy::let_underscore_untyped,
clippy::map_err_ignore,
clippy::new_without_default,
clippy::result_unit_err,
clippy::wildcard_imports,
// not practical
clippy::needless_pass_by_value,
clippy::similar_names,
clippy::too_many_lines,
// preference
clippy::doc_markdown,
clippy::unseparated_literal_suffix,
// false positive
clippy::needless_doctest_main,
// noisy
clippy::missing_errors_doc,
clippy::must_use_candidate,
)]
// Restrictions
#![deny(clippy::question_mark_used)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]
@@ -175,14 +175,16 @@ mod lib {
pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone};
pub use self::core::cmp::Reverse;
pub use self::core::convert::{self, From, Into};
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::num::Wrapping;
pub use self::core::ops::{Range, RangeFrom, RangeTo};
pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo};
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
pub use self::core::time::Duration;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::borrow::{Cow, ToOwned};
@@ -220,7 +222,7 @@ mod lib {
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(all(not(no_core_cstr), not(feature = "std")))]
pub use core::ffi::CStr;
pub use self::core::ffi::CStr;
#[cfg(feature = "std")]
pub use std::ffi::CStr;
@@ -247,18 +249,6 @@ mod lib {
#[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
pub use std::collections::Bound;
#[cfg(not(no_core_reverse))]
pub use self::core::cmp::Reverse;
#[cfg(not(no_ops_bound))]
pub use self::core::ops::Bound;
#[cfg(not(no_range_inclusive))]
pub use self::core::ops::RangeInclusive;
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
@@ -279,16 +269,13 @@ mod lib {
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
#[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration;
}
// None of this crate's error handling needs the `From::from` error conversion
// performed implicitly by the `?` operator or the standard library's `try!`
// macro. This simplified macro gives a 5.5% improvement in compile time
// compared to standard `try!`, and 9% improvement compared to `?`.
macro_rules! try {
macro_rules! tri {
($expr:expr) => {
match $expr {
Ok(val) => val,
@@ -309,20 +296,15 @@ pub mod de;
pub mod ser;
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
pub use crate::de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};
pub use crate::ser::{Serialize, Serializer};
// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;
#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;
#[path = "de/seed.rs"]
mod seed;
@@ -335,8 +317,6 @@ mod std_error;
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
/// Derive macro available if serde is built with `features = ["derive"]`.
+2 -6
View File
@@ -154,9 +154,7 @@ macro_rules! forward_to_deserialize_any_helper {
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
};
(i128<$l:tt, $v:ident>) => {
serde_if_integer128! {
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
}
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
};
(u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
@@ -171,9 +169,7 @@ macro_rules! forward_to_deserialize_any_helper {
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
};
(u128<$l:tt, $v:ident>) => {
serde_if_integer128! {
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
}
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
};
(f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
+101 -185
View File
@@ -1,10 +1,13 @@
use lib::*;
use crate::lib::*;
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor};
use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use crate::de::{
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess,
Visitor,
};
#[cfg(any(feature = "std", feature = "alloc"))]
use de::{DeserializeSeed, MapAccess, Unexpected};
use crate::de::{MapAccess, Unexpected};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{
@@ -13,7 +16,7 @@ pub use self::content::{
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
};
pub use seed::InPlaceSeed;
pub use crate::seed::InPlaceSeed;
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
@@ -203,13 +206,13 @@ mod content {
// This issue is tracking making some of this stuff public:
// https://github.com/serde-rs/serde/issues/741
use lib::*;
use crate::lib::*;
use __private::size_hint;
use actually_private;
use de::{
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
MapAccess, SeqAccess, Unexpected, Visitor,
use crate::actually_private;
use crate::de::value::{MapDeserializer, SeqDeserializer};
use crate::de::{
self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected,
IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor,
};
/// Used from generated code to buffer the contents of the Deserializer when
@@ -299,6 +302,17 @@ mod content {
}
}
impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de>
where
E: de::Error,
{
type Deserializer = ContentDeserializer<'de, E>;
fn into_deserializer(self) -> Self::Deserializer {
ContentDeserializer::new(self)
}
}
struct ContentVisitor<'de> {
value: PhantomData<Content<'de>>,
}
@@ -476,7 +490,7 @@ mod content {
{
let mut vec =
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
while let Some(e) = try!(visitor.next_element()) {
while let Some(e) = tri!(visitor.next_element()) {
vec.push(e);
}
Ok(Content::Seq(vec))
@@ -490,7 +504,7 @@ mod content {
Vec::<(Content, Content)>::with_capacity(
size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
);
while let Some(kv) = try!(visitor.next_entry()) {
while let Some(kv) = tri!(visitor.next_entry()) {
vec.push(kv);
}
Ok(Content::Map(vec))
@@ -833,14 +847,14 @@ mod content {
where
S: SeqAccess<'de>,
{
let tag = match try!(seq.next_element()) {
let tag = match tri!(seq.next_element()) {
Some(tag) => tag,
None => {
return Err(de::Error::missing_field(self.tag_name));
}
};
let rest = de::value::SeqAccessDeserializer::new(seq);
Ok((tag, try!(Content::deserialize(rest))))
Ok((tag, tri!(Content::deserialize(rest))))
}
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
@@ -852,16 +866,16 @@ mod content {
Content,
Content,
)>(map.size_hint()));
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k {
TagOrContent::Tag => {
if tag.is_some() {
return Err(de::Error::duplicate_field(self.tag_name));
}
tag = Some(try!(map.next_value()));
tag = Some(tri!(map.next_value()));
}
TagOrContent::Content(k) => {
let v = try!(map.next_value());
let v = tri!(map.next_value());
vec.push((k, v));
}
}
@@ -1074,9 +1088,9 @@ mod content {
E: de::Error,
{
let seq = content.into_iter().map(ContentDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end());
let mut seq_visitor = SeqDeserializer::new(seq);
let value = tri!(visitor.visit_seq(&mut seq_visitor));
tri!(seq_visitor.end());
Ok(value)
}
@@ -1091,9 +1105,9 @@ mod content {
let map = content
.into_iter()
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
let mut map_visitor = MapDeserializer::new(map);
let value = tri!(visitor.visit_map(&mut map_visitor));
tri!(map_visitor.end());
Ok(value)
}
@@ -1569,7 +1583,7 @@ mod content {
{
match self.value {
Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
}
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
@@ -1592,10 +1606,10 @@ mod content {
{
match self.value {
Some(Content::Map(v)) => {
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor)
}
Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
}
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
@@ -1609,156 +1623,6 @@ mod content {
}
}
struct SeqDeserializer<'de, E>
where
E: de::Error,
{
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
err: PhantomData<E>,
}
impl<'de, E> SeqDeserializer<'de, E>
where
E: de::Error,
{
fn new(vec: Vec<Content<'de>>) -> Self {
SeqDeserializer {
iter: vec.into_iter(),
err: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
#[inline]
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
let len = self.iter.len();
if len == 0 {
visitor.visit_unit()
} else {
let ret = try!(visitor.visit_seq(&mut self));
let remaining = self.iter.len();
if remaining == 0 {
Ok(ret)
} else {
Err(de::Error::invalid_length(len, &"fewer elements in array"))
}
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
None => Ok(None),
}
}
fn size_hint(&self) -> Option<usize> {
size_hint::from_bounds(&self.iter)
}
}
struct MapDeserializer<'de, E>
where
E: de::Error,
{
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
value: Option<Content<'de>>,
err: PhantomData<E>,
}
impl<'de, E> MapDeserializer<'de, E>
where
E: de::Error,
{
fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
MapDeserializer {
iter: map.into_iter(),
value: None,
err: PhantomData,
}
}
}
impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some((key, value)) => {
self.value = Some(value);
seed.deserialize(ContentDeserializer::new(key)).map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.value.take() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
None => Err(de::Error::custom("value is missing")),
}
}
fn size_hint(&self) -> Option<usize> {
size_hint::from_bounds(&self.iter)
}
}
impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_map(self)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
/// Not public API.
pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
content: &'a Content<'de>,
@@ -1820,9 +1684,9 @@ mod content {
E: de::Error,
{
let seq = content.iter().map(ContentRefDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end());
let mut seq_visitor = SeqDeserializer::new(seq);
let value = tri!(visitor.visit_seq(&mut seq_visitor));
tri!(seq_visitor.end());
Ok(value)
}
@@ -1840,9 +1704,9 @@ mod content {
ContentRefDeserializer::new(v),
)
});
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
let mut map_visitor = MapDeserializer::new(map);
let value = tri!(visitor.visit_map(&mut map_visitor));
tri!(map_visitor.end());
Ok(value)
}
@@ -2362,7 +2226,7 @@ mod content {
if len == 0 {
visitor.visit_unit()
} else {
let ret = try!(visitor.visit_seq(&mut self));
let ret = tri!(visitor.visit_seq(&mut self));
let remaining = self.iter.len();
if remaining == 0 {
Ok(ret)
@@ -2541,7 +2405,7 @@ mod content {
where
M: MapAccess<'de>,
{
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
while tri!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
Ok(())
}
}
@@ -2974,3 +2838,55 @@ fn flat_map_take_entry<'de>(
None
}
}
pub struct AdjacentlyTaggedEnumVariantSeed<F> {
pub enum_name: &'static str,
pub variants: &'static [&'static str],
pub fields_enum: PhantomData<F>,
}
pub struct AdjacentlyTaggedEnumVariantVisitor<F> {
enum_name: &'static str,
fields_enum: PhantomData<F>,
}
impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor<F>
where
F: Deserialize<'de>,
{
type Value = F;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "variant of enum {}", self.enum_name)
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (variant, variant_access) = tri!(data.variant());
tri!(variant_access.unit_variant());
Ok(variant)
}
}
impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed<F>
where
F: Deserialize<'de>,
{
type Value = F;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_enum(
self.enum_name,
self.variants,
AdjacentlyTaggedEnumVariantVisitor {
enum_name: self.enum_name,
fields_enum: PhantomData,
},
)
}
}
+2 -2
View File
@@ -1,8 +1,8 @@
// Used only by Serde doc tests. Not public API.
use lib::*;
use crate::lib::*;
use ser;
use crate::ser;
#[doc(hidden)]
#[derive(Debug)]
+11 -13
View File
@@ -3,30 +3,28 @@ pub mod de;
#[cfg(not(no_serde_derive))]
pub mod ser;
pub mod size_hint;
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
pub mod doc;
pub use lib::clone::Clone;
pub use lib::convert::{From, Into};
pub use lib::default::Default;
pub use lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some};
pub use lib::ptr;
pub use lib::result::Result::{self, Err, Ok};
pub use crate::lib::clone::Clone;
pub use crate::lib::convert::{From, Into};
pub use crate::lib::default::Default;
pub use crate::lib::fmt::{self, Formatter};
pub use crate::lib::marker::PhantomData;
pub use crate::lib::option::Option::{self, None, Some};
pub use crate::lib::ptr;
pub use crate::lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::{ToString, Vec};
pub use crate::lib::{ToString, Vec};
#[cfg(not(no_core_try_from))]
pub use lib::convert::TryFrom;
pub use crate::lib::convert::TryFrom;
mod string {
use lib::*;
use crate::lib::*;
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
+141 -66
View File
@@ -1,6 +1,6 @@
use lib::*;
use crate::lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{
@@ -182,14 +182,14 @@ where
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name));
let mut map = tri!(self.delegate.serialize_map(Some(1)));
tri!(map.serialize_entry(self.tag, self.variant_name));
map.end()
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name));
let mut map = tri!(self.delegate.serialize_map(Some(1)));
tri!(map.serialize_entry(self.tag, self.variant_name));
map.end()
}
@@ -199,9 +199,9 @@ where
_: u32,
inner_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, &()));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_entry(inner_variant, &()));
map.end()
}
@@ -226,9 +226,9 @@ where
where
T: Serialize,
{
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, inner_value));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_entry(inner_variant, inner_value));
map.end()
}
@@ -269,9 +269,9 @@ where
inner_variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(
map,
inner_variant,
@@ -280,8 +280,8 @@ where
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name));
let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1)));
tri!(map.serialize_entry(self.tag, self.variant_name));
Ok(map)
}
@@ -290,8 +290,8 @@ where
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
let mut state = tri!(self.delegate.serialize_struct(name, len + 1));
tri!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
@@ -316,9 +316,9 @@ where
inner_variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
let mut map = tri!(self.delegate.serialize_map(Some(2)));
tri!(map.serialize_entry(self.tag, self.variant_name));
tri!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(
map,
inner_variant,
@@ -337,9 +337,9 @@ where
#[cfg(any(feature = "std", feature = "alloc"))]
mod content {
use lib::*;
use crate::lib::*;
use ser::{self, Serialize, Serializer};
use crate::ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> {
map: M,
@@ -368,13 +368,13 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self
tri!(self
.map
.serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end()
@@ -412,13 +412,13 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self
tri!(self
.map
.serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end()
@@ -499,50 +499,50 @@ mod content {
}
Content::Seq(ref elements) => elements.serialize(serializer),
Content::Tuple(ref elements) => {
use ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
use crate::ser::SerializeTuple;
let mut tuple = tri!(serializer.serialize_tuple(elements.len()));
for e in elements {
try!(tuple.serialize_element(e));
tri!(tuple.serialize_element(e));
}
tuple.end()
}
Content::TupleStruct(n, ref fields) => {
use ser::SerializeTupleStruct;
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
use crate::ser::SerializeTupleStruct;
let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len()));
for f in fields {
try!(ts.serialize_field(f));
tri!(ts.serialize_field(f));
}
ts.end()
}
Content::TupleVariant(n, i, v, ref fields) => {
use ser::SerializeTupleVariant;
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
use crate::ser::SerializeTupleVariant;
let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
for f in fields {
try!(tv.serialize_field(f));
tri!(tv.serialize_field(f));
}
tv.end()
}
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
use crate::ser::SerializeMap;
let mut map = tri!(serializer.serialize_map(Some(entries.len())));
for (k, v) in entries {
try!(map.serialize_entry(k, v));
tri!(map.serialize_entry(k, v));
}
map.end()
}
Content::Struct(n, ref fields) => {
use ser::SerializeStruct;
let mut s = try!(serializer.serialize_struct(n, fields.len()));
use crate::ser::SerializeStruct;
let mut s = tri!(serializer.serialize_struct(n, fields.len()));
for &(k, ref v) in fields {
try!(s.serialize_field(k, v));
tri!(s.serialize_field(k, v));
}
s.end()
}
Content::StructVariant(n, i, v, ref fields) => {
use ser::SerializeStructVariant;
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
use crate::ser::SerializeStructVariant;
let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len()));
for &(k, ref v) in fields {
try!(sv.serialize_field(k, v));
tri!(sv.serialize_field(k, v));
}
sv.end()
}
@@ -639,7 +639,7 @@ mod content {
where
T: Serialize,
{
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
}
fn serialize_unit(self) -> Result<Content, E> {
@@ -669,7 +669,7 @@ mod content {
{
Ok(Content::NewtypeStruct(
name,
Box::new(try!(value.serialize(self))),
Box::new(tri!(value.serialize(self))),
))
}
@@ -687,7 +687,7 @@ mod content {
name,
variant_index,
variant,
Box::new(try!(value.serialize(self))),
Box::new(tri!(value.serialize(self))),
))
}
@@ -786,7 +786,7 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
@@ -812,7 +812,7 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
@@ -839,7 +839,7 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
@@ -868,7 +868,7 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
@@ -900,7 +900,7 @@ mod content {
where
T: Serialize,
{
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
@@ -913,7 +913,7 @@ mod content {
.key
.take()
.expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
@@ -927,8 +927,8 @@ mod content {
K: Serialize,
V: Serialize,
{
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
@@ -951,7 +951,7 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
@@ -980,7 +980,7 @@ mod content {
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<E>::new()));
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
@@ -1025,7 +1025,7 @@ where
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
type SerializeMap = FlatMapSerializeMap<'a, M>;
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
@@ -1133,7 +1133,7 @@ where
where
T: Serialize,
{
try!(self.0.serialize_key(variant));
tri!(self.0.serialize_key(variant));
self.0.serialize_value(value)
}
@@ -1157,10 +1157,11 @@ where
self,
_: &'static str,
_: u32,
_: &'static str,
variant: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(Self::bad_type(Unsupported::Enum))
tri!(self.0.serialize_key(variant));
Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0))
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -1182,7 +1183,7 @@ where
inner_variant: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
try!(self.0.serialize_key(inner_variant));
tri!(self.0.serialize_key(inner_variant));
Ok(FlatMapSerializeStructVariantAsMapValue::new(
self.0,
inner_variant,
@@ -1259,6 +1260,52 @@ where
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> {
map: &'a mut M,
fields: Vec<Content>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> FlatMapSerializeTupleVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
fn new(map: &'a mut M) -> Self {
FlatMapSerializeTupleVariantAsMapValue {
map,
fields: Vec::new(),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<(), Self::Error> {
tri!(self.map.serialize_value(&Content::Seq(self.fields)));
Ok(())
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
map: &'a mut M,
@@ -1296,15 +1343,43 @@ where
where
T: Serialize,
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<(), Self::Error> {
try!(self
tri!(self
.map
.serialize_value(&Content::Struct(self.name, self.fields)));
Ok(())
}
}
pub struct AdjacentlyTaggedEnumVariant {
pub enum_name: &'static str,
pub variant_index: u32,
pub variant_name: &'static str,
}
impl Serialize for AdjacentlyTaggedEnumVariant {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name)
}
}
// Error when Serialize for a non_exhaustive remote enum encounters a variant
// that is not recognized.
pub struct CannotSerializeVariant<T>(pub T);
impl<T> Display for CannotSerializeVariant<T>
where
T: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "enum variant cannot be serialized: {:?}", self.0)
}
}
+4 -9
View File
@@ -1,5 +1,5 @@
use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};
use crate::lib::*;
use crate::ser::{Error, Impossible, Serialize, Serializer};
impl Error for fmt::Error {
fn custom<T: Display>(_msg: T) -> Self {
@@ -52,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
serialize_i16: i16,
serialize_i32: i32,
serialize_i64: i64,
serialize_i128: i128,
serialize_u8: u8,
serialize_u16: u16,
serialize_u32: u32,
serialize_u64: u64,
serialize_u128: u128,
serialize_f32: f32,
serialize_f64: f64,
serialize_char: char,
@@ -63,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
serialize_unit_struct: &'static str,
}
serde_if_integer128! {
fmt_primitives! {
serialize_i128: i128,
serialize_u128: u128,
}
}
fn serialize_unit_variant(
self,
_name: &'static str,
+27 -46
View File
@@ -1,6 +1,6 @@
use lib::*;
use crate::lib::*;
use ser::{Error, Serialize, SerializeTuple, Serializer};
use crate::ser::{Error, Serialize, SerializeTuple, Serializer};
////////////////////////////////////////////////////////////////////////////////
@@ -24,20 +24,17 @@ primitive_impl!(i8, serialize_i8);
primitive_impl!(i16, serialize_i16);
primitive_impl!(i32, serialize_i32);
primitive_impl!(i64, serialize_i64);
primitive_impl!(i128, serialize_i128);
primitive_impl!(usize, serialize_u64 as u64);
primitive_impl!(u8, serialize_u8);
primitive_impl!(u16, serialize_u16);
primitive_impl!(u32, serialize_u32);
primitive_impl!(u64, serialize_u64);
primitive_impl!(u128, serialize_u128);
primitive_impl!(f32, serialize_f32);
primitive_impl!(f64, serialize_f64);
primitive_impl!(char, serialize_char);
serde_if_integer128! {
primitive_impl!(i128, serialize_i128);
primitive_impl!(u128, serialize_u128);
}
////////////////////////////////////////////////////////////////////////////////
impl Serialize for str {
@@ -133,7 +130,7 @@ impl<T> Serialize for [T; 0] {
where
S: Serializer,
{
try!(serializer.serialize_tuple(0)).end()
tri!(serializer.serialize_tuple(0)).end()
}
}
@@ -149,9 +146,9 @@ macro_rules! array_impls {
where
S: Serializer,
{
let mut seq = try!(serializer.serialize_tuple($len));
let mut seq = tri!(serializer.serialize_tuple($len));
for e in self {
try!(seq.serialize_element(e));
tri!(seq.serialize_element(e));
}
seq.end()
}
@@ -248,9 +245,9 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Range", 2));
try!(state.serialize_field("start", &self.start));
try!(state.serialize_field("end", &self.end));
let mut state = tri!(serializer.serialize_struct("Range", 2));
tri!(state.serialize_field("start", &self.start));
tri!(state.serialize_field("end", &self.end));
state.end()
}
}
@@ -266,15 +263,14 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeFrom", 1));
try!(state.serialize_field("start", &self.start));
let mut state = tri!(serializer.serialize_struct("RangeFrom", 1));
tri!(state.serialize_field("start", &self.start));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(not(no_range_inclusive))]
impl<Idx> Serialize for RangeInclusive<Idx>
where
Idx: Serialize,
@@ -284,9 +280,9 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
try!(state.serialize_field("start", &self.start()));
try!(state.serialize_field("end", &self.end()));
let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2));
tri!(state.serialize_field("start", &self.start()));
tri!(state.serialize_field("end", &self.end()));
state.end()
}
}
@@ -302,15 +298,14 @@ where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeTo", 1));
try!(state.serialize_field("end", &self.end));
let mut state = tri!(serializer.serialize_struct("RangeTo", 1));
tri!(state.serialize_field("end", &self.end));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<T> Serialize for Bound<T>
where
T: Serialize,
@@ -367,9 +362,9 @@ macro_rules! tuple_impls {
where
S: Serializer,
{
let mut tuple = try!(serializer.serialize_tuple($len));
let mut tuple = tri!(serializer.serialize_tuple($len));
$(
try!(tuple.serialize_element(&self.$n));
tri!(tuple.serialize_element(&self.$n));
)+
tuple.end()
}
@@ -538,7 +533,6 @@ where
macro_rules! nonzero_integers {
($($T:ident,)+) => {
$(
#[cfg(not(no_num_nonzero))]
impl Serialize for num::$T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -556,6 +550,7 @@ nonzero_integers! {
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroU128,
NonZeroUsize,
}
@@ -565,22 +560,10 @@ nonzero_integers! {
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroI128,
NonZeroIsize,
}
// Currently 128-bit integers do not work on Emscripten targets so we need an
// additional `#[cfg]`
serde_if_integer128! {
nonzero_integers! {
NonZeroU128,
}
#[cfg(not(no_num_nonzero_signed))]
nonzero_integers! {
NonZeroI128,
}
}
impl<T> Serialize for Cell<T>
where
T: Serialize + Copy,
@@ -662,16 +645,15 @@ where
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", not(no_core_duration)))]
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Duration", 2));
try!(state.serialize_field("secs", &self.as_secs()));
try!(state.serialize_field("nanos", &self.subsec_nanos()));
let mut state = tri!(serializer.serialize_struct("Duration", 2));
tri!(state.serialize_field("secs", &self.as_secs()));
tri!(state.serialize_field("nanos", &self.subsec_nanos()));
state.end()
}
}
@@ -689,9 +671,9 @@ impl Serialize for SystemTime {
Ok(duration_since_epoch) => duration_since_epoch,
Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")),
};
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
let mut state = tri!(serializer.serialize_struct("SystemTime", 2));
tri!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
tri!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
state.end()
}
}
@@ -963,7 +945,6 @@ where
}
}
#[cfg(not(no_core_reverse))]
impl<T> Serialize for Reverse<T>
where
T: Serialize,
+2 -2
View File
@@ -1,8 +1,8 @@
//! This module contains `Impossible` serializer and its implementations.
use lib::*;
use crate::lib::*;
use ser::{
use crate::ser::{
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
};
+54 -86
View File
@@ -107,7 +107,7 @@
//! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats
use lib::*;
use crate::lib::*;
mod fmt;
mod impls;
@@ -115,15 +115,15 @@ mod impossible;
pub use self::impossible::Impossible;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use crate::std_error::Error as StdError;
#[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(inline)]
#[doc(no_inline)]
pub use core::error::Error as StdError;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
////////////////////////////////////////////////////////////////////////////////
@@ -488,30 +488,27 @@ pub trait Serializer: Sized {
/// ```
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize an `i128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i128(*self)
/// }
/// }
/// ```
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("i128 is not supported"))
}
/// Serialize an `i128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i128(*self)
/// }
/// }
/// ```
///
/// The default behavior unconditionally returns an error.
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("i128 is not supported"))
}
/// Serialize a `u8` value.
@@ -598,30 +595,27 @@ pub trait Serializer: Sized {
/// ```
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! {
/// Serialize a `u128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u128(*self)
/// }
/// }
/// ```
///
/// This method is available only on Rust compiler versions >=1.26. The
/// default behavior unconditionally returns an error.
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("u128 is not supported"))
}
/// Serialize a `u128` value.
///
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
/// #
/// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u128(*self)
/// }
/// }
/// ```
///
/// The default behavior unconditionally returns an error.
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
let _ = v;
Err(Error::custom("u128 is not supported"))
}
/// Serialize an `f32` value.
@@ -1279,22 +1273,9 @@ pub trait Serializer: Sized {
I: IntoIterator,
<I as IntoIterator>::Item: Serialize,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter)));
#[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|item| serializer.serialize_element(&item)));
}
#[cfg(no_iterator_try_fold)]
{
for item in iter {
try!(serializer.serialize_element(&item));
}
}
let mut iter = iter.into_iter();
let mut serializer = tri!(self.serialize_seq(iterator_len_hint(&iter)));
tri!(iter.try_for_each(|item| serializer.serialize_element(&item)));
serializer.end()
}
@@ -1330,22 +1311,9 @@ pub trait Serializer: Sized {
V: Serialize,
I: IntoIterator<Item = (K, V)>,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter)));
#[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
}
#[cfg(no_iterator_try_fold)]
{
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
}
let mut iter = iter.into_iter();
let mut serializer = tri!(self.serialize_map(iterator_len_hint(&iter)));
tri!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
serializer.end()
}
@@ -1839,7 +1807,7 @@ pub trait SerializeMap {
K: Serialize,
V: Serialize,
{
try!(self.serialize_key(key));
tri!(self.serialize_key(key));
self.serialize_value(value)
}
+1 -1
View File
@@ -1,4 +1,4 @@
use lib::{Debug, Display};
use crate::lib::{Debug, Display};
/// Either a re-export of std::error::Error or a new identical trait, depending
/// on whether Serde's "std" feature is enabled.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.175" # remember to update html_root_url
version = "1.0.189" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -23,7 +23,7 @@ proc-macro = true
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = "2.0.25"
syn = "2.0.28"
[dev-dependencies]
serde = { version = "1", path = "../serde" }
+5 -8
View File
@@ -1,12 +1,9 @@
use std::collections::HashSet;
use syn;
use syn::punctuated::{Pair, Punctuated};
use internals::ast::{Container, Data};
use internals::{attr, ungroup};
use crate::internals::ast::{Container, Data};
use crate::internals::{attr, ungroup};
use proc_macro2::Span;
use std::collections::HashSet;
use syn::punctuated::{Pair, Punctuated};
use syn::Token;
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
+243 -290
View File
@@ -1,21 +1,14 @@
use crate::fragment::{Expr, Fragment, Match, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use crate::{bound, dummy, pretend, this};
use proc_macro2::{Literal, Span, TokenStream};
use quote::ToTokens;
#[cfg(precompiled)]
use std::sync::atomic::Ordering;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{self, Ident, Index, Member};
use bound;
use dummy;
use fragment::{Expr, Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use pretend;
use this;
use quote::{quote, quote_spanned, ToTokens};
use std::collections::BTreeSet;
use std::ptr;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{parse_quote, Ident, Index, Member};
pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
replace_receiver(input);
@@ -306,11 +299,6 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
#[cfg(feature = "deserialize_in_place")]
fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<Stmts> {
#[cfg(precompiled)]
if !crate::DESERIALIZE_IN_PLACE.load(Ordering::Relaxed) {
return None;
}
// Only remote derives have getters, and we do not generate
// deserialize_in_place for remote derives.
assert!(!params.has_getter);
@@ -329,10 +317,10 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
let code = match &cont.data {
Data::Struct(Style::Struct, fields) => {
deserialize_struct_in_place(None, params, fields, &cont.attrs, None)?
deserialize_struct_in_place(params, fields, &cont.attrs)?
}
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
deserialize_tuple_in_place(None, params, fields, &cont.attrs, None)
deserialize_tuple_in_place(params, fields, &cont.attrs)
}
Data::Enum(_) | Data::Struct(Style::Unit, _) => {
return None;
@@ -587,11 +575,9 @@ fn deserialize_tuple(
#[cfg(feature = "deserialize_in_place")]
fn deserialize_tuple_in_place(
variant_ident: Option<syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
deserializer: Option<TokenStream>,
) -> Fragment {
assert!(!cattrs.has_flatten());
@@ -605,17 +591,25 @@ fn deserialize_tuple_in_place(
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let is_enum = variant_ident.is_some();
let expecting = match variant_ident {
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
None => format!("tuple struct {}", params.type_name()),
};
let expecting = format!("tuple struct {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
let nfields = fields.len();
let visit_newtype_struct = if !is_enum && nfields == 1 {
Some(deserialize_newtype_struct_in_place(params, &fields[0]))
let visit_newtype_struct = if nfields == 1 {
// We do not generate deserialize_in_place if every field has a
// deserialize_with.
assert!(fields[0].attrs.deserialize_with().is_none());
Some(quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
})
} else {
None
};
@@ -629,15 +623,10 @@ fn deserialize_tuple_in_place(
}
};
let dispatch = if let Some(deserializer) = deserializer {
quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr))
} else if is_enum {
quote!(_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr))
} else if nfields == 1 {
let type_name = cattrs.name().deserialize_name();
let type_name = cattrs.name().deserialize_name();
let dispatch = if nfields == 1 {
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
} else {
let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr))
};
@@ -715,31 +704,23 @@ fn deserialize_seq(
let span = field.original.span();
let func =
quote_spanned!(span=> _serde::de::SeqAccess::next_element::<#field_ty>);
quote!(try!(#func(&mut __seq)))
quote!(#func(&mut __seq)?)
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
_serde::__private::Option::map(
try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)),
_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)?,
|__wrap| __wrap.value)
})
}
};
let value_if_none = match field.attrs.default() {
attr::Default::Default => quote!(_serde::__private::Default::default()),
attr::Default::Path(path) => quote!(#path()),
attr::Default::None => quote!(
return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
),
};
let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting);
let assign = quote! {
let #var = match #visit {
_serde::__private::Some(__value) => __value,
_serde::__private::None => {
#value_if_none
}
_serde::__private::None => #value_if_none,
};
};
index_in_seq += 1;
@@ -815,24 +796,14 @@ fn deserialize_seq_in_place(
self.place.#member = #default;
}
} else {
let value_if_none = match field.attrs.default() {
attr::Default::Default => quote!(
self.place.#member = _serde::__private::Default::default();
),
attr::Default::Path(path) => quote!(
self.place.#member = #path();
),
attr::Default::None => quote!(
return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
),
};
let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting);
let write = match field.attrs.deserialize_with() {
None => {
quote! {
if let _serde::__private::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.#member)))
if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.#member))?
{
#value_if_none
#value_if_none;
}
}
}
@@ -840,12 +811,12 @@ fn deserialize_seq_in_place(
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
match _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)? {
_serde::__private::Some(__wrap) => {
self.place.#member = __wrap.value;
}
_serde::__private::None => {
#value_if_none
#value_if_none;
}
}
})
@@ -892,12 +863,12 @@ fn deserialize_newtype_struct(
let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote! {
try!(#func(__e))
#func(__e)?
}
}
Some(path) => {
quote! {
try!(#path(__e))
#path(__e)?
}
}
};
@@ -923,25 +894,6 @@ fn deserialize_newtype_struct(
}
}
#[cfg(feature = "deserialize_in_place")]
fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> TokenStream {
// We do not generate deserialize_in_place if every field has a
// deserialize_with.
assert!(field.attrs.deserialize_with().is_none());
let delife = params.borrowed.de_lifetime();
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
}
}
enum StructForm<'a> {
Struct,
/// Contains a variant name
@@ -1006,12 +958,7 @@ fn deserialize_struct(
)
})
.collect();
let field_visitor = Stmts(deserialize_generated_identifier(
&field_names_idents,
cattrs,
false,
None,
));
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
// untagged struct variants do not get a visit_seq method. The same applies to
// structs that only have a map representation.
@@ -1063,7 +1010,7 @@ fn deserialize_struct(
} else {
let field_names = field_names_idents
.iter()
.flat_map(|(_, _, aliases)| aliases);
.flat_map(|&(_, _, aliases)| aliases);
Some(quote! {
#[doc(hidden)]
@@ -1138,14 +1085,10 @@ fn deserialize_struct(
#[cfg(feature = "deserialize_in_place")]
fn deserialize_struct_in_place(
variant_ident: Option<syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
deserializer: Option<TokenStream>,
) -> Option<Fragment> {
let is_enum = variant_ident.is_some();
// for now we do not support in_place deserialization for structs that
// are represented as map.
if cattrs.has_flatten() {
@@ -1157,58 +1100,35 @@ fn deserialize_struct_in_place(
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let expecting = match variant_ident {
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
None => format!("struct {}", params.type_name()),
};
let expecting = format!("struct {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let (field_visitor, fields_stmt, visit_map) =
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
let field_visitor = Stmts(field_visitor);
let fields_stmt = Stmts(fields_stmt);
let visit_map = Stmts(visit_map);
let visitor_expr = quote! {
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
}
};
let dispatch = if let Some(deserializer) = deserializer {
quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
}
} else if is_enum {
quote! {
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
}
} else {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
}
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
let visitor_var = if all_skipped {
let mut_seq = if field_names_idents.is_empty() {
quote!(_)
} else {
quote!(mut __seq)
};
let visit_seq = quote! {
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
};
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
let field_names = field_names_idents
.iter()
.flat_map(|&(_, _, aliases)| aliases);
let type_name = cattrs.name().deserialize_name();
let in_place_impl_generics = de_impl_generics.in_place();
let in_place_ty_generics = de_ty_generics.in_place();
@@ -1230,7 +1150,13 @@ fn deserialize_struct_in_place(
_serde::__private::Formatter::write_str(__formatter, #expecting)
}
#visit_seq
#[inline]
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
#[inline]
fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result<Self::Value, __A::Error>
@@ -1241,9 +1167,13 @@ fn deserialize_struct_in_place(
}
}
#fields_stmt
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
#dispatch
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
})
})
}
@@ -1300,7 +1230,12 @@ fn prepare_enum_variant_enum(
})
.collect();
let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other());
let fallthrough = deserialized_variants
.position(|(_, variant)| variant.attrs.other())
.map(|other_idx| {
let ignore_variant = variant_names_idents[other_idx].1.clone();
quote!(_serde::__private::Ok(__Field::#ignore_variant))
});
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
@@ -1314,7 +1249,8 @@ fn prepare_enum_variant_enum(
&variant_names_idents,
cattrs,
true,
other_idx,
None,
fallthrough,
));
(variants_stmt, variant_visitor)
@@ -1369,7 +1305,7 @@ fn deserialize_externally_tagged_enum(
}
} else {
quote! {
match try!(_serde::de::EnumAccess::variant(__data)) {
match _serde::de::EnumAccess::variant(__data)? {
#(#variant_arms)*
}
}
@@ -1449,9 +1385,9 @@ fn deserialize_internally_tagged_enum(
#variants_stmt
let (__tag, __content) = try!(_serde::Deserializer::deserialize_any(
let (__tag, __content) = _serde::Deserializer::deserialize_any(
__deserializer,
_serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting)));
_serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?;
let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content);
match __tag {
@@ -1495,7 +1431,8 @@ fn deserialize_adjacently_tagged_enum(
})
.collect();
let expecting = format!("adjacently tagged enum {}", params.type_name());
let rust_name = params.type_name();
let expecting = format!("adjacently tagged enum {}", rust_name);
let expecting = cattrs.expecting().unwrap_or(&expecting);
let type_name = cattrs.name().deserialize_name();
let deny_unknown_fields = cattrs.deny_unknown_fields();
@@ -1515,6 +1452,14 @@ fn deserialize_adjacently_tagged_enum(
}
};
let variant_seed = quote! {
_serde::__private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
enum_name: #rust_name,
variants: VARIANTS,
fields_enum: _serde::__private::PhantomData
}
};
let mut missing_content = quote! {
_serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
};
@@ -1559,7 +1504,11 @@ fn deserialize_adjacently_tagged_enum(
// Advance the map by one key, returning early in case of error.
let next_key = quote! {
try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content))
_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)?
};
let variant_from_map = quote! {
_serde::de::MapAccess::next_value_seed(&mut __map, #variant_seed)?
};
// When allowing unknown fields, we want to transparently step through keys
@@ -1572,7 +1521,7 @@ fn deserialize_adjacently_tagged_enum(
while let _serde::__private::Some(__k) = #next_key {
match __k {
_serde::__private::de::TagContentOtherField::Other => {
let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
continue;
},
_serde::__private::de::TagContentOtherField::Tag => {
@@ -1607,14 +1556,14 @@ fn deserialize_adjacently_tagged_enum(
let finish_content_then_tag = if variant_arms.is_empty() {
quote! {
match try!(_serde::de::MapAccess::next_value::<__Field>(&mut __map)) {}
match #variant_from_map {}
}
} else {
quote! {
let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) {
let __ret = match #variant_from_map {
// Deserialize the buffered content now that we know the variant.
#(#variant_arms)*
});
}?;
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
}
@@ -1667,7 +1616,7 @@ fn deserialize_adjacently_tagged_enum(
// First key is the tag.
_serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => {
// Parse the tag.
let __field = try!(_serde::de::MapAccess::next_value(&mut __map));
let __field = #variant_from_map;
// Visit the second key.
match #next_relevant_key {
// Second key is a duplicate of the tag.
@@ -1676,12 +1625,12 @@ fn deserialize_adjacently_tagged_enum(
}
// Second key is the content.
_serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => {
let __ret = try!(_serde::de::MapAccess::next_value_seed(&mut __map,
let __ret = _serde::de::MapAccess::next_value_seed(&mut __map,
__Seed {
field: __field,
marker: _serde::__private::PhantomData,
lifetime: _serde::__private::PhantomData,
}));
})?;
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
}
@@ -1692,7 +1641,7 @@ fn deserialize_adjacently_tagged_enum(
// First key is the content.
_serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => {
// Buffer up the content.
let __content = try!(_serde::de::MapAccess::next_value::<_serde::__private::de::Content>(&mut __map));
let __content = _serde::de::MapAccess::next_value::<_serde::__private::de::Content>(&mut __map)?;
// Visit the second key.
match #next_relevant_key {
// Second key is the tag.
@@ -1722,17 +1671,17 @@ fn deserialize_adjacently_tagged_enum(
__A: _serde::de::SeqAccess<#delife>,
{
// Visit the first element - the tag.
match try!(_serde::de::SeqAccess::next_element(&mut __seq)) {
match _serde::de::SeqAccess::next_element(&mut __seq)? {
_serde::__private::Some(__field) => {
// Visit the second element - the content.
match try!(_serde::de::SeqAccess::next_element_seed(
match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
__Seed {
field: __field,
marker: _serde::__private::PhantomData,
lifetime: _serde::__private::PhantomData,
},
)) {
)? {
_serde::__private::Some(__ret) => _serde::__private::Ok(__ret),
// There is no second element.
_serde::__private::None => {
@@ -1788,7 +1737,6 @@ fn deserialize_untagged_enum_after(
quote!(__deserializer),
))
});
let attempts = first_attempt.into_iter().chain(attempts);
// TODO this message could be better by saving the errors from the failed
// attempts. The heuristic used by TOML was to count the number of fields
// processed before an error, and use the error that happened after the
@@ -1801,10 +1749,23 @@ fn deserialize_untagged_enum_after(
);
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
// Ignore any error associated with non-untagged deserialization so that we
// can fall through to the untagged variants. This may be infallible so we
// need to provide the error type.
let first_attempt = first_attempt.map(|expr| {
quote! {
if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| #expr)() {
return _serde::__private::Ok(__ok);
}
}
});
quote_block! {
let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer));
let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
#first_attempt
#(
if let _serde::__private::Ok(__ok) = #attempts {
return _serde::__private::Ok(__ok);
@@ -1835,7 +1796,7 @@ fn deserialize_externally_tagged_variant(
Style::Unit => {
let this_value = &params.this_value;
quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant));
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private::Ok(#this_value::#variant_ident)
}
}
@@ -1884,7 +1845,7 @@ fn deserialize_internally_tagged_variant(
quote!((#default))
});
quote_block! {
try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?;
_serde::__private::Ok(#this_value::#variant_ident #default)
}
}
@@ -1970,7 +1931,7 @@ fn deserialize_externally_tagged_newtype_variant(
if field.attrs.skip_deserializing() {
let default = Expr(expr_is_missing(field, cattrs));
return quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant));
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private::Ok(#this_value::#variant_ident(#default))
};
}
@@ -2023,30 +1984,15 @@ fn deserialize_untagged_newtype_variant(
}
fn deserialize_generated_identifier(
fields: &[(String, Ident, Vec<String>)],
fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container,
is_variant: bool,
other_idx: Option<usize>,
ignore_variant: Option<TokenStream>,
fallthrough: Option<TokenStream>,
) -> Fragment {
let this_value = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
(Some(ignore_variant), Some(fallthrough))
} else if let Some(other_idx) = other_idx {
let ignore_variant = fields[other_idx].1.clone();
let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant));
(None, Some(fallthrough))
} else if is_variant || cattrs.deny_unknown_fields() {
(None, None)
} else {
let ignore_variant = quote!(__ignore,);
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
(Some(ignore_variant), Some(fallthrough))
};
let visitor_impl = Stmts(deserialize_identifier(
&this_value,
fields,
@@ -2092,6 +2038,33 @@ fn deserialize_generated_identifier(
}
}
/// Generates enum and its `Deserialize` implementation that represents each
/// non-skipped field of the struct
fn deserialize_field_identifier(
fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container,
) -> Stmts {
let (ignore_variant, fallthrough) = if cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
(Some(ignore_variant), Some(fallthrough))
} else if cattrs.deny_unknown_fields() {
(None, None)
} else {
let ignore_variant = quote!(__ignore,);
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
(Some(ignore_variant), Some(fallthrough))
};
Stmts(deserialize_generated_identifier(
fields,
cattrs,
false,
ignore_variant,
fallthrough,
))
}
// Generates `Deserialize::deserialize` body for an enum with
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
fn deserialize_custom_identifier(
@@ -2153,7 +2126,7 @@ fn deserialize_custom_identifier(
})
.collect();
let names = names_idents.iter().map(|(name, _, _)| name);
let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases);
let names_const = if fallthrough.is_some() {
None
@@ -2209,32 +2182,24 @@ fn deserialize_custom_identifier(
fn deserialize_identifier(
this_value: &TokenStream,
fields: &[(String, Ident, Vec<String>)],
fields: &[(&str, Ident, &BTreeSet<String>)],
is_variant: bool,
fallthrough: Option<TokenStream>,
fallthrough_borrowed: Option<TokenStream>,
collect_other_fields: bool,
expecting: Option<&str>,
) -> Fragment {
let mut flat_fields = Vec::new();
for (_, ident, aliases) in fields {
flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));
}
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
let field_bytes: &Vec<_> = &flat_fields
.iter()
.map(|(name, _)| Literal::byte_string(name.as_bytes()))
.collect();
let constructors: &Vec<_> = &flat_fields
.iter()
.map(|(_, ident)| quote!(#this_value::#ident))
.collect();
let main_constructors: &Vec<_> = &fields
.iter()
.map(|(_, ident, _)| quote!(#this_value::#ident))
.collect();
let str_mapping = fields.iter().map(|(_, ident, aliases)| {
// `aliases` also contains a main name
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
});
let bytes_mapping = fields.iter().map(|(_, ident, aliases)| {
// `aliases` also contains a main name
let aliases = aliases
.iter()
.map(|alias| Literal::byte_string(alias.as_bytes()));
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
});
let expecting = expecting.unwrap_or(if is_variant {
"variant identifier"
@@ -2242,8 +2207,6 @@ fn deserialize_identifier(
"field identifier"
});
let index_expecting = if is_variant { "variant" } else { "field" };
let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
None
} else {
@@ -2291,21 +2254,6 @@ fn deserialize_identifier(
&fallthrough_arm_tokens
};
let u64_fallthrough_arm_tokens;
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
fallthrough
} else {
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
u64_fallthrough_arm_tokens = quote! {
_serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
};
&u64_fallthrough_arm_tokens
};
let variant_indices = 0_u64..;
let visit_other = if collect_other_fields {
quote! {
fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E>
@@ -2400,15 +2348,33 @@ fn deserialize_identifier(
}
}
} else {
let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| {
let i = i as u64;
quote!(#i => _serde::__private::Ok(#this_value::#ident))
});
let u64_fallthrough_arm_tokens;
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
fallthrough
} else {
let index_expecting = if is_variant { "variant" } else { "field" };
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
u64_fallthrough_arm_tokens = quote! {
_serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
};
&u64_fallthrough_arm_tokens
};
quote! {
fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(
#variant_indices => _serde::__private::Ok(#main_constructors),
)*
#(#u64_mapping,)*
_ => #u64_fallthrough_arm,
}
}
@@ -2416,6 +2382,8 @@ fn deserialize_identifier(
};
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
let str_mapping = str_mapping.clone();
let bytes_mapping = bytes_mapping.clone();
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
Some(quote! {
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
@@ -2423,9 +2391,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(
#field_strs => _serde::__private::Ok(#constructors),
)*
#(#str_mapping,)*
_ => {
#value_as_borrowed_str_content
#fallthrough_borrowed_arm
@@ -2438,9 +2404,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(
#field_bytes => _serde::__private::Ok(#constructors),
)*
#(#bytes_mapping,)*
_ => {
#bytes_to_str
#value_as_borrowed_bytes_content
@@ -2465,9 +2429,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(
#field_strs => _serde::__private::Ok(#constructors),
)*
#(#str_mapping,)*
_ => {
#value_as_str_content
#fallthrough_arm
@@ -2480,9 +2442,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(
#field_bytes => _serde::__private::Ok(#constructors),
)*
#(#bytes_mapping,)*
_ => {
#bytes_to_str
#value_as_bytes_content
@@ -2545,7 +2505,7 @@ fn deserialize_map(
let func =
quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>);
quote! {
try!(#func(&mut __map))
#func(&mut __map)?
}
}
Some(path) => {
@@ -2577,14 +2537,14 @@ fn deserialize_map(
__Field::__other(__name) => {
__collect.push(_serde::__private::Some((
__name,
try!(_serde::de::MapAccess::next_value(&mut __map)))));
_serde::de::MapAccess::next_value(&mut __map)?)));
}
})
} else if cattrs.deny_unknown_fields() {
None
} else {
Some(quote! {
_ => { let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); }
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
})
};
@@ -2592,14 +2552,14 @@ fn deserialize_map(
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
quote! {
// FIXME: Once feature(exhaustive_patterns) is stable:
// let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map));
// let _serde::__private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
_serde::__private::Option::map(
try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)),
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|__impossible| match __impossible {});
}
} else {
quote! {
while let _serde::__private::Some(__key) = try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)) {
while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
#(#value_arms)*
#ignored_arm
@@ -2635,10 +2595,10 @@ fn deserialize_map(
Some(path) => quote!(#path),
};
quote! {
let #name: #field_ty = try!(#func(
let #name: #field_ty = #func(
_serde::__private::de::FlatMapDeserializer(
&mut __collect,
_serde::__private::PhantomData)));
_serde::__private::PhantomData))?;
}
});
@@ -2712,42 +2672,6 @@ fn deserialize_map(
}
}
#[cfg(feature = "deserialize_in_place")]
fn deserialize_struct_as_struct_in_place_visitor(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> (Fragment, Fragment, Fragment) {
assert!(!cattrs.has_flatten());
let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let fields_stmt = {
let field_names = field_names_idents.iter().map(|(name, _, _)| name);
quote_block! {
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
};
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
let visit_map = deserialize_map_in_place(params, fields, cattrs);
(field_visitor, fields_stmt, visit_map)
}
#[cfg(feature = "deserialize_in_place")]
fn deserialize_map_in_place(
params: &Parameters,
@@ -2785,7 +2709,7 @@ fn deserialize_map_in_place(
let visit = match field.attrs.deserialize_with() {
None => {
quote! {
try!(_serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::InPlaceSeed(&mut self.place.#member)))
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::InPlaceSeed(&mut self.place.#member))?
}
}
Some(path) => {
@@ -2817,7 +2741,7 @@ fn deserialize_map_in_place(
None
} else {
Some(quote! {
_ => { let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); }
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
})
};
@@ -2826,14 +2750,14 @@ fn deserialize_map_in_place(
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
quote! {
// FIXME: Once feature(exhaustive_patterns) is stable:
// let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map));
// let _serde::__private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
_serde::__private::Option::map(
try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)),
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|__impossible| match __impossible {});
}
} else {
quote! {
while let _serde::__private::Some(__key) = try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)) {
while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
#(#value_arms_from)*
#ignored_arm
@@ -2930,7 +2854,7 @@ fn wrap_deserialize_with(
__D: _serde::Deserializer<#delife>,
{
_serde::__private::Ok(__DeserializeWith {
value: try!(#deserialize_with(__deserializer)),
value: #deserialize_with(__deserializer)?,
phantom: _serde::__private::PhantomData,
lifetime: _serde::__private::PhantomData,
})
@@ -3040,7 +2964,7 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
let span = field.original.span();
let func = quote_spanned!(span=> _serde::__private::de::missing_field);
quote_expr! {
try!(#func(#name))
#func(#name)?
}
}
Some(_) => {
@@ -3051,6 +2975,35 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
}
}
fn expr_is_missing_seq(
assign_to: Option<TokenStream>,
index: usize,
field: &Field,
cattrs: &attr::Container,
expecting: &str,
) -> TokenStream {
match field.attrs.default() {
attr::Default::Default => {
let span = field.original.span();
return quote_spanned!(span=> #assign_to _serde::__private::Default::default());
}
attr::Default::Path(path) => {
return quote_spanned!(path.span()=> #assign_to #path());
}
attr::Default::None => { /* below */ }
}
match *cattrs.default() {
attr::Default::Default | attr::Default::Path(_) => {
let member = &field.member;
quote!(#assign_to __default.#member)
}
attr::Default::None => quote!(
return _serde::__private::Err(_serde::de::Error::invalid_length(#index, &#expecting))
),
}
}
fn effective_style(variant: &Variant) -> Style {
match variant.style {
Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit,
+1 -6
View File
@@ -1,11 +1,7 @@
use proc_macro2::TokenStream;
use syn;
use try;
use quote::quote;
pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream {
let try_replacement = try::replacement();
let use_serde = match serde_path {
Some(path) => quote! {
use #path as _serde;
@@ -21,7 +17,6 @@ pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> Token
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#use_serde
#try_replacement
#code
};
}
+1 -1
View File
@@ -1,6 +1,6 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::token;
use syn::{token, Token};
pub enum Fragment {
/// Tokens that can be used as an expression.
+9 -8
View File
@@ -1,10 +1,8 @@
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
use internals::attr;
use internals::check;
use internals::{Ctxt, Derive};
use syn;
use crate::internals::{attr, check, Ctxt, Derive};
use syn::punctuated::Punctuated;
use syn::Token;
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
/// parsed into an internal representation.
@@ -88,9 +86,12 @@ impl<'a> Container<'a> {
if field.attrs.flatten() {
has_flatten = true;
}
field
.attrs
.rename_by_rules(variant.attrs.rename_all_rules());
field.attrs.rename_by_rules(
variant
.attrs
.rename_all_rules()
.or(attrs.rename_all_fields_rules()),
);
}
}
}
@@ -121,7 +122,7 @@ impl<'a> Container<'a> {
}
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a Field<'a>> + 'a> {
match self {
Data::Enum(variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
+135 -69
View File
@@ -1,15 +1,14 @@
use internals::symbol::*;
use internals::{ungroup, Ctxt};
use crate::internals::symbol::*;
use crate::internals::{ungroup, Ctxt};
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
use quote::ToTokens;
use std::borrow::Cow;
use std::collections::BTreeSet;
use std::iter::FromIterator;
use syn;
use syn::meta::ParseNestedMeta;
use syn::parse::ParseStream;
use syn::punctuated::Punctuated;
use syn::{token, Ident, Lifetime};
use syn::{parse_quote, token, Ident, Lifetime, Token};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
@@ -19,7 +18,7 @@ use syn::{token, Ident, Lifetime};
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
pub use internals::case::RenameRule;
pub use crate::internals::case::RenameRule;
struct Attr<'c, T> {
cx: &'c Ctxt,
@@ -135,7 +134,7 @@ pub struct Name {
serialize_renamed: bool,
deserialize: String,
deserialize_renamed: bool,
deserialize_aliases: Vec<String>,
deserialize_aliases: BTreeSet<String>,
}
fn unraw(ident: &Ident) -> String {
@@ -149,16 +148,12 @@ impl Name {
de_name: Attr<String>,
de_aliases: Option<VecAttr<String>>,
) -> Name {
let deserialize_aliases = match de_aliases {
Some(de_aliases) => {
let mut alias_list = BTreeSet::new();
for alias_name in de_aliases.get() {
alias_list.insert(alias_name);
}
alias_list.into_iter().collect()
let mut alias_set = BTreeSet::new();
if let Some(de_aliases) = de_aliases {
for alias_name in de_aliases.get() {
alias_set.insert(alias_name);
}
None => Vec::new(),
};
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
@@ -169,35 +164,42 @@ impl Name {
serialize_renamed: ser_renamed,
deserialize: de_name.unwrap_or(source_name),
deserialize_renamed: de_renamed,
deserialize_aliases,
deserialize_aliases: alias_set,
}
}
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String {
self.serialize.clone()
pub fn serialize_name(&self) -> &str {
&self.serialize
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
pub fn deserialize_name(&self) -> &str {
&self.deserialize
}
fn deserialize_aliases(&self) -> Vec<String> {
let mut aliases = self.deserialize_aliases.clone();
let main_name = self.deserialize_name();
if !aliases.contains(&main_name) {
aliases.push(main_name);
}
aliases
fn deserialize_aliases(&self) -> &BTreeSet<String> {
&self.deserialize_aliases
}
}
#[derive(Copy, Clone)]
pub struct RenameAllRules {
serialize: RenameRule,
deserialize: RenameRule,
}
impl RenameAllRules {
/// Returns a new `RenameAllRules` with the individual rules of `self` and
/// `other_rules` joined by `RenameRules::or`.
pub fn or(self, other_rules: Self) -> Self {
Self {
serialize: self.serialize.or(other_rules.serialize),
deserialize: self.deserialize.or(other_rules.deserialize),
}
}
}
/// Represents struct or enum attribute information.
pub struct Container {
name: Name,
@@ -205,6 +207,7 @@ pub struct Container {
deny_unknown_fields: bool,
default: Default,
rename_all_rules: RenameAllRules,
rename_all_fields_rules: RenameAllRules,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
tag: TagType,
@@ -218,6 +221,7 @@ pub struct Container {
is_packed: bool,
/// Error message generated when type can't be deserialized
expecting: Option<String>,
non_exhaustive: bool,
}
/// Styles of representing an enum.
@@ -288,6 +292,8 @@ impl Container {
let mut default = Attr::none(cx, DEFAULT);
let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL);
let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL);
let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS);
let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS);
let mut ser_bound = Attr::none(cx, BOUND);
let mut de_bound = Attr::none(cx, BOUND);
let mut untagged = BoolAttr::none(cx, UNTAGGED);
@@ -301,9 +307,12 @@ impl Container {
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
let mut serde_path = Attr::none(cx, CRATE);
let mut expecting = Attr::none(cx, EXPECTING);
let mut non_exhaustive = false;
for attr in &item.attrs {
if attr.path() != SERDE {
non_exhaustive |=
matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE);
continue;
}
@@ -341,6 +350,44 @@ impl Container {
}
}
}
} else if meta.path == RENAME_ALL_FIELDS {
// #[serde(rename_all_fields = "foo")]
// #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))]
let one_name = meta.input.peek(Token![=]);
let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?;
match item.data {
syn::Data::Enum(_) => {
if let Some(ser) = ser {
match RenameRule::from_str(&ser.value()) {
Ok(rename_rule) => {
rename_all_fields_ser_rule.set(&meta.path, rename_rule);
}
Err(err) => cx.error_spanned_by(ser, err),
}
}
if let Some(de) = de {
match RenameRule::from_str(&de.value()) {
Ok(rename_rule) => {
rename_all_fields_de_rule.set(&meta.path, rename_rule);
}
Err(err) => {
if !one_name {
cx.error_spanned_by(de, err);
}
}
}
}
}
syn::Data::Struct(_) => {
let msg = "#[serde(rename_all_fields)] can only be used on enums";
cx.syn_error(meta.error(msg));
}
syn::Data::Union(_) => {
let msg = "#[serde(rename_all_fields)] can only be used on enums";
cx.syn_error(meta.error(msg));
}
}
} else if meta.path == TRANSPARENT {
// #[serde(transparent)]
transparent.set_true(meta.path);
@@ -353,21 +400,21 @@ impl Container {
if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
match &item.data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => {
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
default.set(&meta.path, Default::Path(path));
}
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
cx.error_spanned_by(fields, msg);
syn::Fields::Unit => {
let msg = "#[serde(default = \"...\")] can only be used on structs that have fields";
cx.syn_error(meta.error(msg));
}
},
syn::Data::Enum(syn::DataEnum { enum_token, .. }) => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
cx.error_spanned_by(enum_token, msg);
syn::Data::Enum(_) => {
let msg = "#[serde(default = \"...\")] can only be used on structs";
cx.syn_error(meta.error(msg));
}
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
cx.error_spanned_by(union_token, msg);
syn::Data::Union(_) => {
let msg = "#[serde(default = \"...\")] can only be used on structs";
cx.syn_error(meta.error(msg));
}
}
}
@@ -375,21 +422,21 @@ impl Container {
// #[serde(default)]
match &item.data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => {
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
default.set(meta.path, Default::Default);
}
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
let msg = "#[serde(default)] can only be used on structs with named fields";
syn::Fields::Unit => {
let msg = "#[serde(default)] can only be used on structs that have fields";
cx.error_spanned_by(fields, msg);
}
},
syn::Data::Enum(syn::DataEnum { enum_token, .. }) => {
let msg = "#[serde(default)] can only be used on structs with named fields";
cx.error_spanned_by(enum_token, msg);
syn::Data::Enum(_) => {
let msg = "#[serde(default)] can only be used on structs";
cx.syn_error(meta.error(msg));
}
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
let msg = "#[serde(default)] can only be used on structs with named fields";
cx.error_spanned_by(union_token, msg);
syn::Data::Union(_) => {
let msg = "#[serde(default)] can only be used on structs";
cx.syn_error(meta.error(msg));
}
}
}
@@ -405,13 +452,13 @@ impl Container {
syn::Data::Enum(_) => {
untagged.set_true(&meta.path);
}
syn::Data::Struct(syn::DataStruct { struct_token, .. }) => {
syn::Data::Struct(_) => {
let msg = "#[serde(untagged)] can only be used on enums";
cx.error_spanned_by(struct_token, msg);
cx.syn_error(meta.error(msg));
}
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
syn::Data::Union(_) => {
let msg = "#[serde(untagged)] can only be used on enums";
cx.error_spanned_by(union_token, msg);
cx.syn_error(meta.error(msg));
}
}
} else if meta.path == TAG {
@@ -427,12 +474,12 @@ impl Container {
}
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields";
cx.error_spanned_by(fields, msg);
cx.syn_error(meta.error(msg));
}
},
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
syn::Data::Union(_) => {
let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields";
cx.error_spanned_by(union_token, msg);
cx.syn_error(meta.error(msg));
}
}
}
@@ -443,13 +490,13 @@ impl Container {
syn::Data::Enum(_) => {
content.set(&meta.path, s.value());
}
syn::Data::Struct(syn::DataStruct { struct_token, .. }) => {
syn::Data::Struct(_) => {
let msg = "#[serde(content = \"...\")] can only be used on enums";
cx.error_spanned_by(struct_token, msg);
cx.syn_error(meta.error(msg));
}
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
syn::Data::Union(_) => {
let msg = "#[serde(content = \"...\")] can only be used on enums";
cx.error_spanned_by(union_token, msg);
cx.syn_error(meta.error(msg));
}
}
}
@@ -528,6 +575,10 @@ impl Container {
serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
},
rename_all_fields_rules: RenameAllRules {
serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None),
deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None),
},
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
tag: decide_tag(cx, item, untagged, internal_tag, content),
@@ -540,6 +591,7 @@ impl Container {
serde_path: serde_path.get(),
is_packed,
expecting: expecting.get(),
non_exhaustive,
}
}
@@ -547,8 +599,12 @@ impl Container {
&self.name
}
pub fn rename_all_rules(&self) -> &RenameAllRules {
&self.rename_all_rules
pub fn rename_all_rules(&self) -> RenameAllRules {
self.rename_all_rules
}
pub fn rename_all_fields_rules(&self) -> RenameAllRules {
self.rename_all_fields_rules
}
pub fn transparent(&self) -> bool {
@@ -621,6 +677,10 @@ impl Container {
pub fn expecting(&self) -> Option<&str> {
self.expecting.as_ref().map(String::as_ref)
}
pub fn non_exhaustive(&self) -> bool {
self.non_exhaustive
}
}
fn decide_tag(
@@ -656,7 +716,7 @@ fn decide_tag(
}
TagType::Internal { tag }
}
(Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => {
(Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => {
let msg = "enum cannot be both untagged and internally tagged";
cx.error_spanned_by(untagged_tokens, msg);
cx.error_spanned_by(tag_tokens, msg);
@@ -667,14 +727,14 @@ fn decide_tag(
cx.error_spanned_by(content_tokens, msg);
TagType::External
}
(Some((untagged_tokens, _)), None, Some((content_tokens, _))) => {
(Some((untagged_tokens, ())), None, Some((content_tokens, _))) => {
let msg = "untagged enum cannot have #[serde(content = \"...\")]";
cx.error_spanned_by(untagged_tokens, msg);
cx.error_spanned_by(content_tokens, msg);
TagType::External
}
(None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content },
(Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => {
(Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => {
let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]";
cx.error_spanned_by(untagged_tokens, msg);
cx.error_spanned_by(tag_tokens, msg);
@@ -696,7 +756,7 @@ fn decide_identifier(
variant_identifier.0.get_with_tokens(),
) {
(_, None, None) => Identifier::No,
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
(_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => {
let msg =
"#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
cx.error_spanned_by(field_identifier_tokens, msg);
@@ -917,21 +977,24 @@ impl Variant {
&self.name
}
pub fn aliases(&self) -> Vec<String> {
pub fn aliases(&self) -> &BTreeSet<String> {
self.name.deserialize_aliases()
}
pub fn rename_by_rules(&mut self, rules: &RenameAllRules) {
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
if !self.name.serialize_renamed {
self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize);
}
if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
}
self.name
.deserialize_aliases
.insert(self.name.deserialize.clone());
}
pub fn rename_all_rules(&self) -> &RenameAllRules {
&self.rename_all_rules
pub fn rename_all_rules(&self) -> RenameAllRules {
self.rename_all_rules
}
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
@@ -1256,17 +1319,20 @@ impl Field {
&self.name
}
pub fn aliases(&self) -> Vec<String> {
pub fn aliases(&self) -> &BTreeSet<String> {
self.name.deserialize_aliases()
}
pub fn rename_by_rules(&mut self, rules: &RenameAllRules) {
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
if !self.name.serialize_renamed {
self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize);
}
if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
}
self.name
.deserialize_aliases
.insert(self.name.deserialize.clone());
}
pub fn skip_serializing(&self) -> bool {
+13 -10
View File
@@ -1,13 +1,8 @@
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
//! case of the source (e.g. `my-field`, `MY_FIELD`).
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
#[allow(deprecated, unused_imports)]
use std::ascii::AsciiExt;
use std::fmt::{self, Debug, Display};
use self::RenameRule::*;
use std::fmt::{self, Debug, Display};
/// The different possible ways to change case of fields in a struct, or variants in an enum.
#[derive(Copy, Clone, PartialEq)]
@@ -59,8 +54,8 @@ impl RenameRule {
}
/// 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 {
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(),
@@ -84,8 +79,8 @@ impl RenameRule {
}
/// Apply a renaming rule to a struct field, returning the version expected in the source.
pub fn apply_to_field(&self, field: &str) -> String {
match *self {
pub fn apply_to_field(self, field: &str) -> String {
match self {
None | LowerCase | SnakeCase => field.to_owned(),
UpperCase => field.to_ascii_uppercase(),
PascalCase => {
@@ -112,6 +107,14 @@ impl RenameRule {
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
}
}
/// Returns the `RenameRule` if it is not `None`, `rule_b` otherwise.
pub fn or(self, rule_b: Self) -> Self {
match self {
None => rule_b,
_ => self,
}
}
}
pub struct ParseError<'a> {
+41 -5
View File
@@ -1,11 +1,12 @@
use internals::ast::{Container, Data, Field, Style};
use internals::attr::{Identifier, TagType};
use internals::{ungroup, Ctxt, Derive};
use crate::internals::ast::{Container, Data, Field, Style};
use crate::internals::attr::{Default, Identifier, TagType};
use crate::internals::{ungroup, Ctxt, Derive};
use syn::{Member, Type};
// Cross-cutting checks that require looking at more than a single attrs object.
// Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_default_on_tuple(cx, cont);
check_remote_generic(cx, cont);
check_getter(cx, cont);
check_flatten(cx, cont);
@@ -17,6 +18,39 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_from_and_try_from(cx, cont);
}
// If some field of a tuple struct is marked #[serde(default)] then all fields
// after it must also be marked with that attribute, or the struct must have a
// container-level serde(default) attribute. A field's default value is only
// used for tuple fields if the sequence is exhausted at that point; that means
// all subsequent fields will fail to deserialize if they don't have their own
// default.
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
if let Default::None = cont.attrs.default() {
if let Data::Struct(Style::Tuple, fields) = &cont.data {
let mut first_default_index = None;
for (i, field) in fields.iter().enumerate() {
// Skipped fields automatically get the #[serde(default)]
// attribute. We are interested only on non-skipped fields here.
if field.attrs.skip_deserializing() {
continue;
}
if let Default::None = field.attrs.default() {
if let Some(first) = first_default_index {
cx.error_spanned_by(
field.ty,
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
);
}
continue;
}
if first_default_index.is_none() {
first_default_index = Some(i);
}
}
}
}
}
// Remote derive definition type must have either all of the generics of the
// remote type:
//
@@ -285,8 +319,10 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
match variant.style {
Style::Struct => {
for field in &variant.fields {
let check_ser = !field.attrs.skip_serializing();
let check_de = !field.attrs.skip_deserializing();
let check_ser =
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
let check_de =
!(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing());
let name = field.attrs.name();
let ser_name = name.serialize_name();
-1
View File
@@ -2,7 +2,6 @@ use quote::ToTokens;
use std::cell::RefCell;
use std::fmt::Display;
use std::thread;
use syn;
/// A type to collect errors together and format them.
///
+5 -6
View File
@@ -1,19 +1,18 @@
pub mod ast;
pub mod attr;
mod ctxt;
pub use self::ctxt::Ctxt;
mod receiver;
pub use self::receiver::replace_receiver;
mod case;
mod check;
mod ctxt;
mod receiver;
mod respan;
mod symbol;
use syn::Type;
pub use self::ctxt::Ctxt;
pub use self::receiver::replace_receiver;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
+2 -2
View File
@@ -1,11 +1,11 @@
use internals::respan::respan;
use crate::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,
Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
};
pub fn replace_receiver(input: &mut DeriveInput) {
+2
View File
@@ -19,10 +19,12 @@ pub const FLATTEN: Symbol = Symbol("flatten");
pub const FROM: Symbol = Symbol("from");
pub const GETTER: Symbol = Symbol("getter");
pub const INTO: Symbol = Symbol("into");
pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive");
pub const OTHER: Symbol = Symbol("other");
pub const REMOTE: Symbol = Symbol("remote");
pub const RENAME: Symbol = Symbol("rename");
pub const RENAME_ALL: Symbol = Symbol("rename_all");
pub const RENAME_ALL_FIELDS: Symbol = Symbol("rename_all_fields");
pub const REPR: Symbol = Symbol("repr");
pub const SERDE: Symbol = Symbol("serde");
pub const SERIALIZE: Symbol = Symbol("serialize");
+5 -27
View File
@@ -13,8 +13,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.175")]
#![allow(unknown_lints, bare_trait_objects)]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.189")]
// Ignored clippy lints
#![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
@@ -63,23 +62,16 @@
)]
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
#[macro_use]
extern crate proc_macro2;
extern crate quote;
#[macro_use]
extern crate syn;
#[cfg(not(precompiled))]
extern crate proc_macro;
extern crate proc_macro2;
#[cfg(precompiled)]
extern crate proc_macro2 as proc_macro;
mod internals;
use proc_macro::TokenStream;
#[cfg(precompiled)]
use std::sync::atomic::AtomicBool;
use syn::parse_macro_input;
use syn::DeriveInput;
#[macro_use]
@@ -92,22 +84,8 @@ mod dummy;
mod pretend;
mod ser;
mod this;
mod try;
#[cfg(precompiled)]
macro_rules! parse_macro_input {
($tokenstream:ident as $ty:ty) => {
match syn::parse2::<$ty>($tokenstream) {
Ok(data) => data,
Err(err) => return err.to_compile_error(),
}
};
}
#[cfg(precompiled)]
pub static DESERIALIZE_IN_PLACE: AtomicBool = AtomicBool::new(false);
#[cfg_attr(not(precompiled), proc_macro_derive(Serialize, attributes(serde)))]
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&mut input)
@@ -115,7 +93,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
.into()
}
#[cfg_attr(not(precompiled), proc_macro_derive(Deserialize, attributes(serde)))]
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&mut input)
+2 -3
View File
@@ -1,7 +1,6 @@
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use proc_macro2::TokenStream;
use quote::format_ident;
use internals::ast::{Container, Data, Field, Style, Variant};
use quote::{format_ident, quote};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
+88 -70
View File
@@ -1,14 +1,11 @@
use crate::fragment::{Fragment, Match, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
use crate::{bound, dummy, pretend, this};
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{self, Ident, Index, Member};
use bound;
use dummy;
use fragment::{Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, replace_receiver, Ctxt, Derive};
use pretend;
use this;
use syn::{parse_quote, Ident, Index, Member};
pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
replace_receiver(input);
@@ -285,7 +282,7 @@ fn serialize_tuple_struct(
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?;
#(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
@@ -307,7 +304,7 @@ fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTra
let type_name = cattrs.name().serialize_name();
let func = struct_trait.serialize_field(Span::call_site());
quote! {
try!(#func(&mut __serde_state, #tag, #type_name));
#func(&mut __serde_state, #tag, #type_name)?;
}
}
_ => quote! {},
@@ -348,7 +345,7 @@ fn serialize_struct_as_struct(
);
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
#tag_field
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
@@ -392,7 +389,7 @@ fn serialize_struct_as_map(
};
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?;
#tag_field
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
@@ -404,7 +401,7 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
let self_var = &params.self_var;
let arms: Vec<_> = variants
let mut arms: Vec<_> = variants
.iter()
.enumerate()
.map(|(variant_index, variant)| {
@@ -412,6 +409,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
})
.collect();
if cattrs.remote().is_some() && cattrs.non_exhaustive() {
arms.push(quote! {
ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))),
});
}
quote_expr! {
match *#self_var {
#(#arms)*
@@ -481,7 +484,14 @@ fn serialize_variant(
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
(attr::TagType::Adjacent { tag, content }, false) => {
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
serialize_adjacently_tagged_variant(
params,
variant,
cattrs,
variant_index,
tag,
content,
)
}
(attr::TagType::None, _) | (_, true) => {
serialize_untagged_variant(params, variant, cattrs)
@@ -562,7 +572,7 @@ fn serialize_externally_tagged_variant(
},
params,
&variant.fields,
&type_name,
type_name,
),
}
}
@@ -596,10 +606,10 @@ fn serialize_internally_tagged_variant(
match effective_style(variant) {
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 1)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name)?;
_serde::ser::SerializeStruct::end(__struct)
}
}
@@ -627,7 +637,7 @@ fn serialize_internally_tagged_variant(
StructVariant::InternallyTagged { tag, variant_name },
params,
&variant.fields,
&type_name,
type_name,
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
@@ -637,12 +647,20 @@ fn serialize_adjacently_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
variant_index: u32,
tag: &str,
content: &str,
) -> Fragment {
let this_type = &params.this_type;
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let serialize_variant = quote! {
&_serde::__private::ser::AdjacentlyTaggedEnumVariant {
enum_name: #type_name,
variant_index: #variant_index,
variant_name: #variant_name,
}
};
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, variant);
@@ -653,10 +671,10 @@ fn serialize_adjacently_tagged_variant(
match effective_style(variant) {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 1)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #serialize_variant)?;
_serde::ser::SerializeStruct::end(__struct)
};
}
@@ -670,12 +688,12 @@ fn serialize_adjacently_tagged_variant(
let span = field.original.span();
let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(#func(
&mut __struct, #content, #field_expr));
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 2)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #serialize_variant)?;
#func(
&mut __struct, #content, #field_expr)?;
_serde::ser::SerializeStruct::end(__struct)
};
}
@@ -686,13 +704,13 @@ fn serialize_adjacently_tagged_variant(
StructVariant::Untagged,
params,
&variant.fields,
&variant_name,
variant_name,
),
}
});
let fields_ty = variant.fields.iter().map(|f| &f.ty);
let fields_ident: &Vec<_> = &match variant.style {
let fields_ident: &[_] = &match variant.style {
Style::Unit => {
if variant.attrs.serialize_with().is_some() {
vec![]
@@ -735,15 +753,15 @@ fn serialize_adjacently_tagged_variant(
}
}
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 2)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #serialize_variant)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*),
phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
}));
})?;
_serde::ser::SerializeStruct::end(__struct)
}
}
@@ -782,16 +800,16 @@ fn serialize_untagged_variant(
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
Style::Struct => {
let type_name = cattrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
}
}
}
enum TupleVariant {
enum TupleVariant<'a> {
ExternallyTagged {
type_name: String,
type_name: &'a str,
variant_index: u32,
variant_name: String,
variant_name: &'a str,
},
Untagged,
}
@@ -833,21 +851,21 @@ fn serialize_tuple_variant(
variant_name,
} => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
__serializer,
#type_name,
#variant_index,
#variant_name,
#len));
#len)?;
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
TupleVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
__serializer,
#len));
#len)?;
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
}
@@ -858,11 +876,11 @@ fn serialize_tuple_variant(
enum StructVariant<'a> {
ExternallyTagged {
variant_index: u32,
variant_name: String,
variant_name: &'a str,
},
InternallyTagged {
tag: &'a str,
variant_name: String,
variant_name: &'a str,
},
Untagged,
}
@@ -910,40 +928,40 @@ fn serialize_struct_variant(
variant_name,
} => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
__serializer,
#name,
#variant_index,
#variant_name,
#len,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
let mut __serde_state = _serde::Serializer::serialize_struct(
__serializer,
#name,
#len + 1,
));
try!(_serde::ser::SerializeStruct::serialize_field(
)?;
_serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
#tag,
#variant_name,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
let #let_mut __serde_state = _serde::Serializer::serialize_struct(
__serializer,
#name,
#len,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
@@ -993,9 +1011,9 @@ fn serialize_struct_variant_with_flatten(
__S: _serde::Serializer,
{
let (#(#members,)*) = self.data;
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
let #let_mut __serde_state = _serde::Serializer::serialize_map(
__serializer,
_serde::__private::None));
_serde::__private::None)?;
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -1014,23 +1032,23 @@ fn serialize_struct_variant_with_flatten(
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
let #let_mut __serde_state = _serde::Serializer::serialize_map(
__serializer,
_serde::__private::None));
try!(_serde::ser::SerializeMap::serialize_entry(
_serde::__private::None)?;
_serde::ser::SerializeMap::serialize_entry(
&mut __serde_state,
#tag,
#variant_name,
));
)?;
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
let #let_mut __serde_state = _serde::Serializer::serialize_map(
__serializer,
_serde::__private::None));
_serde::__private::None)?;
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
@@ -1075,7 +1093,7 @@ fn serialize_tuple_struct_visitor(
let span = field.original.span();
let func = tuple_trait.serialize_element(span);
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
#func(&mut __serde_state, #field_expr)?;
};
match skip {
@@ -1119,12 +1137,12 @@ fn serialize_struct_visitor(
let ser = if field.attrs.flatten() {
let func = quote_spanned!(span=> _serde::Serialize::serialize);
quote! {
try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state)));
#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
}
} else {
let func = struct_trait.serialize_field(span);
quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
#func(&mut __serde_state, #key_expr, #field_expr)?;
}
};
@@ -1136,7 +1154,7 @@ fn serialize_struct_visitor(
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
#skip_func(&mut __serde_state, #key_expr)?;
}
}
} else {
@@ -1236,7 +1254,7 @@ fn wrap_serialize_with(
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// let mut __serde_state = serializer.serialize_struct("S", 0)?;
// _serde::ser::SerializeStruct::end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
+1 -1
View File
@@ -1,4 +1,4 @@
use internals::ast::Container;
use crate::internals::ast::Container;
use syn::{Path, PathArguments, Token};
pub fn this_type(cont: &Container) -> Path {
-24
View File
@@ -1,24 +0,0 @@
use proc_macro2::{Punct, Spacing, TokenStream};
// None of our generated code requires the `From::from` error conversion
// performed by the standard library's `try!` macro. With this simplified macro
// we see a significant improvement in type checking and borrow checking time of
// the generated code and a slight improvement in binary size.
pub fn replacement() -> TokenStream {
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
let dollar = Punct::new('$', Spacing::Alone);
quote! {
#[allow(unused_macros)]
macro_rules! try {
(#dollar __expr:expr) => {
match #dollar __expr {
_serde::__private::Ok(__val) => __val,
_serde::__private::Err(__err) => {
return _serde::__private::Err(__err);
}
}
}
}
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive_internals"
version = "0.28.0" # remember to update html_root_url
version = "0.29.0" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
description = "AST representation used by Serde derive macros. Unstable."
documentation = "https://docs.rs/serde_derive_internals"
@@ -17,7 +17,7 @@ path = "lib.rs"
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+3 -5
View File
@@ -1,5 +1,4 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.28.0")]
#![allow(unknown_lints, bare_trait_objects)]
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.0")]
// Ignored clippy lints
#![allow(
clippy::cognitive_complexity,
@@ -30,6 +29,7 @@
clippy::missing_errors_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::return_self_not_must_use,
clippy::similar_names,
clippy::single_match_else,
clippy::struct_excessive_bools,
@@ -38,11 +38,9 @@
clippy::wildcard_imports
)]
#[macro_use]
extern crate syn;
extern crate proc_macro2;
extern crate quote;
extern crate syn;
#[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
#[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
-28
View File
@@ -1,28 +0,0 @@
[package]
name = "serde_test"
version = "1.0.175" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
categories = ["development-tools::testing"]
description = "Token De/Serializer for testing De/Serialize implementations"
documentation = "https://docs.rs/serde_test"
homepage = "https://serde.rs"
keywords = ["serde", "serialization", "testing", "dev-dependencies"]
license = "MIT OR Apache-2.0"
readme = "crates-io.md"
repository = "https://github.com/serde-rs/serde"
rust-version = "1.19"
[dependencies]
serde = { version = "1.0.60", path = "../serde" }
[dev-dependencies]
serde = { version = "1", path = "../serde", features = ["rc"] }
serde_derive = { version = "1", path = "../serde_derive" }
[lib]
doc-scrape-examples = false
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
-1
View File
@@ -1 +0,0 @@
../LICENSE-APACHE
-1
View File
@@ -1 +0,0 @@
../LICENSE-MIT
-1
View File
@@ -1 +0,0 @@
../README.md
-50
View File
@@ -1,50 +0,0 @@
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() {
println!("cargo:rerun-if-changed=build.rs");
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=no_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()
}
-1
View File
@@ -1 +0,0 @@
../crates-io.md
-237
View File
@@ -1,237 +0,0 @@
use serde::{Deserialize, Serialize};
use de::Deserializer;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Serialize + Deserialize<'de> + PartialEq + Debug,
{
assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens);
}
/// Asserts that `value` serializes to the given `tokens`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_ser_tokens, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_ser_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_ser_tokens<T: ?Sized>(value: &T, tokens: &[Token])
where
T: Serialize,
{
let mut ser = Serializer::new(tokens);
match value.serialize(&mut ser) {
Ok(_) => {}
Err(err) => panic!("value failed to serialize: {}", err),
}
if ser.remaining() > 0 {
panic!("{} remaining tokens", ser.remaining());
}
}
/// Asserts that `value` serializes to the given `tokens`, and then yields
/// `error`.
///
/// ```edition2021
/// use serde_derive::Serialize;
/// use serde_test::{assert_ser_tokens_error, Token};
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// #[derive(Serialize)]
/// struct Example {
/// lock: Arc<Mutex<u32>>,
/// }
///
/// fn main() {
/// let example = Example {
/// lock: Arc::new(Mutex::new(0)),
/// };
/// let lock = example.lock.clone();
///
/// let thread = thread::spawn(move || {
/// // This thread will acquire the mutex first, unwrapping the result
/// // of `lock` because the lock has not been poisoned.
/// let _guard = lock.lock().unwrap();
///
/// // This panic while holding the lock (`_guard` is in scope) will
/// // poison the mutex.
/// panic!()
/// });
/// thread.join();
///
/// let expected = &[
/// Token::Struct {
/// name: "Example",
/// len: 1,
/// },
/// Token::Str("lock"),
/// ];
/// let error = "lock poison error while serializing";
/// assert_ser_tokens_error(&example, expected, error);
/// }
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_ser_tokens_error<T: ?Sized>(value: &T, tokens: &[Token], error: &str)
where
T: Serialize,
{
let mut ser = Serializer::new(tokens);
match value.serialize(&mut ser) {
Ok(_) => panic!("value serialized successfully"),
Err(e) => assert_eq!(e, *error),
}
if ser.remaining() > 0 {
panic!("{} remaining tokens", ser.remaining());
}
}
/// Asserts that the given `tokens` deserialize into `value`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_de_tokens, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_de_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Deserialize<'de> + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens);
let mut deserialized_val = match T::deserialize(&mut de) {
Ok(v) => {
assert_eq!(v, *value);
v
}
Err(e) => panic!("tokens failed to deserialize: {}", e),
};
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
// Do the same thing for deserialize_in_place. This isn't *great* because a
// no-op impl of deserialize_in_place can technically succeed here. Still,
// this should catch a lot of junk.
let mut de = Deserializer::new(tokens);
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
Ok(()) => {
assert_eq!(deserialized_val, *value);
}
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
}
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
}
/// Asserts that the given `tokens` yield `error` when deserializing.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_de_tokens_error, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// #[serde(deny_unknown_fields)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// assert_de_tokens_error::<S>(
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("x"),
/// ],
/// "unknown field `x`, expected `a` or `b`",
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
where
T: Deserialize<'de>,
{
let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) {
Ok(_) => panic!("tokens deserialized successfully"),
Err(e) => assert_eq!(e, *error),
}
// There may be one token left if a peek caused the error
de.next_token_opt();
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
}
-847
View File
@@ -1,847 +0,0 @@
use std::fmt;
use serde::ser::{
SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
SerializeTupleStruct, SerializeTupleVariant,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Readable<T: ?Sized>(T);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Compact<T: ?Sized>(T);
/// Trait to determine whether a value is represented in human-readable or
/// compact form.
///
/// ```edition2021
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{assert_tokens, Configure, Token};
///
/// #[derive(Debug, PartialEq)]
/// struct Example(u8, u8);
///
/// impl Serialize for Example {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// if serializer.is_human_readable() {
/// format!("{}.{}", self.0, self.1).serialize(serializer)
/// } else {
/// (self.0, self.1).serialize(serializer)
/// }
/// }
/// }
///
/// impl<'de> Deserialize<'de> for Example {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where
/// D: Deserializer<'de>,
/// {
/// use serde::de::Error;
/// if deserializer.is_human_readable() {
/// let s = String::deserialize(deserializer)?;
/// let parts: Vec<_> = s.split('.').collect();
/// Ok(Example(
/// parts[0].parse().map_err(D::Error::custom)?,
/// parts[1].parse().map_err(D::Error::custom)?,
/// ))
/// } else {
/// let (x, y) = Deserialize::deserialize(deserializer)?;
/// Ok(Example(x, y))
/// }
/// }
/// }
///
/// fn main() {
/// assert_tokens(
/// &Example(1, 0).compact(),
/// &[
/// Token::Tuple { len: 2 },
/// Token::U8(1),
/// Token::U8(0),
/// Token::TupleEnd,
/// ],
/// );
/// assert_tokens(&Example(1, 0).readable(), &[Token::Str("1.0")]);
/// }
/// ```
pub trait Configure {
/// Marks `self` as using `is_human_readable == true`
fn readable(self) -> Readable<Self>
where
Self: Sized,
{
Readable(self)
}
/// Marks `self` as using `is_human_readable == false`
fn compact(self) -> Compact<Self>
where
Self: Sized,
{
Compact(self)
}
}
impl<T: ?Sized> Configure for T {}
impl<T: ?Sized> Serialize for Readable<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(Readable(serializer))
}
}
impl<T: ?Sized> Serialize for Compact<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(Compact(serializer))
}
}
impl<'de, T> Deserialize<'de> for Readable<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(Readable(deserializer)).map(Readable)
}
}
impl<'de, T> Deserialize<'de> for Compact<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(Compact(deserializer)).map(Compact)
}
}
impl<'de, T> DeserializeSeed<'de> for Readable<T>
where
T: DeserializeSeed<'de>,
{
type Value = T::Value;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.0.deserialize(Readable(deserializer))
}
}
impl<'de, T> DeserializeSeed<'de> for Compact<T>
where
T: DeserializeSeed<'de>,
{
type Value = T::Value;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
self.0.deserialize(Compact(deserializer))
}
}
macro_rules! forward_method {
($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => {
fn $name (self $(, $arg : $arg_type)* ) -> $return_type {
(self.0).$name( $($arg),* )
}
};
}
macro_rules! forward_serialize_methods {
( $( $name: ident $arg_type: ty ),* ) => {
$(
forward_method!($name(self, v : $arg_type) -> Result<Self::Ok, Self::Error>);
)*
};
}
macro_rules! impl_serializer {
($wrapper:ident, $is_human_readable:expr) => {
impl<S> Serializer for $wrapper<S>
where
S: Serializer,
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = $wrapper<S::SerializeSeq>;
type SerializeTuple = $wrapper<S::SerializeTuple>;
type SerializeTupleStruct = $wrapper<S::SerializeTupleStruct>;
type SerializeTupleVariant = $wrapper<S::SerializeTupleVariant>;
type SerializeMap = $wrapper<S::SerializeMap>;
type SerializeStruct = $wrapper<S::SerializeStruct>;
type SerializeStructVariant = $wrapper<S::SerializeStructVariant>;
fn is_human_readable(&self) -> bool {
$is_human_readable
}
forward_serialize_methods! {
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_bytes &[u8],
serialize_unit_struct &'static str
}
fn serialize_unit(self) -> Result<S::Ok, S::Error> {
self.0.serialize_unit()
}
fn serialize_unit_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
) -> Result<S::Ok, S::Error> {
self.0.serialize_unit_variant(name, variant_index, variant)
}
fn serialize_newtype_struct<T: ?Sized>(
self,
name: &'static str,
value: &T,
) -> Result<S::Ok, S::Error>
where
T: Serialize,
{
self.0.serialize_newtype_struct(name, &$wrapper(value))
}
fn serialize_newtype_variant<T: ?Sized>(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<S::Ok, S::Error>
where
T: Serialize,
{
self.0
.serialize_newtype_variant(name, variant_index, variant, &$wrapper(value))
}
fn serialize_none(self) -> Result<S::Ok, Self::Error> {
self.0.serialize_none()
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<S::Ok, Self::Error>
where
T: Serialize,
{
self.0.serialize_some(&$wrapper(value))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
self.0.serialize_seq(len).map($wrapper)
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
self.0.serialize_tuple(len).map($wrapper)
}
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
self.0.serialize_tuple_struct(name, len).map($wrapper)
}
fn serialize_tuple_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
self.0
.serialize_tuple_variant(name, variant_index, variant, len)
.map($wrapper)
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
self.0.serialize_map(len).map($wrapper)
}
fn serialize_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
self.0.serialize_struct(name, len).map($wrapper)
}
fn serialize_struct_variant(
self,
name: &'static str,
variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
self.0
.serialize_struct_variant(name, variant_index, variant, len)
.map($wrapper)
}
}
impl<S> SerializeSeq for $wrapper<S>
where
S: SerializeSeq,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_element(&$wrapper(value))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
impl<S> SerializeTuple for $wrapper<S>
where
S: SerializeTuple,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_element(&$wrapper(value))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
impl<S> SerializeTupleStruct for $wrapper<S>
where
S: SerializeTupleStruct,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_field(&$wrapper(value))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
impl<S> SerializeTupleVariant for $wrapper<S>
where
S: SerializeTupleVariant,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_field(&$wrapper(value))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
impl<S> SerializeMap for $wrapper<S>
where
S: SerializeMap,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_key(&$wrapper(key))
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_value(&$wrapper(value))
}
fn serialize_entry<K: ?Sized, V: ?Sized>(
&mut self,
key: &K,
value: &V,
) -> Result<(), S::Error>
where
K: Serialize,
V: Serialize,
{
self.0.serialize_entry(key, &$wrapper(value))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
impl<S> SerializeStruct for $wrapper<S>
where
S: SerializeStruct,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_field<T: ?Sized>(
&mut self,
name: &'static str,
field: &T,
) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_field(name, &$wrapper(field))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
impl<S> SerializeStructVariant for $wrapper<S>
where
S: SerializeStructVariant,
{
type Ok = S::Ok;
type Error = S::Error;
fn serialize_field<T: ?Sized>(
&mut self,
name: &'static str,
field: &T,
) -> Result<(), S::Error>
where
T: Serialize,
{
self.0.serialize_field(name, &$wrapper(field))
}
fn end(self) -> Result<S::Ok, S::Error> {
self.0.end()
}
}
};
}
impl_serializer!(Readable, true);
impl_serializer!(Compact, false);
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
macro_rules! forward_deserialize_methods {
( $wrapper : ident ( $( $name: ident ),* ) ) => {
$(
fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
(self.0).$name($wrapper(visitor))
}
)*
};
}
macro_rules! impl_deserializer {
($wrapper:ident, $is_human_readable:expr) => {
impl<'de, D> Deserializer<'de> for $wrapper<D>
where
D: Deserializer<'de>,
{
type Error = D::Error;
forward_deserialize_methods! {
$wrapper (
deserialize_any,
deserialize_bool,
deserialize_u8,
deserialize_u16,
deserialize_u32,
deserialize_u64,
deserialize_i8,
deserialize_i16,
deserialize_i32,
deserialize_i64,
deserialize_f32,
deserialize_f64,
deserialize_char,
deserialize_str,
deserialize_string,
deserialize_bytes,
deserialize_byte_buf,
deserialize_option,
deserialize_unit,
deserialize_seq,
deserialize_map,
deserialize_identifier,
deserialize_ignored_any
)
}
fn deserialize_unit_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.deserialize_unit_struct(name, $wrapper(visitor))
}
fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.deserialize_newtype_struct(name, $wrapper(visitor))
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.deserialize_tuple(len, $wrapper(visitor))
}
fn deserialize_tuple_struct<V>(
self,
name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0
.deserialize_tuple_struct(name, len, $wrapper(visitor))
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.deserialize_struct(name, fields, $wrapper(visitor))
}
fn deserialize_enum<V>(
self,
name: &'static str,
variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.deserialize_enum(name, variants, $wrapper(visitor))
}
fn is_human_readable(&self) -> bool {
$is_human_readable
}
}
impl<'de, D> Visitor<'de> for $wrapper<D>
where
D: Visitor<'de>,
{
type Value = D::Value;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
self.0.expecting(formatter)
}
fn visit_bool<E>(self, v: bool) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_bool(v)
}
fn visit_i8<E>(self, v: i8) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_i8(v)
}
fn visit_i16<E>(self, v: i16) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_i16(v)
}
fn visit_i32<E>(self, v: i32) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_i32(v)
}
fn visit_i64<E>(self, v: i64) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_i64(v)
}
fn visit_u8<E>(self, v: u8) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_u8(v)
}
fn visit_u16<E>(self, v: u16) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_u16(v)
}
fn visit_u32<E>(self, v: u32) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_u32(v)
}
fn visit_u64<E>(self, v: u64) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_u64(v)
}
fn visit_f32<E>(self, v: f32) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_f32(v)
}
fn visit_f64<E>(self, v: f64) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_f64(v)
}
fn visit_char<E>(self, v: char) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_char(v)
}
fn visit_str<E>(self, v: &str) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_str(v)
}
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_borrowed_str(v)
}
fn visit_string<E>(self, v: String) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_string(v)
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_bytes(v)
}
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_borrowed_bytes(v)
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_byte_buf(v)
}
fn visit_none<E>(self) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_none()
}
fn visit_some<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
where
D2: Deserializer<'de>,
{
self.0.visit_some($wrapper(deserializer))
}
fn visit_unit<E>(self) -> Result<D::Value, E>
where
E: Error,
{
self.0.visit_unit()
}
fn visit_newtype_struct<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
where
D2: Deserializer<'de>,
{
self.0.visit_newtype_struct($wrapper(deserializer))
}
fn visit_seq<V>(self, seq: V) -> Result<D::Value, V::Error>
where
V: SeqAccess<'de>,
{
self.0.visit_seq($wrapper(seq))
}
fn visit_map<V>(self, map: V) -> Result<D::Value, V::Error>
where
V: MapAccess<'de>,
{
self.0.visit_map($wrapper(map))
}
fn visit_enum<V>(self, data: V) -> Result<D::Value, V::Error>
where
V: EnumAccess<'de>,
{
self.0.visit_enum($wrapper(data))
}
}
impl<'de, D> SeqAccess<'de> for $wrapper<D>
where
D: SeqAccess<'de>,
{
type Error = D::Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, D::Error>
where
T: DeserializeSeed<'de>,
{
self.0.next_element_seed($wrapper(seed))
}
fn size_hint(&self) -> Option<usize> {
self.0.size_hint()
}
}
impl<'de, D> MapAccess<'de> for $wrapper<D>
where
D: MapAccess<'de>,
{
type Error = D::Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, D::Error>
where
K: DeserializeSeed<'de>,
{
self.0.next_key_seed($wrapper(seed))
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, D::Error>
where
V: DeserializeSeed<'de>,
{
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()
}
}
impl<'de, D> EnumAccess<'de> for $wrapper<D>
where
D: EnumAccess<'de>,
{
type Error = D::Error;
type Variant = $wrapper<D::Variant>;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>,
{
self.0
.variant_seed($wrapper(seed))
.map(|(value, variant)| (value, $wrapper(variant)))
}
}
impl<'de, D> VariantAccess<'de> for $wrapper<D>
where
D: VariantAccess<'de>,
{
type Error = D::Error;
fn unit_variant(self) -> Result<(), D::Error> {
self.0.unit_variant()
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, D::Error>
where
T: DeserializeSeed<'de>,
{
self.0.newtype_variant_seed($wrapper(seed))
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.tuple_variant(len, $wrapper(visitor))
}
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
self.0.struct_variant(fields, $wrapper(visitor))
}
}
};
}
impl_deserializer!(Readable, true);
impl_deserializer!(Compact, false);
-671
View File
@@ -1,671 +0,0 @@
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use serde::de::{
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use error::Error;
use token::Token;
#[derive(Debug)]
pub struct Deserializer<'de> {
tokens: &'de [Token],
}
fn assert_next_token(de: &mut Deserializer, expected: Token) -> Result<(), Error> {
match de.next_token_opt() {
Some(token) if token == expected => Ok(()),
Some(other) => Err(de::Error::custom(format!(
"expected Token::{} but deserialization wants Token::{}",
other, expected,
))),
None => Err(de::Error::custom(format!(
"end of tokens but deserialization wants Token::{}",
expected,
))),
}
}
fn unexpected(token: Token) -> Error {
de::Error::custom(format!(
"deserialization did not expect this token: {}",
token,
))
}
fn end_of_tokens() -> Error {
de::Error::custom("ran out of tokens to deserialize")
}
impl<'de> Deserializer<'de> {
pub fn new(tokens: &'de [Token]) -> Self {
Deserializer { tokens: tokens }
}
fn peek_token_opt(&self) -> Option<Token> {
self.tokens.first().cloned()
}
fn peek_token(&self) -> Result<Token, Error> {
self.peek_token_opt().ok_or_else(end_of_tokens)
}
pub fn next_token_opt(&mut self) -> Option<Token> {
match self.tokens.split_first() {
Some((&first, rest)) => {
self.tokens = rest;
Some(first)
}
None => None,
}
}
fn next_token(&mut self) -> Result<Token, Error> {
let (&first, rest) = self.tokens.split_first().ok_or_else(end_of_tokens)?;
self.tokens = rest;
Ok(first)
}
pub fn remaining(&self) -> usize {
self.tokens.len()
}
fn visit_seq<V>(
&mut self,
len: Option<usize>,
end: Token,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let value = visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
end: end,
})?;
assert_next_token(self, end)?;
Ok(value)
}
fn visit_map<V>(
&mut self,
len: Option<usize>,
end: Token,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let value = visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
end: end,
})?;
assert_next_token(self, end)?;
Ok(value)
}
}
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf unit seq map identifier ignored_any
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
let token = self.next_token()?;
match token {
Token::Bool(v) => visitor.visit_bool(v),
Token::I8(v) => visitor.visit_i8(v),
Token::I16(v) => visitor.visit_i16(v),
Token::I32(v) => visitor.visit_i32(v),
Token::I64(v) => visitor.visit_i64(v),
Token::U8(v) => visitor.visit_u8(v),
Token::U16(v) => visitor.visit_u16(v),
Token::U32(v) => visitor.visit_u32(v),
Token::U64(v) => visitor.visit_u64(v),
Token::F32(v) => visitor.visit_f32(v),
Token::F64(v) => visitor.visit_f64(v),
Token::Char(v) => visitor.visit_char(v),
Token::Str(v) => visitor.visit_str(v),
Token::BorrowedStr(v) => visitor.visit_borrowed_str(v),
Token::String(v) => visitor.visit_string(v.to_owned()),
Token::Bytes(v) => visitor.visit_bytes(v),
Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v),
Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
Token::None => visitor.visit_none(),
Token::Some => visitor.visit_some(self),
Token::Unit | Token::UnitStruct { .. } => visitor.visit_unit(),
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
Token::TupleStruct { len, .. } => {
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
Token::Enum { .. } => {
let variant = self.next_token()?;
let next = self.peek_token()?;
match (variant, next) {
(Token::Str(variant), Token::Unit) => {
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) => Err(unexpected(variant)),
(variant, _) => {
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
}
}
}
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Any,
)),
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Seq,
)),
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Map,
)),
Token::SeqEnd
| Token::TupleEnd
| Token::TupleStructEnd
| Token::MapEnd
| Token::StructEnd
| Token::TupleVariantEnd
| Token::StructVariantEnd => Err(unexpected(token)),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::Unit | Token::None => {
self.next_token()?;
visitor.visit_none()
}
Token::Some => {
self.next_token()?;
visitor.visit_some(self)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_enum<V>(
self,
name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::Enum { name: n } if name == n => {
self.next_token()?;
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
Token::UnitVariant { name: n, .. }
| Token::NewtypeVariant { name: n, .. }
| Token::TupleVariant { name: n, .. }
| Token::StructVariant { name: n, .. }
if name == n =>
{
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::UnitStruct { .. } => {
assert_next_token(self, Token::UnitStruct { name: name })?;
visitor.visit_unit()
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::NewtypeStruct { .. } => {
assert_next_token(self, Token::NewtypeStruct { name: name })?;
visitor.visit_newtype_struct(self)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::Unit | Token::UnitStruct { .. } => {
self.next_token()?;
visitor.visit_unit()
}
Token::Seq { .. } => {
self.next_token()?;
self.visit_seq(Some(len), Token::SeqEnd, visitor)
}
Token::Tuple { .. } => {
self.next_token()?;
self.visit_seq(Some(len), Token::TupleEnd, visitor)
}
Token::TupleStruct { .. } => {
self.next_token()?;
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_tuple_struct<V>(
self,
name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::Unit => {
self.next_token()?;
visitor.visit_unit()
}
Token::UnitStruct { .. } => {
assert_next_token(self, Token::UnitStruct { name: name })?;
visitor.visit_unit()
}
Token::Seq { .. } => {
self.next_token()?;
self.visit_seq(Some(len), Token::SeqEnd, visitor)
}
Token::Tuple { .. } => {
self.next_token()?;
self.visit_seq(Some(len), Token::TupleEnd, visitor)
}
Token::TupleStruct { len: n, .. } => {
assert_next_token(self, Token::TupleStruct { name: name, len: n })?;
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
_ => self.deserialize_any(visitor),
}
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.peek_token()? {
Token::Struct { len: n, .. } => {
assert_next_token(self, Token::Struct { name: name, len: n })?;
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
}
Token::Map { .. } => {
self.next_token()?;
self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
}
_ => self.deserialize_any(visitor),
}
}
fn is_human_readable(&self) -> bool {
panic!(
"Types which have different human-readable and compact representations \
must explicitly mark their test cases with `serde_test::Configure`"
);
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerSeqVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
len: Option<usize>,
end: Token,
}
impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: DeserializeSeed<'de>,
{
if self.de.peek_token_opt() == Some(self.end) {
return Ok(None);
}
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
self.len
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerMapVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
len: Option<usize>,
end: Token,
}
impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where
K: DeserializeSeed<'de>,
{
if self.de.peek_token_opt() == Some(self.end) {
return Ok(None);
}
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where
V: DeserializeSeed<'de>,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> Option<usize> {
self.len
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerEnumVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
}
impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
where
V: DeserializeSeed<'de>,
{
match self.de.peek_token()? {
Token::UnitVariant { variant: v, .. }
| Token::NewtypeVariant { variant: v, .. }
| Token::TupleVariant { variant: v, .. }
| Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer();
let value = seed.deserialize(de)?;
Ok((value, self))
}
_ => {
let value = seed.deserialize(&mut *self.de)?;
Ok((value, self))
}
}
}
}
impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
type Error = Error;
fn unit_variant(self) -> Result<(), Error> {
match self.de.peek_token()? {
Token::UnitVariant { .. } => {
self.de.next_token()?;
Ok(())
}
_ => Deserialize::deserialize(self.de),
}
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.de.peek_token()? {
Token::NewtypeVariant { .. } => {
self.de.next_token()?;
seed.deserialize(self.de)
}
_ => seed.deserialize(self.de),
}
}
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.de.peek_token()? {
Token::TupleVariant { len: enum_len, .. } => {
let token = self.de.next_token()?;
if len == enum_len {
self.de
.visit_seq(Some(len), Token::TupleVariantEnd, visitor)
} else {
Err(unexpected(token))
}
}
Token::Seq {
len: Some(enum_len),
} => {
let token = self.de.next_token()?;
if len == enum_len {
self.de.visit_seq(Some(len), Token::SeqEnd, visitor)
} else {
Err(unexpected(token))
}
}
_ => de::Deserializer::deserialize_any(self.de, visitor),
}
}
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.de.peek_token()? {
Token::StructVariant { len: enum_len, .. } => {
let token = self.de.next_token()?;
if fields.len() == enum_len {
self.de
.visit_map(Some(fields.len()), Token::StructVariantEnd, visitor)
} else {
Err(unexpected(token))
}
}
Token::Map {
len: Some(enum_len),
} => {
let token = self.de.next_token()?;
if fields.len() == enum_len {
self.de
.visit_map(Some(fields.len()), Token::MapEnd, visitor)
} else {
Err(unexpected(token))
}
}
_ => de::Deserializer::deserialize_any(self.de, visitor),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct EnumMapVisitor<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>,
variant: Option<Token>,
format: EnumFormat,
}
enum EnumFormat {
Seq,
Map,
Any,
}
impl<'a, 'de> EnumMapVisitor<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self {
EnumMapVisitor {
de: de,
variant: Some(variant),
format: format,
}
}
}
impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where
K: DeserializeSeed<'de>,
{
match self.variant.take() {
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => seed
.deserialize(BytesDeserializer { value: variant })
.map(Some),
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => Err(unexpected(other)),
None => Ok(None),
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where
V: DeserializeSeed<'de>,
{
match self.format {
EnumFormat::Seq => {
let value = {
let visitor = DeserializerSeqVisitor {
de: self.de,
len: None,
end: Token::TupleVariantEnd,
};
seed.deserialize(SeqAccessDeserializer::new(visitor))?
};
assert_next_token(self.de, Token::TupleVariantEnd)?;
Ok(value)
}
EnumFormat::Map => {
let value = {
let visitor = DeserializerMapVisitor {
de: self.de,
len: None,
end: Token::StructVariantEnd,
};
seed.deserialize(MapAccessDeserializer::new(visitor))?
};
assert_next_token(self.de, Token::StructVariantEnd)?;
Ok(value)
}
EnumFormat::Any => seed.deserialize(&mut *self.de),
}
}
}
struct BytesDeserializer {
value: &'static [u8],
}
impl<'de> de::Deserializer<'de> for BytesDeserializer {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::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
}
}
-43
View File
@@ -1,43 +0,0 @@
use std::error;
use std::fmt::{self, Display};
use serde::{de, ser};
#[derive(Clone, Debug)]
pub struct Error {
msg: String,
}
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error {
msg: msg.to_string(),
}
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error {
msg: msg.to_string(),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(&self.msg)
}
}
impl error::Error for Error {
fn description(&self) -> &str {
&self.msg
}
}
impl PartialEq<str> for Error {
fn eq(&self, other: &str) -> bool {
self.msg == other
}
}
-188
View File
@@ -1,188 +0,0 @@
//! This crate provides a convenient concise way to write unit tests for
//! implementations of [`Serialize`] and [`Deserialize`].
//!
//! [`Serialize`]: serde::ser::Serialize
//! [`Deserialize`]: serde::de::Deserialize
//!
//! The `Serialize` impl for a value can be characterized by the sequence of
//! [`Serializer`] calls that are made in the course of serializing the value,
//! so `serde_test` provides a [`Token`] abstraction which corresponds roughly
//! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to
//! test that a value serializes to a particular sequence of method calls, an
//! [`assert_de_tokens`] function to test that a value can be deserialized from
//! a particular sequence of method calls, and an [`assert_tokens`] function to
//! test both directions. There are also functions to test expected failure
//! conditions.
//!
//! [`Serializer`]: serde::ser::Serializer
//!
//! Here is an example from the [`linked-hash-map`] crate.
//!
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
//!
//! ```edition2021
//! # const IGNORE: &str = stringify! {
//! use linked_hash_map::LinkedHashMap;
//! # };
//! use serde_test::{assert_tokens, Token};
//!
//! # use std::fmt;
//! # use std::marker::PhantomData;
//! #
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
//! #
//! # // Dumb imitation of LinkedHashMap.
//! # #[derive(PartialEq, Debug)]
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
//! #
//! # impl<K, V> LinkedHashMap<K, V> {
//! # fn new() -> Self {
//! # LinkedHashMap(Vec::new())
//! # }
//! #
//! # fn insert(&mut self, k: K, v: V) {
//! # self.0.push((k, v));
//! # }
//! # }
//! #
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
//! # where
//! # K: Serialize,
//! # V: Serialize,
//! # {
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//! # where
//! # S: Serializer,
//! # {
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
//! # for &(ref k, ref v) in &self.0 {
//! # map.serialize_entry(k, v)?;
//! # }
//! # map.end()
//! # }
//! # }
//! #
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
//! #
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
//! # where
//! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # {
//! # type Value = LinkedHashMap<K, V>;
//! #
//! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result {
//! # unimplemented!()
//! # }
//! #
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
//! # where
//! # M: MapAccess<'de>,
//! # {
//! # let mut map = LinkedHashMap::new();
//! # while let Some((key, value)) = access.next_entry()? {
//! # map.insert(key, value);
//! # }
//! # Ok(map)
//! # }
//! # }
//! #
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
//! # where
//! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # {
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//! # where
//! # D: Deserializer<'de>,
//! # {
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
//! # }
//! # }
//! #
//! #[test]
//! # fn not_a_test_ser_de_empty() {}
//! fn test_ser_de_empty() {
//! let map = LinkedHashMap::<char, u32>::new();
//!
//! assert_tokens(
//! &map,
//! &[
//! Token::Map { len: Some(0) },
//! Token::MapEnd,
//! ],
//! );
//! }
//!
//! #[test]
//! # fn not_a_test_ser_de() {}
//! fn test_ser_de() {
//! let mut map = LinkedHashMap::new();
//! map.insert('b', 20);
//! map.insert('a', 10);
//! map.insert('c', 30);
//!
//! assert_tokens(
//! &map,
//! &[
//! Token::Map { len: Some(3) },
//! Token::Char('b'),
//! Token::I32(20),
//! Token::Char('a'),
//! Token::I32(10),
//! Token::Char('c'),
//! Token::I32(30),
//! Token::MapEnd,
//! ],
//! );
//! }
//! #
//! # fn main() {
//! # test_ser_de_empty();
//! # test_ser_de();
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.175")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy lints
#![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
)
)]
#[macro_use]
extern crate serde;
mod de;
mod error;
mod ser;
mod assert;
mod configure;
mod token;
pub use assert::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens,
};
pub use token::Token;
pub use configure::{Compact, Configure, Readable};
-462
View File
@@ -1,462 +0,0 @@
use serde::{ser, Serialize};
use error::Error;
use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of
/// tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
tokens: &'a [Token],
}
impl<'a> Serializer<'a> {
/// Creates the serializer.
pub fn new(tokens: &'a [Token]) -> Self {
Serializer { tokens: tokens }
}
/// Pulls the next token off of the serializer, ignoring it.
fn next_token(&mut self) -> Option<Token> {
if let Some((&first, rest)) = self.tokens.split_first() {
self.tokens = rest;
Some(first)
} else {
None
}
}
pub fn remaining(&self) -> usize {
self.tokens.len()
}
}
macro_rules! assert_next_token {
($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!($actual), "({:?})"), $v),
Token::$actual(v),
v == $v
);
}};
($ser:expr, $actual:ident { $($k:ident),* }) => {{
let compare = ($($k,)*);
let field_format = || {
use std::fmt::Write;
let mut buffer = String::new();
$(
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
)*
buffer
};
assert_next_token!(
$ser,
format_args!(concat!(stringify!($actual), " {{ {}}}"), field_format()),
Token::$actual { $($k),* },
($($k,)*) == compare
);
}};
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
match $ser.next_token() {
Some($pat) if $guard => {}
Some(expected) => return Err(ser::Error::custom(
format!("expected Token::{} but serialized as {}", expected, $actual)
)),
None => return Err(ser::Error::custom(
format!("expected end of tokens, but {} was serialized", $actual)
)),
}
};
}
impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Variant<'s, 'a>;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Variant<'s, 'a>;
fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_next_token!(self, Bool(v));
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_next_token!(self, I8(v));
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_next_token!(self, I16(v));
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_next_token!(self, I32(v));
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_next_token!(self, I64(v));
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_next_token!(self, U8(v));
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_next_token!(self, U16(v));
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_next_token!(self, U32(v));
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_next_token!(self, U64(v));
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_next_token!(self, F32(v));
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_next_token!(self, F64(v));
Ok(())
}
fn serialize_char(self, v: char) -> Result<(), Error> {
assert_next_token!(self, Char(v));
Ok(())
}
fn serialize_str(self, v: &str) -> Result<(), Error> {
match self.tokens.first() {
Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
Some(&Token::String(_)) => assert_next_token!(self, String(v)),
_ => assert_next_token!(self, Str(v)),
}
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
match self.tokens.first() {
Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
_ => assert_next_token!(self, Bytes(v)),
}
Ok(())
}
fn serialize_unit(self) -> Result<(), Error> {
assert_next_token!(self, Unit);
Ok(())
}
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
assert_next_token!(self, UnitStruct { name });
Ok(())
}
fn serialize_unit_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<(), Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
assert_next_token!(self, Unit);
} else {
assert_next_token!(self, UnitVariant { name, variant });
}
Ok(())
}
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
assert_next_token!(self, NewtypeStruct { name });
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<(), Error>
where
T: Serialize,
{
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
} else {
assert_next_token!(self, NewtypeVariant { name, variant });
}
value.serialize(self)
}
fn serialize_none(self) -> Result<(), Error> {
assert_next_token!(self, None);
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
assert_next_token!(self, Some);
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_next_token!(self, Seq { len });
Ok(self)
}
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_next_token!(self, Tuple { len });
Ok(self)
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_next_token!(self, TupleStruct { name, len });
Ok(self)
}
fn serialize_tuple_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Seq { len });
Ok(Variant {
ser: self,
end: Token::SeqEnd,
})
} else {
assert_next_token!(self, TupleVariant { name, variant, len });
Ok(Variant {
ser: self,
end: Token::TupleVariantEnd,
})
}
}
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
assert_next_token!(self, Map { len });
Ok(self)
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_next_token!(self, Struct { name, len });
Ok(self)
}
fn serialize_struct_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Map { len });
Ok(Variant {
ser: self,
end: Token::MapEnd,
})
} else {
assert_next_token!(self, StructVariant { name, variant, len });
Ok(Variant {
ser: self,
end: Token::StructVariantEnd,
})
}
}
fn is_human_readable(&self) -> bool {
panic!(
"Types which have different human-readable and compact representations \
must explicitly mark their test cases with `serde_test::Configure`"
);
}
}
pub struct Variant<'s, 'a: 's> {
ser: &'s mut Serializer<'a>,
end: Token,
}
impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, SeqEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, TupleEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, TupleStructEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Error> {
match self.end {
Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
_ => unreachable!(),
}
Ok(())
}
}
impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
key.serialize(&mut **self)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_next_token!(self, MapEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
key.serialize(&mut **self)?;
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_next_token!(self, StructEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
key.serialize(&mut *self.ser)?;
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Self::Error> {
match self.end {
Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
Token::MapEnd => assert_next_token!(self.ser, MapEnd),
_ => unreachable!(),
}
Ok(())
}
}
-561
View File
@@ -1,561 +0,0 @@
use std::fmt::{self, Debug, Display};
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Token {
/// A serialized `bool`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&true, &[Token::Bool(true)]);
/// ```
Bool(bool),
/// A serialized `i8`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i8, &[Token::I8(0)]);
/// ```
I8(i8),
/// A serialized `i16`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i16, &[Token::I16(0)]);
/// ```
I16(i16),
/// A serialized `i32`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i32, &[Token::I32(0)]);
/// ```
I32(i32),
/// A serialized `i64`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i64, &[Token::I64(0)]);
/// ```
I64(i64),
/// A serialized `u8`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u8, &[Token::U8(0)]);
/// ```
U8(u8),
/// A serialized `u16`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u16, &[Token::U16(0)]);
/// ```
U16(u16),
/// A serialized `u32`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u32, &[Token::U32(0)]);
/// ```
U32(u32),
/// A serialized `u64`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u64, &[Token::U64(0)]);
/// ```
U64(u64),
/// A serialized `f32`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f32, &[Token::F32(0.0)]);
/// ```
F32(f32),
/// A serialized `f64`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f64, &[Token::F64(0.0)]);
/// ```
F64(f64),
/// A serialized `char`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&'\n', &[Token::Char('\n')]);
/// ```
Char(char),
/// A serialized `str`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("transient");
/// assert_tokens(&s, &[Token::Str("transient")]);
/// ```
Str(&'static str),
/// A borrowed `str`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s: &str = "borrowed";
/// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]);
/// ```
BorrowedStr(&'static str),
/// A serialized `String`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("owned");
/// assert_tokens(&s, &[Token::String("owned")]);
/// ```
String(&'static str),
/// A serialized `[u8]`
Bytes(&'static [u8]),
/// A borrowed `[u8]`.
BorrowedBytes(&'static [u8]),
/// A serialized `ByteBuf`
ByteBuf(&'static [u8]),
/// A serialized `Option<T>` containing none.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = None::<char>;
/// assert_tokens(&opt, &[Token::None]);
/// ```
None,
/// The header to a serialized `Option<T>` containing some value.
///
/// The tokens of the value follow after this header.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = Some('c');
/// assert_tokens(&opt, &[Token::Some, Token::Char('c')]);
/// ```
Some,
/// A serialized `()`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&(), &[Token::Unit]);
/// ```
Unit,
/// A serialized unit struct of the given name.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct X;
///
/// assert_tokens(&X, &[Token::UnitStruct { name: "X" }]);
/// # }
/// ```
UnitStruct { name: &'static str },
/// A unit variant of an enum.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// A,
/// }
///
/// let a = E::A;
/// assert_tokens(
/// &a,
/// &[Token::UnitVariant {
/// name: "E",
/// variant: "A",
/// }],
/// );
/// # }
/// ```
UnitVariant {
name: &'static str,
variant: &'static str,
},
/// The header to a serialized newtype struct of the given name.
///
/// After this header is the value contained in the newtype struct.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct N(String);
///
/// let n = N("newtype".to_owned());
/// assert_tokens(
/// &n,
/// &[Token::NewtypeStruct { name: "N" }, Token::String("newtype")],
/// );
/// # }
/// ```
NewtypeStruct { name: &'static str },
/// The header to a newtype variant of an enum.
///
/// After this header is the value contained in the newtype variant.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// B(u8),
/// }
///
/// let b = E::B(0);
/// assert_tokens(
/// &b,
/// &[
/// Token::NewtypeVariant {
/// name: "E",
/// variant: "B",
/// },
/// Token::U8(0),
/// ],
/// );
/// # }
/// ```
NewtypeVariant {
name: &'static str,
variant: &'static str,
},
/// The header to a sequence.
///
/// After this header are the elements of the sequence, followed by
/// `SeqEnd`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let vec = vec!['a', 'b', 'c'];
/// assert_tokens(
/// &vec,
/// &[
/// Token::Seq { len: Some(3) },
/// Token::Char('a'),
/// Token::Char('b'),
/// Token::Char('c'),
/// Token::SeqEnd,
/// ],
/// );
/// ```
Seq { len: Option<usize> },
/// An indicator of the end of a sequence.
SeqEnd,
/// The header to a tuple.
///
/// After this header are the elements of the tuple, followed by `TupleEnd`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let tuple = ('a', 100);
/// assert_tokens(
/// &tuple,
/// &[
/// Token::Tuple { len: 2 },
/// Token::Char('a'),
/// Token::I32(100),
/// Token::TupleEnd,
/// ],
/// );
/// ```
Tuple { len: usize },
/// An indicator of the end of a tuple.
TupleEnd,
/// The header to a tuple struct.
///
/// After this header are the fields of the tuple struct, followed by
/// `TupleStructEnd`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct T(u8, u8);
///
/// let t = T(0, 0);
/// assert_tokens(
/// &t,
/// &[
/// Token::TupleStruct { name: "T", len: 2 },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleStructEnd,
/// ],
/// );
/// # }
/// ```
TupleStruct { name: &'static str, len: usize },
/// An indicator of the end of a tuple struct.
TupleStructEnd,
/// The header to a tuple variant of an enum.
///
/// After this header are the fields of the tuple variant, followed by
/// `TupleVariantEnd`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// C(u8, u8),
/// }
///
/// let c = E::C(0, 0);
/// assert_tokens(
/// &c,
/// &[
/// Token::TupleVariant {
/// name: "E",
/// variant: "C",
/// len: 2,
/// },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleVariantEnd,
/// ],
/// );
/// # }
/// ```
TupleVariant {
name: &'static str,
variant: &'static str,
len: usize,
},
/// An indicator of the end of a tuple variant.
TupleVariantEnd,
/// The header to a map.
///
/// After this header are the entries of the map, followed by `MapEnd`.
///
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert('A', 65);
/// map.insert('Z', 90);
///
/// assert_tokens(
/// &map,
/// &[
/// Token::Map { len: Some(2) },
/// Token::Char('A'),
/// Token::I32(65),
/// Token::Char('Z'),
/// Token::I32(90),
/// Token::MapEnd,
/// ],
/// );
/// ```
Map { len: Option<usize> },
/// An indicator of the end of a map.
MapEnd,
/// The header of a struct.
///
/// After this header are the fields of the struct, followed by `StructEnd`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
/// b: u8,
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// # }
/// ```
Struct { name: &'static str, len: usize },
/// An indicator of the end of a struct.
StructEnd,
/// The header of a struct variant of an enum.
///
/// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// D { d: u8 },
/// }
///
/// let d = E::D { d: 0 };
/// assert_tokens(
/// &d,
/// &[
/// Token::StructVariant {
/// name: "E",
/// variant: "D",
/// len: 1,
/// },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::StructVariantEnd,
/// ],
/// );
/// # }
/// ```
StructVariant {
name: &'static str,
variant: &'static str,
len: usize,
},
/// An indicator of the end of a struct variant.
StructVariantEnd,
/// The header to an enum of the given name.
///
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// enum E {
/// A,
/// B(u8),
/// C(u8, u8),
/// D { d: u8 },
/// }
///
/// let a = E::A;
/// assert_tokens(
/// &a,
/// &[Token::Enum { name: "E" }, Token::Str("A"), Token::Unit],
/// );
///
/// let b = E::B(0);
/// assert_tokens(
/// &b,
/// &[Token::Enum { name: "E" }, Token::Str("B"), Token::U8(0)],
/// );
///
/// let c = E::C(0, 0);
/// assert_tokens(
/// &c,
/// &[
/// Token::Enum { name: "E" },
/// Token::Str("C"),
/// Token::Seq { len: Some(2) },
/// Token::U8(0),
/// Token::U8(0),
/// Token::SeqEnd,
/// ],
/// );
///
/// let d = E::D { d: 0 };
/// assert_tokens(
/// &d,
/// &[
/// Token::Enum { name: "E" },
/// Token::Str("D"),
/// Token::Map { len: Some(1) },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::MapEnd,
/// ],
/// );
/// # }
/// ```
Enum { name: &'static str },
}
impl Display for Token {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(self, formatter)
}
}
+1 -1
View File
@@ -17,5 +17,5 @@ fnv = "1.0"
rustversion = "1.0"
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" }
serde_test = "1.0.176"
trybuild = { version = "1.0.66", features = ["diff"] }
+1
View File
@@ -1,3 +1,4 @@
#![allow(internal_features)]
#![feature(lang_items, start)]
#![no_std]
+450 -336
View File
@@ -13,16 +13,14 @@
use serde::de::{self, Deserialize, Deserializer, IgnoredAny, MapAccess, Unexpected, Visitor};
use serde::ser::{Serialize, Serializer};
use serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fmt;
use std::marker::PhantomData;
use serde_test::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens, Token,
};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fmt;
use std::marker::PhantomData;
trait MyDefault: Sized {
fn my_default() -> Self;
@@ -116,42 +114,6 @@ struct CollectOther {
extra: HashMap<String, u32>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructEnumWrapper {
#[serde(flatten)]
data: FlattenStructEnum,
#[serde(flatten)]
extra: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum FlattenStructEnum {
InsertInteger { index: u32, value: u32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumWrapper {
outer: u32,
#[serde(flatten)]
data: FlattenStructTagContentEnumNewtype,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
enum FlattenStructTagContentEnum {
InsertInteger { index: u32, value: u32 },
NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtypeVariant {
value: u32,
}
#[test]
fn test_default_struct() {
assert_de_tokens(
@@ -643,7 +605,7 @@ fn test_unknown_field_rename_struct() {
Token::Str("a4"),
Token::I32(3),
],
"unknown field `a4`, expected one of `a1`, `a3`, `a2`, `a5`, `a6`",
"unknown field `a4`, expected one of `a1`, `a2`, `a3`, `a5`, `a6`",
);
}
@@ -837,7 +799,7 @@ fn test_unknown_field_rename_enum() {
Token::Str("d"),
Token::I8(2),
],
"unknown field `d`, expected one of `a`, `c`, `b`, `e`, `f`",
"unknown field `d`, expected one of `a`, `b`, `c`, `e`, `f`",
);
}
@@ -1645,149 +1607,6 @@ fn test_collect_other() {
);
}
#[test]
fn test_flatten_struct_enum() {
let mut extra = HashMap::new();
extra.insert("extra_key".into(), "extra value".into());
let change_request = FlattenStructEnumWrapper {
data: FlattenStructEnum::InsertInteger {
index: 0,
value: 42,
},
extra,
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("insert_integer"),
Token::Map { len: None },
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::MapEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("insert_integer"),
Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_struct_tag_content_enum() {
let change_request = FlattenStructTagContentEnumWrapper {
outer: 42,
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
index: 0,
value: 42,
}),
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("insert_integer"),
Token::Str("value"),
Token::Map { len: None },
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::MapEnd,
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("insert_integer"),
Token::Str("value"),
Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_struct_tag_content_enum_newtype() {
let change_request = FlattenStructTagContentEnumWrapper {
outer: 42,
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
FlattenStructTagContentEnumNewtypeVariant { value: 23 },
)),
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("newtype_variant"),
Token::Str("value"),
Token::Map { len: None },
Token::Str("value"),
Token::U32(23),
Token::MapEnd,
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("newtype_variant"),
Token::Str("value"),
Token::Struct {
len: 1,
name: "FlattenStructTagContentEnumNewtypeVariant",
},
Token::Str("value"),
Token::U32(23),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_unknown_field_in_flatten() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -2144,86 +1963,6 @@ fn test_lifetime_propagation_for_flatten() {
);
}
#[test]
fn test_flatten_enum_newtype() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
flat: E,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum E {
Q(HashMap<String, String>),
}
let e = E::Q({
let mut map = HashMap::new();
map.insert("k".to_owned(), "v".to_owned());
map
});
let s = S { flat: e };
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("Q"),
Token::Map { len: Some(1) },
Token::Str("k"),
Token::Str("v"),
Token::MapEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_internally_tagged() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
let s = S {
x: X::B { b: 1 },
y: Y::D { d: 2 },
};
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn test_externally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -2262,6 +2001,39 @@ fn test_externally_tagged_enum_containing_flatten() {
);
}
#[test]
fn test_internally_tagged_enum_with_skipped_conflict() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t")]
enum Data {
A,
#[serde(skip)]
#[allow(dead_code)]
B {
t: String,
},
C {
#[serde(default, skip)]
t: String,
},
}
let data = Data::C { t: String::new() };
assert_tokens(
&data,
&[
Token::Struct {
name: "Data",
len: 1,
},
Token::Str("t"),
Token::Str("C"),
Token::StructEnd,
],
);
}
#[test]
fn test_internally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -2336,7 +2108,10 @@ fn test_adjacently_tagged_enum_bytes() {
len: 2,
},
Token::Str("t"),
Token::Str("A"),
Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Str("c"),
Token::Struct { name: "A", len: 1 },
Token::Str("a"),
@@ -2354,7 +2129,10 @@ fn test_adjacently_tagged_enum_bytes() {
len: 2,
},
Token::Bytes(b"t"),
Token::Str("A"),
Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Bytes(b"c"),
Token::Struct { name: "A", len: 1 },
Token::Str("a"),
@@ -2395,7 +2173,10 @@ fn test_adjacently_tagged_enum_containing_flatten() {
len: 2,
},
Token::Str("t"),
Token::Str("A"),
Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Str("c"),
Token::Map { len: None },
Token::Str("a"),
@@ -2600,32 +2381,65 @@ fn test_partially_untagged_enum_desugared() {
}
#[test]
fn test_flatten_untagged_enum() {
fn test_partially_untagged_internally_tagged_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Outer {
#[serde(flatten)]
inner: Inner,
#[serde(tag = "t")]
enum Data {
A,
B,
#[serde(untagged)]
Var(u32),
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Inner {
Variant { a: i32 },
}
let data = Data::A;
let data = Outer {
inner: Inner::Variant { a: 0 },
};
assert_tokens(
assert_de_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("t"),
Token::Str("A"),
Token::MapEnd,
],
);
let data = Data::Var(42);
assert_de_tokens(&data, &[Token::U32(42)]);
// TODO test error output
}
#[test]
fn test_partially_untagged_adjacently_tagged_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t", content = "c")]
enum Data {
A(u32),
B,
#[serde(untagged)]
Var(u32),
}
let data = Data::A(7);
assert_de_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("t"),
Token::Str("A"),
Token::Str("c"),
Token::U32(7),
Token::MapEnd,
],
);
let data = Data::Var(42);
assert_de_tokens(&data, &[Token::U32(42)]);
// TODO test error output
}
#[test]
@@ -2784,48 +2598,6 @@ fn test_internally_tagged_unit_enum_with_unknown_fields() {
);
}
#[test]
fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
#[derive(Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A,
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
B { c: u32 },
}
let s = S {
x: X::A,
y: Y::B { c: 0 },
};
assert_de_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("A"),
Token::Str("typeY"),
Token::Str("B"),
Token::Str("c"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_any_after_flatten_struct() {
#[derive(PartialEq, Debug)]
@@ -3009,7 +2781,7 @@ fn test_expecting_message_externally_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>(
&[Token::Enum { name: "Enum" }, Token::Unit],
r#"invalid type: unit value, expected variant identifier"#,
"invalid type: unit value, expected variant identifier",
);
}
@@ -3030,7 +2802,7 @@ fn test_expecting_message_internally_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>(
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
r#"invalid type: unit value, expected variant identifier"#,
"invalid type: unit value, expected variant identifier",
);
}
@@ -3056,7 +2828,7 @@ fn test_expecting_message_adjacently_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>(
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
r#"invalid type: unit value, expected variant identifier"#,
"invalid type: unit value, expected variant of enum Enum",
);
}
@@ -3069,7 +2841,7 @@ fn test_expecting_message_untagged_tagged_enum() {
Untagged,
}
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], "something strange...");
}
#[test]
@@ -3090,7 +2862,7 @@ fn test_expecting_message_identifier_enum() {
assert_de_tokens_error::<FieldEnum>(
&[Token::Unit],
r#"invalid type: unit value, expected something strange..."#,
"invalid type: unit value, expected something strange...",
);
assert_de_tokens_error::<FieldEnum>(
@@ -3099,12 +2871,12 @@ fn test_expecting_message_identifier_enum() {
Token::Str("Unknown"),
Token::None,
],
r#"invalid type: map, expected something strange..."#,
"invalid type: map, expected something strange...",
);
assert_de_tokens_error::<VariantEnum>(
&[Token::Unit],
r#"invalid type: unit value, expected something strange..."#,
"invalid type: unit value, expected something strange...",
);
assert_de_tokens_error::<VariantEnum>(
@@ -3115,6 +2887,348 @@ fn test_expecting_message_identifier_enum() {
Token::Str("Unknown"),
Token::None,
],
r#"invalid type: map, expected something strange..."#,
"invalid type: map, expected something strange...",
);
}
mod flatten {
use super::*;
mod enum_ {
use super::*;
mod externally_tagged {
use super::*;
use std::iter::FromIterator;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
data: Enum,
#[serde(flatten)]
extra: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum Enum {
Newtype(HashMap<String, String>),
Tuple(u32, u32),
Struct { index: u32, value: u32 },
}
#[test]
fn newtype() {
assert_tokens(
&Flatten {
data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])),
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Newtype"), // variant
Token::Map { len: Some(1) },
Token::Str("key"),
Token::Str("value"),
Token::MapEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
// Content::Seq case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn tuple() {
assert_tokens(
&Flatten {
data: Enum::Tuple(0, 42),
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Tuple"), // variant
Token::Seq { len: Some(2) },
Token::U32(0),
Token::U32(42),
Token::SeqEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Seq case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn struct_from_seq() {
assert_de_tokens(
&Flatten {
data: Enum::Struct {
index: 0,
value: 42,
},
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Struct"), // variant
Token::Seq { len: Some(2) },
Token::U32(0), // index
Token::U32(42), // value
Token::SeqEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Map case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn struct_from_map() {
assert_tokens(
&Flatten {
data: Enum::Struct {
index: 0,
value: 42,
},
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Struct"), // variant
Token::Struct {
len: 2,
name: "Struct",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
}
mod adjacently_tagged {
use super::*;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
outer: u32,
#[serde(flatten)]
data: NewtypeWrapper,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NewtypeWrapper(pub Enum);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "tag", content = "content")]
enum Enum {
Newtype(NewtypeVariant),
Struct { index: u32, value: u32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NewtypeVariant {
value: u32,
}
#[test]
fn struct_() {
assert_tokens(
&Flatten {
outer: 42,
data: NewtypeWrapper(Enum::Struct {
index: 0,
value: 42,
}),
},
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("tag"),
Token::UnitVariant {
name: "Enum",
variant: "Struct",
},
Token::Str("content"),
Token::Struct {
len: 2,
name: "Struct",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn newtype() {
assert_tokens(
&Flatten {
outer: 42,
data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })),
},
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("tag"),
Token::UnitVariant {
name: "Enum",
variant: "Newtype",
},
Token::Str("content"),
Token::Struct {
len: 1,
name: "NewtypeVariant",
},
Token::Str("value"),
Token::U32(23),
Token::StructEnd,
Token::MapEnd,
],
);
}
}
mod internally_tagged {
use super::*;
#[test]
fn structs() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
assert_tokens(
&Flatten {
x: X::B { b: 1 },
y: Y::D { d: 2 },
},
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn unit_enum_with_unknown_fields() {
#[derive(Debug, PartialEq, Deserialize)]
struct Flatten {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "typeX")]
enum X {
A,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "typeY")]
enum Y {
B { c: u32 },
}
assert_de_tokens(
&Flatten {
x: X::A,
y: Y::B { c: 0 },
},
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("A"),
Token::Str("typeY"),
Token::Str("B"),
Token::Str("c"),
Token::I32(0),
Token::MapEnd,
],
);
}
}
mod untagged {
use super::*;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
data: Enum,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum Enum {
Struct { a: i32 },
}
#[test]
fn struct_() {
assert_tokens(
&Flatten {
data: Enum::Struct { a: 0 },
},
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::MapEnd,
],
);
}
}
}
}
-1
View File
@@ -8,7 +8,6 @@ use serde::de::value::{BorrowedStrDeserializer, MapDeserializer};
use serde::de::{Deserialize, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
use std::borrow::Cow;
#[test]
+6 -8
View File
@@ -10,6 +10,10 @@
)]
#![cfg_attr(feature = "unstable", feature(never_type))]
use fnv::FnvHasher;
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, Configure, Token};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::default::Default;
use std::ffi::{CStr, CString, OsString};
@@ -27,16 +31,10 @@ use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize, Ordering,
};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(target_arch = "x86_64")]
use std::sync::atomic::{AtomicI64, AtomicU64};
use fnv::FnvHasher;
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, Configure, Token};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[macro_use]
mod macros;
+1 -2
View File
@@ -23,7 +23,6 @@
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
use serde::ser::{Serialize, Serializer};
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
use std::marker::PhantomData;
use std::option::Option as StdOption;
@@ -844,7 +843,7 @@ pub fn is_zero(n: &u8) -> bool {
*n == 0
}
fn vec_first_element<T, S>(vec: &Vec<T>, serializer: S) -> StdResult<S::Ok, S::Error>
fn vec_first_element<T, S>(vec: &[T], serializer: S) -> StdResult<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
+158 -58
View File
@@ -3,86 +3,186 @@
#![allow(clippy::derive_partial_eq_without_eq)]
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, Token};
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
mod variant_identifier {
use super::*;
#[test]
fn test_variant_identifier() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(variant_identifier)]
enum V {
Aaa,
#[serde(alias = "Ccc", alias = "Ddd")]
Bbb,
}
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
#[test]
fn variant1() {
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
}
#[test]
fn aliases() {
assert_de_tokens(&V::Bbb, &[Token::U8(1)]);
assert_de_tokens(&V::Bbb, &[Token::U16(1)]);
assert_de_tokens(&V::Bbb, &[Token::U32(1)]);
assert_de_tokens(&V::Bbb, &[Token::U64(1)]);
assert_de_tokens(&V::Bbb, &[Token::Str("Bbb")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Bbb")]);
assert_de_tokens(&V::Bbb, &[Token::Str("Ccc")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ccc")]);
assert_de_tokens(&V::Bbb, &[Token::Str("Ddd")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ddd")]);
}
#[test]
fn unknown() {
assert_de_tokens_error::<V>(
&[Token::U8(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U16(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U32(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U64(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::Str("Unknown")],
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
);
assert_de_tokens_error::<V>(
&[Token::Bytes(b"Unknown")],
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
);
}
}
#[test]
fn test_field_identifier() {
mod field_identifier {
use super::*;
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
#[serde(alias = "ccc", alias = "ddd")]
Bbb,
}
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
}
#[test]
fn test_unit_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
#[serde(other)]
Other,
#[test]
fn field1() {
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
}
assert_de_tokens(&F::Other, &[Token::U8(42)]);
assert_de_tokens(&F::Other, &[Token::U16(42)]);
assert_de_tokens(&F::Other, &[Token::U32(42)]);
assert_de_tokens(&F::Other, &[Token::U64(42)]);
assert_de_tokens(&F::Other, &[Token::Str("x")]);
}
#[test]
fn aliases() {
assert_de_tokens(&F::Bbb, &[Token::U8(1)]);
assert_de_tokens(&F::Bbb, &[Token::U16(1)]);
assert_de_tokens(&F::Bbb, &[Token::U32(1)]);
assert_de_tokens(&F::Bbb, &[Token::U64(1)]);
#[test]
fn test_newtype_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
Other(String),
assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]);
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]);
assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]);
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]);
assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]);
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]);
}
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
#[test]
fn test_newtype_fallthrough_generic() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F<T> {
Aaa,
Bbb,
Other(T),
#[test]
fn unknown() {
assert_de_tokens_error::<F>(
&[Token::U8(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U16(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U32(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U64(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::Str("unknown")],
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
);
assert_de_tokens_error::<F>(
&[Token::Bytes(b"unknown")],
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
);
}
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
#[test]
fn unit_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
#[serde(other)]
Other,
}
assert_de_tokens(&F::Other, &[Token::U8(42)]);
assert_de_tokens(&F::Other, &[Token::U16(42)]);
assert_de_tokens(&F::Other, &[Token::U32(42)]);
assert_de_tokens(&F::Other, &[Token::U64(42)]);
assert_de_tokens(&F::Other, &[Token::Str("x")]);
}
#[test]
fn newtype_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
Other(String),
}
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
#[test]
fn newtype_fallthrough_generic() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F<T> {
Aaa,
Bbb,
Other(T),
}
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
}
+155 -20
View File
@@ -12,7 +12,6 @@ use serde_derive::{Deserialize, Serialize};
use serde_test::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token,
};
use std::collections::BTreeMap;
use std::marker::PhantomData;
@@ -473,7 +472,10 @@ fn test_adjacently_tagged_newtype_struct() {
},
Token::U32(5),
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "E",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1067,7 +1069,10 @@ fn test_adjacently_tagged_enum() {
len: 1,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd,
],
);
@@ -1081,7 +1086,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd,
],
);
@@ -1095,7 +1103,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"),
Token::Unit,
Token::StructEnd,
@@ -1113,7 +1124,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("c"),
Token::Unit,
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd,
],
);
@@ -1129,7 +1143,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("f"),
Token::Unit,
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("g"),
Token::Unit,
Token::Str("c"),
@@ -1149,7 +1166,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::Str("c"),
Token::U8(1),
Token::StructEnd,
@@ -1167,7 +1187,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("c"),
Token::U8(1),
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1181,7 +1204,10 @@ fn test_adjacently_tagged_enum() {
len: 1,
},
Token::Str("t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1195,7 +1221,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Tuple"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Tuple",
},
Token::Str("c"),
Token::Tuple { len: 2 },
Token::U8(1),
@@ -1219,7 +1248,10 @@ fn test_adjacently_tagged_enum() {
Token::U8(1),
Token::TupleEnd,
Token::Str("t"),
Token::Str("Tuple"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Tuple",
},
Token::StructEnd,
],
);
@@ -1233,7 +1265,10 @@ fn test_adjacently_tagged_enum() {
len: 2,
},
Token::Str("t"),
Token::Str("Struct"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Struct",
},
Token::Str("c"),
Token::Struct {
name: "Struct",
@@ -1263,7 +1298,10 @@ fn test_adjacently_tagged_enum() {
Token::U8(1),
Token::StructEnd,
Token::Str("t"),
Token::Str("Struct"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Struct",
},
Token::StructEnd,
],
);
@@ -1279,7 +1317,10 @@ fn test_adjacently_tagged_enum() {
Token::U64(1), // content field
Token::U8(1),
Token::U64(0), // tag field
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1295,7 +1336,10 @@ fn test_adjacently_tagged_enum() {
Token::Bytes(b"c"),
Token::U8(1),
Token::Bytes(b"t"),
Token::Str("Newtype"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd,
],
);
@@ -1317,7 +1361,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"),
Token::Unit,
Token::StructEnd,
@@ -1331,7 +1378,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"),
Token::Unit,
Token::Str("h"),
@@ -1370,7 +1420,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::U64(3),
],
r#"invalid value: integer `3`, expected "t" or "c""#,
@@ -1430,6 +1483,9 @@ fn test_enum_in_internally_tagged_enum() {
],
);
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
// Content::Seq case
// via ContentDeserializer::deserialize_enum
assert_tokens(
&Outer::Inner(Inner::Tuple(1, 1)),
&[
@@ -1448,6 +1504,9 @@ fn test_enum_in_internally_tagged_enum() {
],
);
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Map case
// via ContentDeserializer::deserialize_enum
assert_tokens(
&Outer::Inner(Inner::Struct { f: 1 }),
&[
@@ -1465,6 +1524,23 @@ fn test_enum_in_internally_tagged_enum() {
Token::MapEnd,
],
);
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Seq case
// via ContentDeserializer::deserialize_enum
assert_de_tokens(
&Outer::Inner(Inner::Struct { f: 1 }),
&[
Token::Map { len: Some(2) },
Token::Str("type"),
Token::Str("Inner"),
Token::Str("Struct"),
Token::Seq { len: Some(1) },
Token::U8(1), // f
Token::SeqEnd,
Token::MapEnd,
],
);
}
#[test]
@@ -1543,7 +1619,10 @@ fn test_internally_tagged_struct_with_flattened_field() {
Token::Str("tag_struct"),
Token::Str("Struct"),
Token::Str("tag_enum"),
Token::Str("A"),
Token::UnitVariant {
name: "Enum",
variant: "A",
},
Token::Str("content"),
Token::U64(0),
Token::MapEnd,
@@ -1924,6 +2003,62 @@ fn test_rename_all() {
);
}
#[test]
fn test_rename_all_fields() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all_fields = "kebab-case")]
enum E {
V1,
V2(bool),
V3 {
a_field: bool,
another_field: bool,
#[serde(rename = "last-field")]
yet_another_field: bool,
},
#[serde(rename_all = "snake_case")]
V4 {
a_field: bool,
},
}
assert_tokens(
&E::V3 {
a_field: true,
another_field: true,
yet_another_field: true,
},
&[
Token::StructVariant {
name: "E",
variant: "V3",
len: 3,
},
Token::Str("a-field"),
Token::Bool(true),
Token::Str("another-field"),
Token::Bool(true),
Token::Str("last-field"),
Token::Bool(true),
Token::StructVariantEnd,
],
);
assert_tokens(
&E::V4 { a_field: true },
&[
Token::StructVariant {
name: "E",
variant: "V4",
len: 1,
},
Token::Str("a_field"),
Token::Bool(true),
Token::StructVariantEnd,
],
);
}
#[test]
fn test_untagged_newtype_variant_containing_unit_struct_not_map() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
+20
View File
@@ -125,6 +125,9 @@ struct Test {
#[serde(with = "EnumConcrete")]
enum_concrete: remote::EnumGeneric<u8>,
#[serde(with = "ErrorKindDef")]
io_error_kind: ErrorKind,
}
#[derive(Serialize, Deserialize)]
@@ -197,6 +200,23 @@ enum EnumConcrete {
Variant(u8),
}
#[derive(Debug)]
enum ErrorKind {
NotFound,
PermissionDenied,
#[allow(dead_code)]
ConnectionRefused,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "ErrorKind")]
#[non_exhaustive]
enum ErrorKindDef {
NotFound,
PermissionDenied,
// ...
}
impl From<PrimitivePrivDef> for remote::PrimitivePriv {
fn from(def: PrimitivePrivDef) -> Self {
remote::PrimitivePriv::new(def.0)
-1
View File
@@ -1,5 +1,4 @@
use serde_test::{assert_tokens, Configure, Token};
use std::net;
#[macro_use]
+7 -9
View File
@@ -1,6 +1,9 @@
#![allow(clippy::derive_partial_eq_without_eq, clippy::unreadable_literal)]
#![cfg_attr(feature = "unstable", feature(never_type))]
use fnv::FnvHasher;
use serde_derive::Serialize;
use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token};
use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::ffi::CString;
@@ -9,21 +12,16 @@ use std::num::Wrapping;
use std::ops::Bound;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak};
#[cfg(unix)]
use std::str;
use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize,
};
use std::sync::{Arc, Mutex, RwLock, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(unix)]
use std::str;
#[cfg(target_arch = "x86_64")]
use std::sync::atomic::{AtomicI64, AtomicU64};
use fnv::FnvHasher;
use serde_derive::Serialize;
use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token};
use std::sync::{Arc, Mutex, RwLock, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[macro_use]
mod macros;

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