Compare commits

...

546 Commits

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

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

I find this number more understandable than 0x1000.
2018-01-26 00:19:26 -08:00
David Tolnay 1bdf5ecec4 Ignore unused_parens warning on the proc macro workaround 2018-01-21 17:54:06 -08:00
David Tolnay 59017aa19b Follow clippy's replace_consts lint 2018-01-15 17:40:32 -08:00
David Tolnay 6b4625dcbb Ignore warning in no_std test 2018-01-13 14:43:34 -08:00
David Tolnay 6e01f220b1 Ignore clippy flagging our workaround 2018-01-13 14:28:12 -08:00
David Tolnay 64573319f9 Meaningful spans when invoking deserializer trait methods 2018-01-10 20:59:48 -08:00
David Tolnay 3d64df6e87 Meaningful span for attrs parsed from string literal 2018-01-10 19:59:49 -08:00
David Tolnay cc2558b0dc Meaningful spans when invoking serializer trait methods 2018-01-10 19:22:07 -08:00
David Tolnay 5c41661bce Merge pull request #1140 from serde-rs/hygiene
Hygiene fixes
2018-01-09 22:39:23 -08:00
David Tolnay dd6914a203 Build the test suite in CI using proc-macro2/nightly 2018-01-09 22:23:19 -08:00
David Tolnay 63623eb3b3 Hygiene fixes 2018-01-09 22:22:08 -08:00
David Tolnay ddc4b50d4d Use call_site in 'with' attribute 2018-01-09 20:34:29 -08:00
David Tolnay b313f947dc Use call_site as the span of unnamed member access 2018-01-09 20:28:23 -08:00
David Tolnay 16bc9fb99e Address clippy lints in serde_derive 2018-01-09 19:40:34 -08:00
David Tolnay 34eaab00f7 Address clippy lints in serde_derive_internals 2018-01-09 19:40:33 -08:00
David Tolnay 6024e717fb Merge pull request #1138 from serde-rs/syn
Update to syn 0.12
2018-01-09 19:23:19 -08:00
David Tolnay ef4dd6c0ec Update to syn 0.12 2018-01-09 19:05:08 -08:00
David Tolnay f7ed967db1 Merge pull request #1135 from mcgoo/appveyor-tls
get rustup-init with curl to avoid tls failures
2018-01-04 20:55:53 -08:00
mcgoo 613e46b0ee get rustup-init with curl to avoid tls failures 2018-01-04 22:04:16 -06:00
David Tolnay b2d2e96267 Merge pull request #1133 from martinlindhe/master
fix some typos
2018-01-03 07:44:40 -08:00
Martin Lindhe ae0373643c fix some typos 2018-01-03 15:16:45 +01:00
David Tolnay 7aeabddd2f Release 1.0.27 2017-12-30 22:19:41 -05:00
David Tolnay 9df8f5ecc0 Merge pull request #1132 from Lireer/uppercase
Add UPPERCASE to rename_all
2017-12-30 22:18:20 -05:00
Carl Scherer c4fad2883b Add UPPERCASE to rename_all 2017-12-31 03:12:00 +01:00
David Tolnay 9cfcd78c87 Release 1.0.26 2017-12-27 17:33:32 -05:00
David Tolnay 4751627f1c Implement De/Serialize for PhantomData where T: ?Sized 2017-12-27 17:32:49 -05:00
David Tolnay ae59c6b6d2 Release 1.0.25 2017-12-23 23:33:59 -05:00
David Tolnay 4973d7a62d Suppress errors on rustfmt line overflow
Some of the serde_derive lines inside of quote!(...) are too long. Rustfmt
cannot fix these. Will need to follow up.
2017-12-23 20:27:56 -08:00
David Tolnay ed6a1de311 Auto format attributes on their own line 2017-12-23 20:24:57 -08:00
David Tolnay ab234be025 The rustfmt rfc style is now the default 2017-12-23 20:21:52 -08:00
David Tolnay ee75e6c0e9 Format with rustfmt-nightly 0.3.4 2017-12-23 20:17:52 -08:00
David Tolnay c2b390fe63 Merge pull request #1124 from serde-rs/in-place
Rename deserialize_from to deserialize_in_place
2017-12-23 19:56:29 -08:00
David Tolnay 56d5d7f761 Rename deserialize_from to deserialize_in_place 2017-12-17 10:46:44 -08:00
David Tolnay 0b89bc920e Merge pull request #1094 from Gankro/deserialize_from
Add and derive deserialize_from
2017-12-11 21:29:15 -08:00
David Tolnay 0dac13e4db Resolve conflict with pr 1115 2017-12-11 20:59:54 -08:00
David Tolnay 0c2e91f28a Merge branch serde-rs/master into Gankro/deserialize_from 2017-12-11 20:49:23 -08:00
David Tolnay 13e7bee0e6 Eliminate need for unwrap in deserialize_from_seq 2017-12-11 18:13:13 -08:00
David Tolnay 65104aca9c Remove need for allow(unreachable_code) 2017-12-11 17:55:23 -08:00
David Tolnay 9360094ba7 Revert main_body naming change
The naming here isn't great but no need to change it in this PR.
2017-12-10 23:19:31 -08:00
David Tolnay 3700779bfa More meaningful names and types for nop_reserve 2017-12-10 23:18:08 -08:00
David Tolnay d9e894911f Move all the deserialize_from derive code behind flag 2017-12-10 23:15:14 -08:00
David Tolnay 85e3ddc2b8 Less indentiation in deserialize_from_body 2017-12-10 23:04:44 -08:00
David Tolnay ccae35d92a Do not emit deserialize_from if every field has deserialize_with 2017-12-10 22:55:28 -08:00
David Tolnay 61ca928325 Can never see getters in a deserialize_from 2017-12-10 22:46:46 -08:00
David Tolnay a93f2ebff0 Enable deserialize_from in the test suite 2017-12-10 22:46:25 -08:00
David Tolnay a45f1ae915 Remove unused dev-dependency of serde_test on deserialize_from 2017-12-10 22:02:11 -08:00
David Tolnay 9641978481 Hide deserialize_from 2017-12-10 21:55:07 -08:00
David Tolnay ffd2017c6f Use the default deserialize_from for Option<T>
The custom one was functionally identical to the default implementation given by
the Deserialize trait. If someone has benchmarks that the custom one performs
better, we can put it back.
2017-12-10 21:27:44 -08:00
David Tolnay b7eb42aa6b Release 1.0.24 2017-12-09 14:43:55 -08:00
David Tolnay 750f8ba299 Clean up trailing whitespace 2017-12-09 14:42:59 -08:00
David Tolnay 49cdef074d Merge pull request #1115 from Binero/master
Solved #1105.
2017-12-08 08:57:31 -08:00
Jeroen Bollen aa86b04714 Adressed concerns raised by @oli-obk.
Specifically:
 - Change identation in `de.rs`.
 - Make `attr::Field` take a `attr::Default` as opposed to the entire parent `attr::Container`.
2017-12-08 15:13:05 +01:00
Jeroen Bollen c887a0b472 Solved #1105.
When a field should be skipped during deserialization, it will not use its own Default implementation
when the container structure has `#[serde(default)]` set.
2017-12-06 21:14:02 +01:00
Alexis Beingessner 34936be574 test deserialize_from 2017-12-04 13:29:03 -05:00
Alexis Beingessner e354dd0c7f Derive deserialize_from for tuples and structs
This adds a new "deserialize_from" feature (default off) that opts into
deriving deserialize_from with #[derive(Deserialize)].
2017-12-04 13:23:26 -05:00
Alexis Beingessner bc221abb04 Augment builtin std/core Deserialize impls to implement deserialize_from 2017-12-04 13:23:26 -05:00
Alexis Beingessner ab5e8780ab Add deserialize_from to Deserialize 2017-12-04 13:23:26 -05:00
David Tolnay 0c34e06e51 Merge pull request #1106 from khuey/inlines
Inline various deserialization helper methods.
2017-12-02 15:57:07 -08:00
Kyle Huey 4a0c4e0c25 Mark size_hint::cautious as inline. 2017-12-01 14:31:52 -08:00
David Tolnay 8c34e0940f Release 1.0.23 2017-11-29 22:26:32 -08:00
David Tolnay eb6bf16a51 Revert "Catch wrong field names length in serde_test"
There are at least two reasonable things to expect the len field to
check: the length of the fields array passed to deserialize_struct, or
the number of field tokens. Even beyond these, in some cases it can be
useful to test deserialization with a bogus len to test how the
Deserialize impl reacts to an incorrect size_hint.

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

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

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

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

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

This pull request fixes the issue by allowing
`ContentDeserializer` and `ContentRefDeserializer` to
deserialize sequence-encoded struct enum variant data.
2017-11-15 21:56:33 -08:00
David Tolnay 4773863e3a Release 1.0.20 2017-11-12 10:29:08 -08:00
David Tolnay 80cd9c7617 Merge pull request #1091 from serde-rs/fields-len
Catch wrong field names length in serde_test
2017-11-12 10:28:26 -08:00
David Tolnay 436cafb0a3 Catch wrong field names length in serde_test 2017-11-12 10:16:43 -08:00
David Tolnay 98bb02e9b4 Whitelist use of Debug in serde_test 2017-11-07 10:00:18 -08:00
David Tolnay 142439088c Merge pull request #1086 from Marwes/better_errors
Print the contents of the expected token when a serialize assert fails
2017-11-07 09:53:58 -08:00
Markus Westerlind ce81288235 Print the contents of the expected token when a serialize assert fails
Before
```
expected Token::Str but serialized as Str(“F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4")
```
After
```
expected Token::Str(“f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4”) but serialized as Str(“F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4")
```
2017-11-07 14:22:42 +01:00
David Tolnay 88d5fe6bfd Release 1.0.19 2017-11-06 23:50:24 -08:00
David Tolnay 9a2c352025 Rephrase serde_test::Configure documentation 2017-11-06 23:47:39 -08:00
David Tolnay 61c90cb8cb Fix typo in serde_test::Configure documentation 2017-11-06 23:45:26 -08:00
David Tolnay 66e8b0a0cd Merge pull request #1085 from serde-rs/internally-unit-struct
Allow internally tagged newtype variant containing unit struct
2017-11-06 23:44:29 -08:00
David Tolnay 9e7a3437d9 Allow internally tagged newtype variant containing unit struct 2017-11-06 23:32:36 -08:00
David Tolnay 7ac8d4f9ae AsciiExt transition 2017-11-06 22:50:10 -08:00
David Tolnay 501bae42f5 Fix space in serde_test panic message
Without this, the message contains "representationsmust".
2017-11-06 22:46:28 -08:00
David Tolnay 7a0397451e Allow serde_test::Configure to be dynamically sized
This is a more cautious choice for the trait. In the future we may need
a `whatever_ref(&self)` that works for !Sized types.
2017-11-06 22:40:09 -08:00
David Tolnay 16787318d1 Enable clippy_pedantic in serde_test 2017-11-06 22:31:35 -08:00
David Tolnay f4ae0888c8 Run clippy on serde_test in Travis 2017-11-06 22:28:58 -08:00
David Tolnay 213071fe5c Combine identical match arms in serde_test
As recommended by Clippy's match_same_arms lint.
2017-11-06 22:27:51 -08:00
David Tolnay cfd26c6fda Avoid cloning Copy types
As recommended by Clippy's clone_on_copy lint.
2017-11-06 22:26:55 -08:00
David Tolnay 23fa83941e Whitelist float_cmp lint in serde_test 2017-11-06 22:26:01 -08:00
David Tolnay 88f5b9511d Use .. in patterns
As recommended by Clippy's unneeded_field_pattern lint.
2017-11-06 22:24:25 -08:00
David Tolnay d537f1e1f0 Whitelist needless_pass_by_value lint
This lint has a false positive on trait methods with a default implementation.
2017-11-06 22:10:11 -08:00
David Tolnay f6ac232580 Merge pull request #1084 from Marwes/serde_test_readable_
Add an API for making tests for readable/compact representations
2017-11-06 22:05:29 -08:00
Markus Westerlind aad7a7987f Add an example to the Configure trait 2017-11-06 10:35:22 +01:00
David Tolnay b24ad76880 Merge pull request #1080 from xfix/patch-2
serde_test requires serde 1.0.16 to work
2017-11-05 15:03:28 -08:00
Konrad Borowski 5796f1a0f5 serde_test requires serde 1.0.16 to work
This is due to implementing is_human_readable which was
added in serde 1.0.16.
2017-11-05 23:51:01 +01:00
David Tolnay 6437167930 Merge pull request #1083 from serde-rs/ty-macro
Fix bounds for macro named the same as a type parameter
2017-11-05 12:56:57 -08:00
David Tolnay f98daaa250 Merge pull request #1082 from serde-rs/borrow-variant
Allow borrow attribute on newtype variants
2017-11-05 12:20:40 -08:00
David Tolnay b8a40551a2 Fix bounds for macro named the same as a type parameter 2017-11-05 12:18:39 -08:00
David Tolnay 40db31691a Allow borrow attribute on newtype variants 2017-11-05 12:10:40 -08:00
David Tolnay ab68132b1f Release 1.0.18 2017-11-03 10:20:41 -07:00
David Tolnay e70bbd9dde Merge pull request #1079 from serde-rs/skipborrow
Ignore skipped fields when looking for borrowed lifetimes
2017-11-03 10:20:32 -07:00
David Tolnay d5e5c520ac Ignore skipped fields when looking for borrowed lifetimes 2017-11-03 10:08:02 -07:00
Markus Westerlind 1b9a096fa7 Export configure api 2017-11-02 16:03:50 +01:00
Markus Westerlind 39e05ffad2 Implement Deserializer for Readable/Compact 2017-11-02 15:47:07 +01:00
Markus Westerlind 78fab25c5c implement Serializer for Readable/Compact 2017-11-02 15:47:07 +01:00
David Tolnay 2a557a1e36 Clippy false positive on needless_lifetimes has been fixed 2017-10-31 22:42:53 -07:00
David Tolnay ab0848f780 Follow clippy advice about unreadable literal 2017-10-31 22:42:12 -07:00
David Tolnay 2b1303f59c Whitelist const_static_lifetime
This clippy suggestion is not stable in the older rustc we support.
2017-10-31 22:23:39 -07:00
David Tolnay 7f9ba155cb Explain what each dependency is for 2017-10-31 22:16:33 -07:00
David Tolnay a4e0c2f055 Merge pull request #1075 from hcpl/clarify-readme-example
Clarify the README example for local builds
2017-10-31 22:16:15 -07:00
hcpl 3bbf70575b Clarify the README example for local builds 2017-10-31 21:20:23 +02:00
David Tolnay ad680cbd44 Release 1.0.17 2017-10-31 09:36:06 -07:00
David Tolnay ff0cfb1f1f Clean up trailing whitespace and where-clauses 2017-10-31 09:36:05 -07:00
David Tolnay 9b08915a18 Add tests for std::num::Wrapping impls 2017-10-31 09:32:58 -07:00
David Tolnay 501aa3ee1d Share the import of std::num::Wrapping 2017-10-31 09:27:58 -07:00
David Tolnay eebf0f8db8 Merge pull request #1072 from LinearZoetrope/wrapping
Add std::num::Wrapping impl
2017-10-31 09:26:17 -07:00
Zoe Juozapaitis a7e4911ddb Add newlines to ends of files 2017-10-31 04:29:00 -07:00
Zoe Juozapaitis eb08f037f5 Add std::num::Wrapping support 2017-10-31 03:02:58 -07:00
David Tolnay aa03fd5d1a Duplicate error messages have been fixed 2017-10-27 21:08:41 -04:00
David Tolnay e198afb0c1 Add missing copyright notices 2017-10-22 16:01:19 -07:00
David Tolnay bc8de251cf Update contributing.md with steps for running test suite 2017-10-22 15:46:54 -07:00
David Tolnay 99e8686189 Add error banner when running test suite without nightly compiler 2017-10-22 15:46:17 -07:00
David Tolnay 826f656e28 Compile and test the serde_derive "example" code 2017-10-22 12:09:56 -07:00
David Tolnay ab7c003b64 Remove associated constants workaround
This has been stable since Rust 1.20.
2017-10-22 11:55:16 -07:00
David Tolnay 422191fcb0 Release 1.0.16 2017-10-22 11:29:44 -07:00
David Tolnay 4ba748c902 Clean up trailing whitespace 2017-10-22 11:29:35 -07:00
David Tolnay 14ed6f2dab Simplify some IntoDeserializer deserializer types 2017-10-20 21:38:18 -07:00
David Tolnay 30606a43aa IntoDeserializer for HashSet and HashMap with non-default hasher 2017-10-20 21:36:40 -07:00
David Tolnay 9be3d32016 Remove redundant readable/compact tests
This functionality is covered well enough by the std::net types.
2017-10-17 23:16:21 -07:00
David Tolnay 5daf1b89a1 Consolidate readable/compact deserialization tests 2017-10-17 23:15:35 -07:00
David Tolnay f8f5d0ca2f No need for readable setting for the ignore test 2017-10-17 23:09:50 -07:00
David Tolnay 57873cce28 Remove unused deserialization macros on no_std 2017-10-17 10:04:26 -07:00
David Tolnay 4ed0362c8e Panic by default in serde_test is_human_readable
The serde_test Serializer and Deserializer panic in is_human_readable unless the
readableness has been set explicitly through one of the hidden functions. This
is to force types that have distinct readable/compact representations to be
tested explicitly in one or the other, rather than with a plain assert_tokens
which arbitrarily picks one.

We need to follow up by designing a better API in serde_test to expose this
publicly. For now serde_test cannot be used to test types that rely on
is_human_readable. (The hidden functions are meant for our test suite only.)
2017-10-17 09:49:42 -07:00
David Tolnay 4cecaf8d02 Test the maximum std::net string lengths 2017-10-15 20:32:30 -07:00
David Tolnay 50c696aabe Write is_human_readable examples 2017-10-15 20:27:03 -07:00
David Tolnay 2f58a20bc6 Inline is_human_readable 2017-10-15 16:54:48 -07:00
David Tolnay 030459a040 Merge pull request #1044 from Marwes/human_readable
Serialize to binary if the serde format is not human readable
2017-10-15 16:39:58 -07:00
Markus Westerlind e9b530a000 Hide is_human_readable constructors in serde_test
Until a good API can be found
2017-10-13 17:37:47 +02:00
David Tolnay ea1a729088 Release 1.0.15 2017-09-17 13:58:35 -07:00
David Tolnay 857dcea774 Merge pull request #1058 from serde-rs/internally-tagged-seq
Support deserializing internally tagged enum from seq
2017-09-17 13:57:33 -07:00
David Tolnay b98a9a8f9b Support deserializing internally tagged enum from seq
During serialization, internally tagged enums invoke the Serializer's
serialize_struct. In JSON this turns into a map which uses visit_map
when deserialized. But some formats employ visit_seq when
deserializing a struct. One example is rmp-serde. Such formats were
previously unable to deserialize an internally tagged enum. This
change fixes it by adding visit_seq for internally tagged enums.
2017-09-17 13:45:12 -07:00
Markus Westerlind 3b135431fd Try to fix compilation on 1.13 2017-09-14 17:12:23 +02:00
Markus Westerlind 945d12c0b4 Use the variant_identifier macro for OsString 2017-09-14 17:08:17 +02:00
Markus Westerlind e36915300f Properly deserialize non-readable IpAddr and SocketAddr 2017-09-14 17:08:17 +02:00
Markus Westerlind 85c05d301a Fix the non-readble IpAddr serialize implementations 2017-09-11 17:40:02 +02:00
Markus Westerlind c2474bf6ee Document that is_human_readable == false is a breaking change 2017-09-11 17:18:35 +02:00
Markus Westerlind a52f436788 Fix rustc 1.13 and clippy errors on travis 2017-09-11 16:03:00 +02:00
Markus Westerlind ad3335e5d6 Serialize non-human-readble ip addresses as tuples
Since we know exactly how many bytes we should serialize as we can hint
to the serializer that it is not required which further reduces the
serialized size when compared to just serializing as bytes.
2017-09-11 15:54:53 +02:00
David Tolnay 4b00de0e22 Release 1.0.14 2017-09-09 12:50:57 -07:00
David Tolnay 8403fa018e Merge pull request #1052 from serde-rs/static
Special case for 'static fields
2017-09-09 12:50:11 -07:00
David Tolnay 0e9f1b42de Merge pull request #1053 from serde-rs/cast
Fix trivial numeric cast in visit_u64
2017-09-09 12:43:46 -07:00
David Tolnay 0085d05e55 Special case for 'static fields 2017-09-09 12:39:14 -07:00
David Tolnay 2eed855bff Fix trivial numeric cast in visit_u64 2017-09-09 12:37:00 -07:00
David Tolnay c3eced410f Release 1.0.13 2017-09-09 11:40:31 -07:00
David Tolnay 8a630fea7c Suppress cast_lossless lint in test suite 2017-09-09 11:08:19 -07:00
David Tolnay 2e597ed3f0 Remove unused functions in with-variant tests
Macro expansion fails before it would generate code to call any of these.
2017-09-09 10:58:32 -07:00
David Tolnay 0963121beb Support consolidated with attribute for variants 2017-09-09 10:50:40 -07:00
David Tolnay 15b2714058 Merge pull request #1015 from spinda/with-variant
implement (de)serialize_with for variants
2017-09-09 10:49:24 -07:00
David Tolnay 9ce107de25 Merge pull request 963 from sfackler/u64-identifier
Conflicts:
    serde_derive/src/de.rs
2017-09-08 21:35:41 -07:00
David Tolnay e47284c0e0 Merge pull request #1043 from greyblake/screaming-kebab-case
SCREAMING-KEBAB-CASE support
2017-09-08 21:30:01 -07:00
David Tolnay 800620e2aa Merge pull request #1022 from sfackler/skip-field
Inform serializers about skipped fields.
2017-09-08 09:47:43 -07:00
Markus Westerlind 40c670e625 Add non-human readable serializations for ip addresses 2017-09-08 10:37:33 +02:00
David Tolnay ba260b0e5f Merge pull request #1045 from xfix/patch-1
Fix a type name typo in visit_i64 documentation
2017-09-07 12:07:03 -07:00
Konrad Borowski 8452e313cc Fix a type name typo in visit_i64 documentation 2017-09-07 19:53:07 +02:00
Markus Westerlind 0dccbb1f11 Serialize to binary if the serde format is not human readable
This implements the KISS suggested in https://github.com/serde-rs/serde/issues/790.
It is possible that one of the other approaches may be better but this
seemed like the simplest one to reignite som discussion.

Personally I find the original suggestion of adding two traits perhaps slightly
cleaner in theory but I think it ends up more complicated in the end
since the added traits also need to be duplicated to to the `Seed`
traits.

Closes #790
2017-09-07 16:20:57 +02:00
Steven Fackler deca49315a Inline skip_field 2017-09-05 22:36:42 -07:00
Steven Fackler 95407a4ca5 Support field ident deserialization from u32 2017-09-05 21:55:33 -07:00
Steven Fackler 2fe9a860cd Inform serializers about skipped fields.
Closes #960.
2017-09-05 21:55:33 -07:00
Sergey Potapov e67d941b78 Support for SCREAMING-KEBAB-CASE 2017-09-05 22:07:08 +02:00
David Tolnay d4042872f5 Release 1.0.12 2017-09-04 11:11:44 -07:00
David Tolnay 64af86b830 Suppress cast_lossless lint 2017-09-04 11:10:43 -07:00
David Tolnay 370c8a91cb Merge pull request #1039 from serde-rs/rcde
Deserialize unsized Arc and Rc
2017-09-04 11:07:19 -07:00
David Tolnay 972da59ebc Deserialize unsized Arc and Rc 2017-09-04 10:56:42 -07:00
David Tolnay a42008f695 Merge pull request #1038 from serde-rs/rcser
Serialize unsized Arc and Rc
2017-09-04 10:54:20 -07:00
David Tolnay e4ea2a56e9 Serialize unsized Arc and Rc 2017-09-04 10:31:03 -07:00
David Tolnay 7650a48fdd Opt in to clippy_pedantic lints 2017-08-24 00:41:42 -07:00
David Tolnay d665a2f2b2 Merge pull request #1023 from hcpl/fix-doc-typo
Fix `SeqAcccess` typo in docs
2017-08-20 15:03:10 -07:00
hcpl 44e23254c9 Fix SeqAcccess typo in docs 2017-08-20 22:02:28 +03:00
Michael Smith 552971196d Fix Clippy errors in variant serialize_with tests 2017-08-16 12:04:39 -07:00
David Tolnay 0681cd5003 Replace deprecated compiletest::default_config() 2017-08-15 22:10:18 -07:00
David Tolnay d965367238 No longer need feature(into_boxed_c_str) 2017-08-15 22:08:23 -07:00
David Tolnay a6df35b3d2 Disable no_std test on appveyor 2017-08-15 21:58:52 -07:00
Michael Smith 9fc180e62f Implement deserialize_with for variants
Complements variant serialize_with and closes #1013.
2017-08-14 14:41:05 -07:00
Michael Smith 5b815b7001 Implement serialize_with for variants
As discussed in #1013, serialize_with functions attached to variants receive an
argument for each inner value contained within the variant. Internally such a
function is wired up to the serializer as if the variant were a newtype variant.
2017-08-14 11:17:08 -07:00
David Tolnay 4831482695 Doc comment on statement is not used by rustdoc
Fixes #1014.
2017-08-05 23:35:14 -07:00
David Tolnay d3e5dd9cd7 Disagree that 0x10000 is unreadable 2017-08-05 23:26:15 -07:00
David Tolnay 26098ed877 Release 1.0.11 2017-07-27 00:56:28 -07:00
David Tolnay 42ed62cf24 Merge pull request #1003 from serde-rs/newnonzero
NonZero constructor now returns Option
2017-07-27 00:54:23 -07:00
David Tolnay 9f0973aff7 NonZero constructor now returns Option 2017-07-27 00:35:56 -07:00
David Tolnay ccec002bf3 Merge pull request #1001 from serde-rs/remotevis
Inherit the visibility of remote struct definition
2017-07-27 00:29:57 -07:00
David Tolnay f36a1e0895 Inherit the visibility of remote struct definition 2017-07-25 23:52:06 -07:00
David Tolnay e6487cf6fa Merge pull request #995 from serde-rs/nobin
Workaround for "no bin target named serde_derive_tests_no_std"
2017-07-21 00:17:25 -07:00
David Tolnay 4f2e8d5dbb Workaround for "no bin target named serde_derive_tests_no_std" 2017-07-21 00:05:30 -07:00
David Tolnay 1c2a4bff1c Merge pull request #991 from Marwes/test_systemtime
Fix SystemTime serialization test on Windows
2017-07-16 06:10:43 -07:00
Markus Westerlind 85bccf42b6 Fix SystemTime serialization test on Windows
Windows's `SystemTime` do not have nanosecond resolution which caused the test duration to be truncated https://github.com/rust-lang/rust/blob/b1363a73ede57ae595f3a1be2bb75d308ba4f7f6/src/libstd/sys/windows/time.rs#L177
2017-07-16 12:16:07 +02:00
David Tolnay 959fee024f Merge pull request #986 from Marwes/simplify_seed
refactor: Implement Deserialize of wrapper types with a macro
2017-07-12 20:36:48 -07:00
Markus Westerlind 8ede8c8e2a refactor: Implement Deserialize of wrapper types with a macro 2017-07-13 00:02:29 +02:00
David Tolnay 83537c95e1 Release 1.0.10 2017-07-11 21:19:24 -07:00
David Tolnay fa9057fa31 Merge pull request #949 from WiSaGaN/feature/support-system-time
Support std::time::SystemTime
2017-07-11 21:17:56 -07:00
Wangshan Lu 0084d82a50 Add tests for SystemTime 2017-07-12 12:01:40 +08:00
Wangshan Lu b504b08782 Fix SystemTime serde name 2017-07-12 12:01:29 +08:00
David Tolnay 775e8154e7 Fix libc dependency in no_std test 2017-07-09 10:19:19 -07:00
David Tolnay 9c679d9082 Test for serializing BTreeSet 2017-07-09 10:16:49 -07:00
David Tolnay b0f9d2a0ba Exclude macros file from being tested by itself 2017-07-09 09:24:29 -07:00
David Tolnay f39b1db96a Additional errors for some reason 2017-07-09 09:22:20 -07:00
David Tolnay 9ecb0839de Release 1.0.9 2017-06-29 20:21:29 -07:00
David Tolnay 8a4c116812 Merge pull request #971 from serde-rs/remotede
Fix deserializer bounds on remote derive
2017-06-29 20:19:36 -07:00
David Tolnay 1d3e921ba6 Fix deserializer bounds on remote derive 2017-06-29 20:12:44 -07:00
Steven Fackler 8e8694261b Fix identifier deserialization from non-u32
Closes #962
2017-06-19 20:23:14 -07:00
David Tolnay 4fdba725fe Revert "Support deserialization of struct keys from integers"
This is not as useful as expected because the Serializer does not know the real
index of each struct field being serialized. The best it can do is keep a
counter, which goes wrong if fields are conditionally skipped.

This reverts commit eec7101894.
2017-06-18 09:11:21 -07:00
David Tolnay 75eed8cdde Merge pull request #958 from serde-rs/unused
Fix unused seq and map macros
2017-06-17 19:14:39 -07:00
David Tolnay 6801a13650 Fix unused seq and map macros 2017-06-17 19:01:12 -07:00
David Tolnay 25ab84d4b9 Merge pull request #957 from serde-rs/alloc
Merge crate `collections` into `alloc`
2017-06-17 18:59:43 -07:00
David Tolnay e43d3f3e4f Merge crate collections into alloc 2017-06-17 18:35:56 -07:00
David Tolnay b37d47c987 Merge pull request #956 from sfackler/int-field
Support deserialization of struct keys from integers
2017-06-17 18:26:45 -07:00
Steven Fackler eec7101894 Support deserialization of struct keys from integers
serde-cbor supports a "packed" serialization flag which causes keys to
be serialized as their indices, but the deserializer currently has to
hardcode support for this format. We can simply support deserialization
of struct keys from integers as we already do for enum variants.
2017-06-17 18:12:07 -07:00
Wangshan Lu 5dd327fb02 Support std::time::SystemTime 2017-06-04 16:39:03 +08:00
David Tolnay fd3d1396d3 Release 1.0.8 2017-05-24 00:17:27 -07:00
David Tolnay c47b4c8e0b Release 1.0.7 2017-05-19 17:00:31 -07:00
David Tolnay 2d793b82f6 Merge pull request #940 from BurntSushi/ag-deser-borrowed
add borrowed value deserializers
2017-05-19 16:59:55 -07:00
Andrew Gallant 237be46e29 add borrowed value deserializers
This adds two new types to the `de::value` module,
`BorrowedStrDeserializer` and `BorrowedBytesDeserializer`. A
`BorrowedStrDeserializer` is just like `StrDeserializer`, except the
lifetime of the string is tied to the lifetime of the deserializer. This
can be useful when, for example, deserializing into a
`HashMap<&str, &str>` when the keys/values are tied to the deserializer
itself.

The `BorrowedBytesDeserializer` has no analog, but it's the same as
`BorrowedStrDeserialize` except for `&[u8]` instead of `&str`.
2017-05-19 19:55:34 -04:00
David Tolnay 3d7aad1e7b Release 1.0.6 2017-05-17 08:20:54 -07:00
David Tolnay e792874369 Merge pull request #935 from spikefoo/combined-skip
Add a combined skip attribute
2017-05-16 09:13:49 -07:00
spikefoo 1669c69714 Add a combined #serde[(skip)] field attribute 2017-05-16 12:33:26 +03:00
David Tolnay 4d5e450054 Release 1.0.5 2017-05-14 12:53:48 -07:00
David Tolnay 26b22e647d Merge pull request #933 from serde-rs/contentstr
Fix internally tagged struct variant containing unit variant containing borrowed string
2017-05-14 12:53:07 -07:00
David Tolnay cda1fc46b0 Fix internally tagged struct variant containing unit variant containing borrowed string 2017-05-14 12:39:42 -07:00
David Tolnay c68b959696 Release 1.0.4 2017-05-10 20:05:22 -07:00
David Tolnay eab80172e4 Merge pull request #926 from serde-rs/borrow
Support borrowing within internally tagged enum
2017-05-10 20:04:36 -07:00
David Tolnay c1259fbc87 Support borrowing within internally tagged enum 2017-05-10 19:56:05 -07:00
David Tolnay 58e30eaee4 Release 1.0.3 2017-05-10 10:15:39 -07:00
David Tolnay bafa941004 Merge pull request #924 from pshc/deserialize-borrowed-path
impl Deserialize for &'a Path
2017-05-10 10:14:25 -07:00
Paul Collier f347b2d363 impl Deserialize for &'a Path 2017-05-10 13:03:03 -04:00
David Tolnay 3f9fc49cca Merge pull request #922 from serde-rs/nonzero
Removed Deref impl for NonZero
2017-05-09 19:58:17 -07:00
David Tolnay c913527944 Removed Deref impl for NonZero 2017-05-09 19:48:54 -07:00
David Tolnay 8fafc7420c Release 1.0.2 2017-04-27 12:32:30 -07:00
David Tolnay bea1c5b0f5 Remove trailing whitespace 2017-04-27 12:31:13 -07:00
David Tolnay aa37caf216 Merge pull request #905 from TedDriggs/adjacent_tag_enums
Fix #816 - adjacently-tagged enums honor deny_unknown_fields
2017-04-27 12:27:31 -07:00
Ted Driggs 2440b59aae Address feedback on PR #905
* Added error test when deny_unknown_fields enabled
* Fixed next_relevant_key to use absolute paths
2017-04-27 12:21:32 -07:00
Ted Driggs 873cfbe9ab Fix #816 - adjacently-tagged enums honor deny_unknown_fields 2017-04-27 11:24:09 -07:00
David Tolnay c96efcb87a Merge pull request #900 from SuperFluffy/macro_to_derive_input
Replace deprecated MacroInput; completes c52e131
2017-04-25 08:10:26 -07:00
Richard Janis Goldschmidt b53026a21b Replace deprecated MacroInput; completes c52e13 2017-04-25 11:08:56 +02:00
David Tolnay c7901e532e Release 1.0.1 2017-04-23 16:40:56 -07:00
David Tolnay 2af0701be6 Merge tag 'v0.9.15' into 'origin/master' 2017-04-23 16:39:32 -07:00
David Tolnay ae79451b7a Release 0.9.15 2017-04-23 16:37:43 -07:00
David Tolnay b220f264a5 Merge pull request #898 from SimonSapin/z-is-dead
Remove usage of unstable core::num::Zero, which was removed upstream.
2017-04-23 16:35:57 -07:00
David Tolnay 1a2b3815ef Merge pull request #899 from SimonSapin/z-is-dead-in-0.9-too
Remove usage of unstable core::num::Zero, which was removed upstream.
2017-04-23 16:34:06 -07:00
Simon Sapin 6fbf40b83c Remove usage of unstable core::num::Zero, which was removed upstream.
https://github.com/rust-lang/rust/pull/41437
2017-04-24 08:29:38 +09:00
Simon Sapin 1d6ecf3c2c Remove usage of unstable core::num::Zero, which was removed upstream.
https://github.com/rust-lang/rust/pull/41437

Backport of https://github.com/serde-rs/serde/pull/898 to 0.9.x
2017-04-24 08:25:08 +09:00
David Tolnay d7ccef0cac Release 1.0.0 2017-04-20 08:19:31 -07:00
David Tolnay 2d465415c5 Take credit 2017-04-20 08:13:46 -07:00
David Tolnay bc2d637112 Cut an internals release 2017-04-20 08:11:31 -07:00
David Tolnay cf1cdadc77 Fix some rustfmt screwups 2017-04-19 15:56:22 -07:00
David Tolnay 4a9cb3395d Fix the serialize_bytes doc test 2017-04-19 15:03:02 -07:00
David Tolnay dfa6623a24 Encourage serialize_entry 2017-04-19 14:56:52 -07:00
David Tolnay a8adac6b93 Document misuse of SerializeMap 2017-04-19 14:55:28 -07:00
David Tolnay b9b7922ef1 Naming for &str and &[u8] is more like primitives 2017-04-19 14:53:15 -07:00
David Tolnay a369ee156f Run serde_test doc tests in Travis 2017-04-19 14:45:06 -07:00
David Tolnay d1253cb193 Minimal serde_derive documentation
Fixes #886.
2017-04-19 14:43:53 -07:00
David Tolnay bc982f9757 Examples for serde_test methods 2017-04-19 14:39:52 -07:00
David Tolnay 0240814677 Update post-merge html_root_urls 2017-04-19 14:32:04 -07:00
David Tolnay 670be2ce2f Crate-level documentation for serde_test 2017-04-19 14:31:07 -07:00
David Tolnay c893e3e872 Support old rustc 2017-04-19 14:17:18 -07:00
David Tolnay fe8141fd70 Reorder Tokens to match the Serializer trait 2017-04-19 14:15:24 -07:00
David Tolnay aa750d2bf3 Examples of every token 2017-04-19 14:12:56 -07:00
David Tolnay 4cea214da2 Update the assert_ser_tokens_error example 2017-04-19 13:11:14 -07:00
David Tolnay 15341780a2 Use struct variants in test suite 2017-04-19 13:06:31 -07:00
David Tolnay 4767ca3f5d Use struct variants in token 2017-04-19 12:20:17 -07:00
David Tolnay 26a6ba177c Remove error from serde_test public API 2017-04-19 11:54:48 -07:00
David Tolnay 974c8434e9 Add example of Error::Message 2017-04-19 10:42:15 -07:00
David Tolnay 0734b44a3a Remove unneeded trait bounds 2017-04-19 10:41:58 -07:00
David Tolnay d0f846182b Keep serde_test serializer and deserializer private 2017-04-19 09:46:30 -07:00
David Tolnay 7a7d4c6364 Format in rfc style 2017-04-18 14:23:21 -07:00
David Tolnay c567e749ef Merge branch 'origin/1.0' into 'origin/master' 2017-04-18 14:03:00 -07:00
David Tolnay b8a6e68322 Revert "Allow borrowing from str's IntoDeserializer"
This reverts commit 30e8c84d01.
2017-04-17 16:18:48 -07:00
David Tolnay 6279b0d930 Resolve merge conflicts 2017-04-17 14:25:29 -07:00
David Tolnay a778425d0f Merge branch 'origin/master' into 'origin/1.0'
Conflicts:
    serde/Cargo.toml
    serde/src/de/impls.rs
    serde/src/ser/impls.rs
    serde_derive/Cargo.toml
    serde_test/Cargo.toml
2017-04-17 14:18:33 -07:00
David Tolnay faaf5ee115 Merge pull request #884 from serde-rs/sfs
Remove seq_fixed_size in favor of tuple
2017-04-17 12:29:36 -07:00
David Tolnay 86deb8db79 Remove seq_fixed_size in favor of tuple 2017-04-17 12:07:49 -07:00
David Tolnay d4d2061a2e Release 0.9.14 2017-04-17 07:33:45 -07:00
David Tolnay c202ce13dc Merge pull request #882 from jethrogb/feature/interior_mut_types
Add Serialize/Deserialize for std types that provide interior mutability
2017-04-17 07:32:13 -07:00
Jethro Beekman 1c9478bfa6 Add Serialize/Deserialize for std types that provide interior mutability
Fixes #179
2017-04-16 22:59:17 -07:00
David Tolnay 739ad64c7c Organize top links 2017-04-16 20:44:27 -07:00
David Tolnay 3eef7c87c9 Fix xml link spacing 2017-04-16 20:33:15 -07:00
David Tolnay e0c040a3a2 Document MapAccess misuse 2017-04-15 12:36:43 -07:00
David Tolnay c13a37d4db Rename VariantAccess methods to not conflict with Deserializer 2017-04-15 12:35:04 -07:00
David Tolnay 4354aab93a Document the default behavior of Visitor methods 2017-04-14 22:29:46 -07:00
David Tolnay 691e304fff Mention the shorthand for identifiers 2017-04-14 22:13:55 -07:00
David Tolnay 13463e25c2 Add a lowercase case convention 2017-04-14 22:09:46 -07:00
David Tolnay 54bbf81dfc Put deserialize_struct and deserialize_enum adjacent 2017-04-14 22:00:27 -07:00
David Tolnay cdfd445528 Generate deserialize impls for identifiers 2017-04-14 21:53:48 -07:00
David Tolnay 30e8c84d01 Allow borrowing from str's IntoDeserializer 2017-04-14 20:54:58 -07:00
David Tolnay a35bde49c6 Factor out logic to decide the tag style 2017-04-14 16:14:10 -07:00
David Tolnay f9535a4d67 Remove "item" terminology in favor of "container"
The docs have been using "container" for a long time.
2017-04-14 15:52:58 -07:00
David Tolnay 6d55501dab Replace "codegen" with "derive" 2017-04-14 15:42:27 -07:00
David Tolnay 5b118fdef4 Reorder methods to match the serializer trait 2017-04-14 15:24:21 -07:00
David Tolnay 337c6e91d8 Access terminology in serde_test 2017-04-14 15:07:19 -07:00
David Tolnay b0dc7ea6da Nicer type parameter for the access forwarding impls 2017-04-14 15:03:43 -07:00
David Tolnay 67d56ae427 Remove unneeded impl bounds 2017-04-14 15:00:16 -07:00
David Tolnay 6829c10a10 Helper deserializer means nothing 2017-04-14 14:49:45 -07:00
David Tolnay 6a37472023 Implement ser::Error for the value error 2017-04-14 14:40:37 -07:00
David Tolnay d10fa2bd86 Keep underscored names out of the documentation 2017-04-14 14:38:58 -07:00
David Tolnay e722cf8791 Fix some function signatures that rustfmt missed 2017-04-14 14:33:00 -07:00
David Tolnay bc4205a1d0 Use V as the Visitor parameter 2017-04-14 14:31:29 -07:00
David Tolnay ea5af417fb Use access terminology for value deserializers 2017-04-14 14:30:28 -07:00
David Tolnay c70c364754 Example of IntoDeserializer 2017-04-14 14:24:47 -07:00
David Tolnay 9cda4563c0 Clean up extraneous vertical space 2017-04-14 14:10:55 -07:00
David Tolnay fc927e0e25 Review deserialize impls 2017-04-14 14:08:11 -07:00
David Tolnay 7915835a93 Merge pull request #879 from serde-rs/size_hint
Simplify size_hint to Option<usize>
2017-04-14 14:07:36 -07:00
David Tolnay 0c5db90de8 Simplify size_hint to Option<usize> 2017-04-14 13:31:46 -07:00
David Tolnay 637332de2d Merge pull request #878 from serde-rs/deserialize_any
Rename Deserializer::deserialize to deserialize_any
2017-04-14 13:04:20 -07:00
David Tolnay e77e7c4bba Rename Deserializer::deserialize to deserialize_any 2017-04-14 12:52:57 -07:00
David Tolnay 1798d1af6e Merge pull request #876 from serde-rs/access
Access traits
2017-04-14 12:45:54 -07:00
David Tolnay 31cec05712 Access traits 2017-04-14 12:24:35 -07:00
David Tolnay f2de0509f5 Whitelist the zero prefixed literals used in array_impls 2017-04-14 12:24:22 -07:00
David Tolnay 26d357e846 Map ser impls should serialize a map 2017-04-14 12:08:26 -07:00
David Tolnay 4e2f08cc7a Format some where clauses that rustfmt refused to touch 2017-04-13 23:04:53 -07:00
David Tolnay 91a0f248a1 More readable MapDeserializer bounds 2017-04-13 22:59:36 -07:00
David Tolnay 03462b6e39 Update the list of deserializable types 2017-04-13 17:48:39 -07:00
David Tolnay 37f8ea234f Hyperlink the de module documentation 2017-04-13 17:43:10 -07:00
David Tolnay 3f920f645c License boilerplate 2017-04-13 17:34:42 -07:00
David Tolnay a937a06d3e Add an IgnoredAny example 2017-04-13 17:22:51 -07:00
David Tolnay dd092dce95 Allow using IgnoredAny as a visitor 2017-04-13 16:53:27 -07:00
David Tolnay dfea7ec939 This is not a bottleneck 2017-04-13 16:46:38 -07:00
David Tolnay 0e7c027ff1 NonZero is just another deref 2017-04-13 16:44:05 -07:00
David Tolnay 8b6f77095a Remove redundant cfg 2017-04-13 16:43:03 -07:00
David Tolnay dbe7d04282 Import Path and PathBuf directly 2017-04-13 16:38:04 -07:00
David Tolnay fb7964fde7 Clean up serialize_display_bounded_length 2017-04-13 16:36:24 -07:00
David Tolnay f45b83f0c1 Condense the deref impls 2017-04-13 16:26:30 -07:00
David Tolnay f28abe8fde Map impls more like the seq impls 2017-04-13 16:09:53 -07:00
David Tolnay 15faaf8bc3 Condense the tuple impls 2017-04-13 16:01:50 -07:00
David Tolnay a15636f808 More like the Deserialize impls for sequences 2017-04-13 15:55:34 -07:00
David Tolnay 5d396c4e3b Condense the array impls 2017-04-13 15:41:26 -07:00
David Tolnay bdccde5c9b Simplify serialize impl for String 2017-04-13 15:36:46 -07:00
David Tolnay 7dd01dd54a This macro serializes a primitive 2017-04-13 15:36:42 -07:00
David Tolnay e4b21e6caa Example for serialize_unit 2017-04-13 15:20:09 -07:00
David Tolnay 2afbffa924 Example for serialize_unit_struct 2017-04-13 15:20:01 -07:00
David Tolnay 385f83a7de Examples and links for Option 2017-04-13 15:16:43 -07:00
David Tolnay 50f5ef2fb6 Condense some serializer imports 2017-04-13 14:54:59 -07:00
David Tolnay 13f273ad74 Examples for the primitive serializer methods 2017-04-13 14:51:39 -07:00
David Tolnay 09bd8287e7 Hyperlink the serialize_entry documentation 2017-04-13 14:27:13 -07:00
David Tolnay 35313257c5 Do not hyperlink first sentence because it shows up in index 2017-04-13 14:23:06 -07:00
David Tolnay 07bce54ad3 Add a collect_map example 2017-04-13 14:21:28 -07:00
David Tolnay 41488252ff Add a collect_seq example 2017-04-13 14:19:17 -07:00
David Tolnay 8d1f882512 Hyperlink the collect methods 2017-04-13 14:16:28 -07:00
David Tolnay dec6b67236 Hyperlink the Serializer associated types 2017-04-13 14:02:13 -07:00
David Tolnay 0cf8eadef8 Dynamically sized means something else 2017-04-13 13:56:12 -07:00
David Tolnay 7d16710fb4 Add an example to Serialize 2017-04-13 13:55:51 -07:00
David Tolnay 9253fccf04 Hyperlink the Serialize documentation 2017-04-13 13:55:34 -07:00
David Tolnay eab771cd1a Standardize on 80 characters per line
Per Mozilla coding style:
https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style
2017-04-13 13:24:47 -07:00
David Tolnay 4f6518dad7 Hyperlink the ser::Error documentation 2017-04-13 13:20:12 -07:00
David Tolnay f8e53e837d Hyperlink the ser module documentation 2017-04-13 13:15:23 -07:00
David Tolnay c5854f19f7 Prefer where clauses 2017-04-13 13:02:10 -07:00
David Tolnay 5bb6de80b2 Use better names for the sake of the documentation 2017-04-13 12:45:42 -07:00
David Tolnay c4e31bd968 Match the associated types from the Serializer trait 2017-04-13 12:43:24 -07:00
David Tolnay 2887c379de Hyperlink the Impossible documentation 2017-04-13 12:42:36 -07:00
David Tolnay ea8fb97beb Format in rfc style 2017-04-13 12:32:29 -07:00
David Tolnay c5bd760133 Sort macros in a more readable order 2017-04-13 12:15:12 -07:00
David Tolnay 942642c0f4 Hyperlink the forward_to_deserialize documentation 2017-04-13 12:09:42 -07:00
David Tolnay 78407e19a9 Export Formatter directly for generated code 2017-04-13 12:02:16 -07:00
David Tolnay 47a4e61b8b Document the parts of lib.rs 2017-04-13 11:59:42 -07:00
David Tolnay 5141270346 Touch up the top-level documentation 2017-04-13 11:52:33 -07:00
David Tolnay dc7ab2696a Point html_root_url to docs.rs 2017-04-13 11:31:29 -07:00
David Tolnay 14034968df Implement Copy for de::Unexpected 2017-04-13 11:11:37 -07:00
David Tolnay aef136934b Implement Clone for the value deserializers 2017-04-13 11:11:09 -07:00
David Tolnay 7d0a38270d Eagerly implement common traits for IgnoredAny 2017-04-13 11:06:48 -07:00
David Tolnay 07154303ed Implement Debug for public types 2017-04-13 11:04:16 -07:00
David Tolnay 4f39766211 Fix paths to readme files 2017-04-13 10:37:24 -07:00
David Tolnay 304b598a05 Add appveyor badge to crates.io 2017-04-13 10:26:47 -07:00
David Tolnay afd080d005 Merge branch 'origin/master' into 'origin/1.0' 2017-04-13 10:19:35 -07:00
David Tolnay 1232cfd194 Add playground link to readme 2017-04-13 10:19:22 -07:00
David Tolnay 7e72d8bf66 Merge pull request #869 from serde-rs/into
Rename ValueDeserializer trait to IntoDeserializer
2017-04-12 08:06:18 -07:00
David Tolnay 0d82bbf74f Rename ValueDeserializer trait to IntoDeserializer 2017-04-11 23:20:35 -07:00
David Tolnay aed5a77540 Fix assert_next_token on old rustc 2017-04-10 19:41:32 -07:00
David Tolnay f54d597b2e Merge pull request #865 from serde-rs/use
Centralize all import wrangling
2017-04-10 19:15:45 -07:00
David Tolnay 2efb95015b Appease Rust 1.13.0 2017-04-10 19:06:42 -07:00
David Tolnay f88db0f547 Centralize all import wrangling 2017-04-10 18:50:22 -07:00
David Tolnay 0b7accf86c Remove unused unstable flag from serde_derive 2017-04-10 17:29:59 -07:00
David Tolnay ab82f09e5d Merge pull request #864 from serde-rs/rc
Put rc impls behind a cfg
2017-04-10 17:20:38 -07:00
David Tolnay 0f72d1a388 Put rc impls behind a cfg 2017-04-10 17:01:11 -07:00
David Tolnay ef3489a23e Merge pull request #863 from serde-rs/cfgs
Document the cargo cfgs
2017-04-10 16:47:14 -07:00
David Tolnay 8bbab627a0 Document the cargo cfgs 2017-04-10 16:38:11 -07:00
David Tolnay 76ff216a5f Merge pull request #853 from serde-rs/fwd
Configurable forward_to_deserialize
2017-04-10 15:43:34 -07:00
David Tolnay b40ecf04ce Merge branch 'origin/1.0' into 'origin/fwd'
Conflicts:
    serde/src/macros.rs
2017-04-10 15:23:37 -07:00
David Tolnay eeaa095cd3 Merge pull request #860 from serde-rs/identifier
Standardize on u32 for struct field index and enum variant index
2017-04-10 15:16:16 -07:00
David Tolnay 1985cfc955 Merge branch 'origin/1.0' into 'origin/identifier'
Conflicts:
    serde_derive/src/ser.rs
2017-04-10 12:37:41 -07:00
David Tolnay 517270a943 Merge pull request #858 from serde-rs/remote
Derive for remote types
2017-04-10 12:33:38 -07:00
David Tolnay 6a6606cd64 Test unknown field in remote struct 2017-04-10 12:23:02 -07:00
David Tolnay 174867295b Test missing field in remote struct 2017-04-10 12:22:51 -07:00
David Tolnay ad5bf04c4e Test for incorrect remote type deserializing 2017-04-10 12:15:40 -07:00
David Tolnay 2deacf8eaa Detect incorrect remote type without getter 2017-04-10 12:12:00 -07:00
David Tolnay e133b8b708 Fix unused import on windows 2017-04-09 14:11:27 -07:00
David Tolnay 52e93150e6 Standardize on u32 as the type of a variant index 2017-04-09 14:03:18 -07:00
David Tolnay a38b24136b Rename deserialize_struct_field to deserialize_identifier
Because it applies to both struct fields and discriminants of an enum.
2017-04-09 13:35:22 -07:00
David Tolnay 78f682590a Merge branch 'origin/1.0' into 'origin/remote'
Conflicts:
    serde_derive/src/de.rs
2017-04-09 13:19:04 -07:00
David Tolnay 528ec3cdd8 Merge pull request #859 from serde-rs/unitseq
Remove conversion from empty seq to unit struct
2017-04-09 13:17:41 -07:00
David Tolnay 1986c17052 Remove conversion from empty seq to unit struct 2017-04-09 13:08:05 -07:00
David Tolnay 5ec317a899 More compile-fail tests for remote derive 2017-04-09 11:11:27 -07:00
David Tolnay 9d8987bde8 Require getters to return the correct type 2017-04-09 10:59:54 -07:00
David Tolnay a6d172111b Derive for remote types 2017-04-09 10:15:46 -07:00
David Tolnay 9271f7c48c Use a deserializer in which V would conflict 2017-04-08 22:46:53 -07:00
David Tolnay 74e15ea9f5 Configurable forward_to_deserialize 2017-04-08 22:43:07 -07:00
David Tolnay 2c49f9aad3 Recommend 'extern crate serde' 2017-04-08 13:53:13 -07:00
David Tolnay cc933b9cdb Just use an existing macro 2017-04-07 17:26:03 -07:00
David Tolnay fdaa8202b9 Clean up some existing examples 2017-04-07 11:06:19 -07:00
David Tolnay 85d4dc3e20 Copy the Serializer examples to the helper traits 2017-04-07 10:45:13 -07:00
David Tolnay 11a6e42256 Unignore SerializeSeq example 2017-04-07 10:42:54 -07:00
David Tolnay b1cfa5aef5 Unignore Serializer::serialize_struct_variant example 2017-04-07 10:35:42 -07:00
David Tolnay f2b230a0b8 Unignore Serializer::serialize_struct example 2017-04-07 10:34:03 -07:00
David Tolnay 8aa630ea48 Unignore Serializer::serialize_map example 2017-04-07 10:32:01 -07:00
David Tolnay ad249c7fac Unignore Serializer::serialize_tuple_variant example 2017-04-07 10:28:53 -07:00
David Tolnay fccb395168 Unignore Serializer::serialize_tuple_struct example 2017-04-07 10:26:00 -07:00
David Tolnay 8d130123d9 Unignore Serializer::serialize_tuple example 2017-04-07 10:23:52 -07:00
David Tolnay d97c4f403c Unignore Serializer::serialize_seq_fixed_size example 2017-04-07 10:17:40 -07:00
David Tolnay e86e716f7a Show imports in Serializer examples 2017-04-07 10:12:15 -07:00
David Tolnay 870305aa93 Unignore Serializer::serialize_seq example 2017-04-07 10:11:08 -07:00
David Tolnay b9be543596 Unignore Serializer::serialize_newtype_variant example 2017-04-07 10:04:37 -07:00
David Tolnay 43d49f54be Unignore Serializer::serialize_newtype_struct example 2017-04-07 10:02:11 -07:00
David Tolnay 753c711cd7 Unignore Serializer::serialize_unit_variant example 2017-04-07 10:01:39 -07:00
David Tolnay 2e9cc6e98a Move utf8 encode to where it is used 2017-04-07 09:50:38 -07:00
David Tolnay 726eea9a97 Separate out the private functionality
This makes it easier when clicking through [src] links from rustdoc, not having
to sift through public and internal code combined together.
2017-04-07 09:46:48 -07:00
David Tolnay 467b5fc595 Macro to ignore tokens in doc test 2017-04-07 09:28:33 -07:00
David Tolnay 995f2b3f76 Ignore clippy false positive 2017-04-07 09:21:30 -07:00
David Tolnay e57ce37ac1 Unignore Serializer::serialize_bytes example 2017-04-07 09:07:08 -07:00
David Tolnay a581c0d147 Keep Debug and Display as supertraits even in no_std 2017-04-07 09:00:00 -07:00
David Tolnay 21c2119349 Unignore the Impossible example 2017-04-06 17:09:01 -07:00
David Tolnay f12a951f22 Unignore VariantVisitor::visit_struct example 2017-04-06 16:28:24 -07:00
David Tolnay d2d4892873 Unignore VariantVisitor::visit_tuple example 2017-04-06 16:26:51 -07:00
David Tolnay 2b449683f3 Unignore VariantVisitor::visit_newtype_seed example 2017-04-06 16:24:48 -07:00
David Tolnay 9d73271db2 Unignore VariantVisitor::visit_unit example 2017-04-06 16:19:47 -07:00
David Tolnay 7ef80a845d Unignore DeserializeOwned example 2017-04-06 16:11:30 -07:00
David Tolnay 33760e122c Remove LineColIterator
This belongs in a helper crate.
2017-04-06 14:27:21 -07:00
David Tolnay dd62801b22 Use spaces around =-sign like Rust does 2017-04-06 14:22:03 -07:00
David Tolnay 5415abf80b Merge pull request #848 from serde-rs/emptyarray
Relax impls for [T; 0]
2017-04-05 17:43:11 -07:00
David Tolnay 6388019ad4 Relax impls for [T; 0] 2017-04-05 17:34:13 -07:00
David Tolnay 2fe67d3d72 Merge pull request #847 from serde-rs/error
Remove serde::error::Error
2017-04-05 16:37:18 -07:00
David Tolnay 1e32329e61 Fix unused feature gate warning 2017-04-05 16:30:46 -07:00
David Tolnay e2a1f08e43 Remove unused import of std::ops 2017-04-05 16:26:58 -07:00
David Tolnay 11c89695a1 Rust 1.13.0 macro parsing workaround 2017-04-05 16:22:47 -07:00
David Tolnay 5f49eb8b24 Remove unused import of MapVisitor 2017-04-05 16:18:11 -07:00
David Tolnay 3cc14c2a6d Remove serde::error::Error 2017-04-05 16:12:41 -07:00
David Tolnay aa30ef827c Move Bytes and ByteBuf to their own crate
Moved to https://github.com/serde-rs/bytes.
2017-04-05 15:21:27 -07:00
David Tolnay ebe214e8ac Remove CString dependency on ByteBuf 2017-04-05 15:19:29 -07:00
David Tolnay 8fd41d3b28 Disable publishing 2017-04-05 15:11:47 -07:00
David Tolnay a7f6ad137a Merge branch 'master' into '1.0'
Conflicts:
    serde/src/macros.rs
2017-04-05 15:10:18 -07:00
David Tolnay 1b763da529 Release 0.9.13 2017-04-05 15:03:37 -07:00
David Tolnay b7d6c5d9f7 Remove no_std special case in forward_to_deserialize 2017-04-05 15:01:55 -07:00
David Tolnay e7d3d515df Simplify integer conversion logic 2017-04-05 13:06:05 -07:00
David Tolnay 145733ce77 Remove redundant Bounded trait 2017-04-05 12:36:51 -07:00
David Tolnay 1a63cbccb2 Remove unused ToPrimitive trait 2017-04-05 12:29:05 -07:00
David Tolnay 07ac9eb538 Remove unused number conversion logic 2017-04-05 12:11:50 -07:00
David Tolnay 14aa89aac8 Merge pull request #846 from serde-rs/float
Remove implicit conversion from float to integer
2017-04-05 11:51:49 -07:00
David Tolnay e66033e53e Remove implicit conversion from float to integer 2017-04-05 11:25:12 -07:00
David Tolnay dcb837b531 Merge pull request #845 from serde-rs/token
Modernize serde_test Token names
2017-04-05 10:52:33 -07:00
David Tolnay 51d3fb1ebc Update token names in test suite 2017-04-05 10:40:14 -07:00
David Tolnay 826b53f691 Update token names in serde_test 2017-04-05 10:30:46 -07:00
David Tolnay b6605b57e0 Modernize serde_test Token names 2017-04-05 10:26:34 -07:00
David Tolnay f03e8e6056 Exhaustive match in serde_test deserializer 2017-04-05 09:54:12 -07:00
David Tolnay a33a9a5b26 Merge pull request #844 from serde-rs/sep
Eliminate Sep tokens in serde_test
2017-04-05 09:54:02 -07:00
David Tolnay 67ed7a0edd Eliminate Sep tokens in serde_test 2017-04-05 09:42:27 -07:00
David Tolnay 9b51be4ba6 Merge pull request #843 from serde-rs/ignore
Stop ignoring error in assert_de_tokens_ignore
2017-04-05 09:36:22 -07:00
David Tolnay c3d9b42cdf Fix handling of option and newtype in IgnoredAny 2017-04-05 09:19:22 -07:00
David Tolnay b2377d4c0b Allow enums in ignored map value in serde_test 2017-04-05 08:54:30 -07:00
David Tolnay dee58ead7f Merge pull request #841 from serde-rs/nostr
Remove the no_std implementation of collect_str
2017-04-05 08:12:31 -07:00
David Tolnay 887985523e Merge pull request #840 from serde-rs/privimpl
Make the built-in visitors private
2017-04-05 08:12:00 -07:00
David Tolnay cabc299447 Merge pull request #839 from serde-rs/conv
Remove questionable type conversions
2017-04-05 08:11:50 -07:00
David Tolnay 21adee8f40 Partial support for EnumStart in assert_ser_tokens 2017-04-05 01:15:42 -07:00
David Tolnay afaab12b66 Improve assert_ser_tokens error messages 2017-04-05 01:06:42 -07:00
David Tolnay 93860d0643 Require slice of tokens in serde_test::Serializer 2017-04-05 00:27:30 -07:00
David Tolnay b43554fbb1 Require slice of tokens in serde_test::Deserializer 2017-04-05 00:22:00 -07:00
David Tolnay 5871fb9ce0 Remove lifetime from serde_test::Token 2017-04-05 00:17:50 -07:00
David Tolnay f05368ed24 Remove the no_std implementation of collect_str 2017-04-04 19:10:35 -07:00
David Tolnay 732b91e53d Make the built-in visitors private 2017-04-04 18:59:57 -07:00
David Tolnay d03ecda333 Test that conversions do not happen 2017-04-04 18:50:40 -07:00
David Tolnay 7a722d5060 Remove questionable conversion tests 2017-04-04 18:38:58 -07:00
David Tolnay 2795f0ed9d Remove questionable type conversions 2017-04-04 18:18:47 -07:00
David Tolnay 92bc23e484 Deserializing OsString on windows requires a 'de lifetime 2017-04-04 18:08:36 -07:00
David Tolnay 5a98bd9ee3 Merge branch 'master' into '1.0' 2017-04-04 18:04:40 -07:00
David Tolnay bfabaf3789 Merge pull request #838 from serde-rs/winstr
Deserialize OsString on Windows
2017-04-04 11:33:42 -07:00
David Tolnay cf6c4ab7ec Deserialize OsString on Windows 2017-04-04 11:19:24 -07:00
David Tolnay 7c27e10226 Merge pull request #837 from serde-rs/borrow
Derive for borrowed fields
2017-04-04 10:51:56 -07:00
David Tolnay 20ff9ba89b Add tests of deserializing borrows 2017-04-04 10:47:21 -07:00
David Tolnay 211e2bb8d9 Support borrowed tokens in serde_test 2017-04-04 09:56:01 -07:00
David Tolnay cee3efbda8 Relax lifetime requirement of the borrow_cow functions 2017-04-03 00:54:50 -07:00
David Tolnay fb48111e46 Derive for borrowed fields 2017-04-03 00:40:45 -07:00
David Tolnay 8c3e72f2c8 Merge pull request #834 from serde-rs/easy
Deserialize impls for &str and &[u8]
2017-03-31 00:44:44 -07:00
David Tolnay aa46318425 Deserialize impls for &str and &[u8] 2017-03-30 23:36:20 -07:00
David Tolnay 3d3118f8b0 Merge pull request #826 from serde-rs/lifetime
Add a 'de lifetime to the deserialize traits
2017-03-30 23:11:49 -07:00
David Tolnay b6f1a2eb55 Add a note about assuming the deserializer lifetime name 2017-03-30 23:06:00 -07:00
David Tolnay 8eb50186e0 Merge pull request #831 from serde-rs/derivepath
Use the live serde_derive for serde doc tests
2017-03-30 22:55:33 -07:00
David Tolnay 4dec5f4de8 Update example code for zero copy 2017-03-30 22:54:42 -07:00
David Tolnay 8e0c036158 Merge branch 'derivepath' into 'lifetime' 2017-03-30 22:48:48 -07:00
David Tolnay 7d985ff3fd Use the live serde_derive for serde doc tests
This is required as both are updated to Deserialize<'de> together.
2017-03-30 22:45:15 -07:00
David Tolnay d3a2f5e268 Add a 'de lifetime to the deserialize traits 2017-03-29 00:10:34 -07:00
David Tolnay 59b3961ad4 Release 0.9.12 2017-03-27 15:45:14 -07:00
David Tolnay dbc9a60c5f Merge pull request #824 from alexcrichton/osstr-osstring
Implement Serialize/Deserialize for OsStr/OsString
2017-03-27 15:39:07 -07:00
Alex Crichton ce687431f3 Implement Serialize/Deserialize for OsStr/OsString
This commit implements the two serde traits for the libstd `OsStr` and
`OsString` types. This came up as a use case during implementing sccache where
we're basically just doing IPC to communicate paths around. Additionally the
`Path` and `PathBuf` implementations have been updated to delegate to the os
string ones.

These types are platform-specific, however, so the serialization/deserialization
isn't trivial. Currently this "fakes" a newtype variant for Unix/Windows to
prevent cross-platform serialization/deserialization. This means if you're doing
IPC within the same OS (e.g. Windows to Windows) then serialization should be
infallible. If you're doing IPC across platforms (e.g.  Unix to Windows) then
using `OsString` is guaranteed to fail as bytes from one OS won't deserialize on
the other (even if they're unicode).
2017-03-27 11:44:50 -07:00
David Tolnay 71ccc5753b Merge pull request #820 from serde-rs/reexport
Re-export derives from serde
2017-03-26 20:37:12 -07:00
David Tolnay 13886435a6 Re-export derives from serde 2017-03-21 16:54:31 -07:00
David Tolnay 08e2182042 UFCS for Option::map and Result::map 2017-03-18 13:31:03 -07:00
David Tolnay d60595cc27 Use format_args! to simplify de::Error 2017-03-18 10:48:47 -07:00
David Tolnay 8c7396c35a Be consistent with UFCS and double underscores 2017-03-18 10:33:22 -07:00
David Tolnay 42b2fd8eec Improve error message parsing from and into 2017-03-18 09:22:44 -07:00
John Baublitz bc946e4fd7 Macro attributes to specify From and Into trait types for structs and enums (#817)
* serde macro support for type conversions through From and Into trait

* Revisions requested by dtolnay

* Additional changes requested by dtolnay
2017-03-18 09:22:27 -07:00
David Tolnay c488cec641 Remove RangeInclusive impl for now
The old impl is inconsistent with the new ops::Range impl.
2017-03-13 11:09:56 -07:00
David Tolnay fcc3c69a49 Range impl is defined when building with std 2017-03-09 12:04:02 -08:00
David Tolnay 350c2e835b Remove duplicate ops::Range serialize impl 2017-03-09 11:57:36 -08:00
David Tolnay a0a031677e Merge pull request #813 from rocallahan/support-range
Implement `Serialize`/`Deserialize` for `Range`
2017-03-09 11:55:21 -08:00
Robert O'Callahan cc0d045f5c Add Deserialize impl for std::ops::Range
Resolves #796
2017-03-10 08:39:34 +13:00
Robert O'Callahan aebe1fddab Add Serialize impl for std::ops::Range 2017-03-10 00:35:04 +13:00
David Tolnay 77ee306b57 Format serde with rustfmt 0.8.0 2017-03-08 21:11:17 -08:00
David Tolnay 6750fdaae1 Merge pull request #811 from jonhoo/deserialize-cstr
Add Deserialize impl for CStr
2017-03-08 21:06:09 -08:00
David Tolnay dd6989d551 Actually run unstable tests 2017-03-08 21:02:15 -08:00
Jon Gjengset 0c2fed49e2 Add Deserialize impl for CStr
Fixes #810
2017-03-08 23:57:26 -05:00
Oliver Schneider a4ee9bd045 Merge pull request #808 from serde-rs/u32
Implement deserialize_enum for U32Deserializer
2017-03-07 18:58:29 +01:00
David Tolnay 6d9397d573 Implement deserialize_enum for U32Deserializer 2017-03-07 09:05:33 -08:00
David Tolnay dc9445f873 Release 0.9.11 2017-03-05 16:51:44 -08:00
David Tolnay 17bc40ec1c Merge pull request #789 from nox/display
Introduce Serializer::collect_str (fixes #786)
2017-03-05 16:47:22 -08:00
David Tolnay 2184fef82f Add format_args example to collect_str 2017-03-05 16:43:31 -08:00
David Tolnay 7e1b5c6ce4 Neater collect_str variable name for rustdoc 2017-03-05 16:26:05 -08:00
David Tolnay 36da8a5cee Error message geared toward serializer users
The previous message was targeted toward Serializer implementors, which is not
the group that will be seeing this message most often.
2017-03-05 16:24:48 -08:00
David Tolnay fbe85f399d Force no_std formats to implement collect_str in the future 2017-03-05 16:22:02 -08:00
David Tolnay 880b27b19e Identical signature for std and no_std collect_str 2017-03-05 16:17:03 -08:00
David Tolnay cc06f070d1 Use the existing CString error message 2017-03-05 13:59:18 -08:00
David Tolnay 2f988aa5e6 Merge pull request #801 from jonhoo/ffi-strings
impls for null-terminated FFI string types
2017-03-05 13:51:09 -08:00
Jon Gjengset d294a10e83 Only include ByteBuf when ser/de is on for std 2017-03-03 23:48:00 -05:00
Jon Gjengset defcbef7ab Use a non-stupid path for bytes::ByteBuf 2017-03-03 23:28:35 -05:00
Jon Gjengset d90eecd4a2 Add tests for CStr(ing) ser/de 2017-03-03 18:06:04 -05:00
Jon Gjengset 0d6d077e6a Serialize and deserialize CString through [u8] 2017-03-03 18:05:08 -05:00
Jon Gjengset be09fc9bbb Remove unsafe Deserialize impl for CStr
See also https://github.com/rust-lang/rust/issues/40248
2017-03-03 17:34:01 -05:00
Jon Gjengset fc9d78e26b Use serialize_bytes for speed 2017-03-03 17:14:39 -05:00
Jon Gjengset 9f83164c40 Don't serialize trailing NULL 2017-03-03 17:14:28 -05:00
Jon Gjengset 857974ab8a impls for null-terminated FFI string types
Fixes #800.
2017-03-03 16:09:41 -05:00
David Tolnay d70636f4d4 Merge pull request #794 from clarcharr/master
Documentation for serde_test.
2017-03-02 11:53:05 -08:00
Clar Charr 09e467cc4c Documentation for serde_test. 2017-02-28 18:20:27 -05:00
Anthony Ramine a9a05350a9 Introduce Serializer::collect_str (fixes #786)
The default implementation collects the Display value into a String
and then passes that to Serializer::serialize_str when the std or collections
features are enabled, otherwise it unconditionally returns an error.
2017-02-28 12:11:47 +01:00
136 changed files with 20492 additions and 10474 deletions
+3 -2
View File
@@ -1,3 +1,4 @@
Cargo.lock
target
target/
**/*.rs.bk
*.sw[po]
Cargo.lock
+52 -31
View File
@@ -1,45 +1,66 @@
# Contributing to Serde
Serde welcomes contribution from everyone. Here are the guidelines if you are
thinking of helping us:
Serde welcomes contribution from everyone in the form of suggestions, bug
reports, pull requests, and feedback. This document gives some guidance if you
are thinking of helping us.
## Contributions
Please reach out here in a GitHub issue or in the #serde IRC channel on
[`irc.mozilla.org`] if we can do anything to help you contribute.
Contributions to Serde or its dependencies should be made in the form of GitHub
pull requests. Each pull request will be reviewed by a core contributor
(someone with permission to land patches) and either landed in the main tree or
given feedback for changes that would be required. All contributions should
follow this format, even those from core contributors.
[`irc.mozilla.org`]: https://wiki.mozilla.org/IRC
Should you wish to work on an issue, please claim it first by commenting on
the GitHub issue that you want to work on it. This is to prevent duplicated
efforts from contributors on the same issue.
## Submitting bug reports and feature requests
## Pull Request Checklist
Serde development is spread across lots of repositories, but this serde-rs/serde
repository is always a safe choice for opening any issues related to Serde.
- Branch from the master branch and, if needed, rebase to the current master
branch before submitting your pull request. If it doesn't merge cleanly with
master you may be asked to rebase your changes.
When reporting a bug or asking for help, please include enough details so that
the people helping you can reproduce the behavior you are seeing. For some tips
on how to approach this, read about how to produce a [Minimal, Complete, and
Verifiable example].
- Commits should be as small as possible, while ensuring that each commit is
correct independently (i.e., each commit should compile and pass tests).
[Minimal, Complete, and Verifiable example]: https://stackoverflow.com/help/mcve
- If your patch is not getting reviewed or you need a specific person to review
it, you can @-reply a reviewer asking for a review in the pull request or a
comment, or you can ask for a review in `#serde` on `irc.mozilla.org`.
When making a feature request, please make it clear what problem you intend to
solve with the feature, any ideas for how Serde could support solving that
problem, any possible alternatives, and any disadvantages.
- Add tests relevant to the fixed bug or new feature.
## Running the test suite
We encourage you to check that the test suite passes locally before submitting a
pull request with your changes. If anything does not pass, typically it will be
easier to iterate and fix it locally than waiting for the CI servers to run
tests for you.
##### In the [`serde`] directory
```sh
# Test all the example code in Serde documentation
cargo test
```
##### In the [`test_suite/deps`] directory
```sh
# This is a prerequisite for running the full test suite
cargo clean && cargo update && cargo build
```
##### In the [`test_suite`] directory
```sh
# Run the full test suite, including tests of unstable functionality
cargo test --features unstable
```
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde
[`test_suite/deps`]: https://github.com/serde-rs/serde/tree/master/test_suite/deps
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
## Conduct
In all Serde-related forums, we follow the [Rust Code of
Conduct](https://www.rust-lang.org/conduct.html). For escalation or moderation
issues, please contact Erick (erick.tryzelaar@gmail.com) instead of the Rust
moderation team.
In all Serde-related forums, we follow the [Rust Code of Conduct]. For
escalation or moderation issues please contact Erick (erick.tryzelaar@gmail.com)
instead of the Rust moderation team.
## Communication
Beyond opening tickets on the
[serde-rs/serde](https://github.com/serde-rs/serde) project, Serde contributors
frequent the `#serde` channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC).
[Rust Code of Conduct]: https://www.rust-lang.org/conduct.html
+1 -2
View File
@@ -1,9 +1,8 @@
[workspace]
members = [
"serde",
"serde_codegen_internals",
"serde_derive",
"serde_derive_internals",
"serde_test",
"test_suite",
"test_suite/no_std",
]
+32 -1
View File
@@ -1,4 +1,9 @@
# Serde &emsp; [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
# Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io]
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
[travis]: https://travis-ci.org/serde-rs/serde
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
@@ -15,10 +20,36 @@ You may be looking for:
## Serde in action
<details>
<summary>
Click to show Cargo.toml.
<a href="http://play.integer32.com/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a>
</summary>
```toml
[dependencies]
# The core APIs, including the Serialize and Deserialize traits. Always
# required when using Serde.
serde = "1.0"
# Support for #[derive(Serialize, Deserialize)]. Required if you want Serde
# to work for structs and enums defined in your crate.
serde_derive = "1.0"
# Each data format lives in its own crate; the sample code below uses JSON
# but you may be using a different one.
serde_json = "1.0"
```
</details>
<p></p>
```rust
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
+17
View File
@@ -0,0 +1,17 @@
environment:
matrix:
- APPVEYOR_RUST_CHANNEL: stable
- APPVEYOR_RUST_CHANNEL: nightly
install:
# Install rust, x86_64-pc-windows-msvc host
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -vV
- cargo -vV
build: false
test_script:
- sh -c 'PATH=`rustc --print sysroot`/bin:$PATH ./travis.sh'
+2
View File
@@ -0,0 +1,2 @@
error_on_line_overflow = false
same_line_attributes = false
+46 -12
View File
@@ -1,7 +1,7 @@
[package]
name = "serde"
version = "0.9.10"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
version = "1.0.29" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
@@ -9,26 +9,60 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
readme = "../README.md"
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[dependencies]
serde_derive = { version = "1.0", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" }
### FEATURES #################################################################
[features]
default = ["std"]
# Re-export the derive(Serialize, Deserialize) macros. This is specifically
# intended for library crates that provide optional Serde impls behind a Cargo
# cfg of their own. All other crates should depend on serde_derive directly.
#
# Please refer to the long comment above the line `pub use serde_derive::*` in
# src/lib.rs before enabling this feature. If you think you need this feature
# and your use case does not precisely match the one described in the comment,
# please open an issue to let us know about your use case.
derive = ["serde_derive"]
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
# Requires a dependency on the Rust standard library.
std = []
# Provide impls for types that require unstable functionality. For tracking and
# discussion of unstable functionality please refer to this issue:
#
# https://github.com/serde-rs/serde/issues/812
unstable = []
# Provide impls for types in the Rust core allocation and collections library
# including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
# be enabled without depending on all of std.
#
# Requires a dependency on the unstable core allocation library:
#
# https://doc.rust-lang.org/alloc/
alloc = ["unstable"]
collections = ["alloc"]
unstable-testing = ["unstable", "std"]
# to get serde_derive picked up by play.integer32.com
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature.
rc = []
# Get serde_derive picked up by the Integer 32 playground. Not public API.
#
# http://play.integer32.com/
playground = ["serde_derive"]
[dependencies]
serde_derive = { version = "0.9", optional = true }
[dev-dependencies]
serde_derive = "0.9"
-315
View File
@@ -1,315 +0,0 @@
//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces us to treat `&[u8]` just like any other
//! slice and `Vec<u8>` just like any other vector. In reality this particular
//! slice and vector can often be serialized and deserialized in a more
//! efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec<u8>` by wrapping it in
//! `bytes::ByteBuf`.
//!
//! Rust support for specialization is being tracked in
//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler
//! we will be deprecating these wrapper types in favor of optimizing `&[u8]`
//! and `Vec<u8>` out of the box.
//!
//! [specialization]: https://github.com/rust-lang/rust/issues/31844
use core::{ops, fmt, char, iter, slice};
use core::fmt::Write;
use ser;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::ByteBuf;
#[cfg(any(feature = "std", feature = "collections"))]
#[doc(hidden)] // does anybody need this?
pub use self::bytebuf::ByteBufVisitor;
#[cfg(feature = "collections")]
use collections::Vec;
///////////////////////////////////////////////////////////////////////////////
/// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support
/// deserialization.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::Bytes;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize)]
/// struct Packet<'a> {
/// destination: IpAddr,
/// payload: Bytes<'a>,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> Bytes<'a> {
/// Wrap an existing `&[u8]`.
pub fn new(bytes: &'a [u8]) -> Self {
Bytes { bytes: bytes }
}
}
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in escape_bytestring(self.bytes) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes::new(bytes)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
Bytes::new(bytes)
}
}
impl<'a> Into<&'a [u8]> for Bytes<'a> {
fn into(self) -> &'a [u8] {
self.bytes
}
}
impl<'a> ops::Deref for Bytes<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.bytes
}
}
impl<'a> ser::Serialize for Bytes<'a> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
mod bytebuf {
use core::cmp;
use core::ops;
use core::fmt;
use core::fmt::Write;
use ser;
use de;
#[cfg(feature = "collections")]
use collections::{String, Vec};
/// Wraps a `Vec<u8>` in order to serialize and deserialize in an efficient
/// way.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::ByteBuf;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize, Deserialize)]
/// struct Packet {
/// destination: IpAddr,
/// payload: ByteBuf,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf::from(Vec::new())
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf::from(Vec::with_capacity(cap))
}
/// Wrap existing bytes in a `ByteBuf`.
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
ByteBuf { bytes: bytes.into() }
}
}
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in super::escape_bytestring(self.bytes.as_ref()) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf::from(bytes)
}
}
impl AsRef<Vec<u8>> for ByteBuf {
fn as_ref(&self) -> &Vec<u8> {
&self.bytes
}
}
impl AsRef<[u8]> for ByteBuf {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl AsMut<Vec<u8>> for ByteBuf {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl AsMut<[u8]> for ByteBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes[..]
}
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..]
}
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self)
}
}
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
#[inline]
fn visit_unit<E>(self) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::new())
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor
{
let len = cmp::min(visitor.size_hint().0, 4096);
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
Ok(ByteBuf::from(values))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.deserialize_byte_buf(ByteBufVisitor)
}
}
}
///////////////////////////////////////////////////////////////////////////////
#[inline]
fn escape_bytestring<'a>
(bytes: &'a [u8])
-> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
fn f(b: &u8) -> char::EscapeDefault {
char::from_u32(*b as u32).unwrap().escape_default()
}
bytes.iter().flat_map(f as fn(&u8) -> char::EscapeDefault)
}
File diff suppressed because it is too large Load Diff
+89 -382
View File
@@ -1,6 +1,4 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@@ -8,402 +6,111 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Extracted from https://github.com/rust-num/num.
use lib::*;
// Rust 1.5 is unhappy that this private module is undocumented.
#![allow(missing_docs)]
use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;
/// Numbers which have upper and lower bounds
pub trait Bounded {
// FIXME (#5527): These should be associated constants
/// returns the smallest finite number this type can represent
fn min_value() -> Self;
/// returns the largest finite number this type can represent
fn max_value() -> Self;
}
macro_rules! bounded_impl {
($t:ty, $min:expr, $max:expr) => {
impl Bounded for $t {
#[inline]
fn min_value() -> $t { $min }
#[inline]
fn max_value() -> $t { $max }
}
}
}
bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8, u8::MIN, u8::MAX);
bounded_impl!(u16, u16::MIN, u16::MAX);
bounded_impl!(u32, u32::MIN, u32::MAX);
bounded_impl!(u64, u64::MIN, u64::MAX);
bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8, i8::MIN, i8::MAX);
bounded_impl!(i16, i16::MIN, i16::MAX);
bounded_impl!(i32, i32::MIN, i32::MAX);
bounded_impl!(i64, i64::MIN, i64::MAX);
bounded_impl!(f32, f32::MIN, f32::MAX);
bounded_impl!(f64, f64::MIN, f64::MAX);
/// A generic trait for converting a value to a number.
pub trait ToPrimitive {
/// Converts the value of `self` to an `isize`.
#[inline]
fn to_isize(&self) -> Option<isize> {
self.to_i64().and_then(|x| x.to_isize())
}
/// Converts the value of `self` to an `i8`.
#[inline]
fn to_i8(&self) -> Option<i8> {
self.to_i64().and_then(|x| x.to_i8())
}
/// Converts the value of `self` to an `i16`.
#[inline]
fn to_i16(&self) -> Option<i16> {
self.to_i64().and_then(|x| x.to_i16())
}
/// Converts the value of `self` to an `i32`.
#[inline]
fn to_i32(&self) -> Option<i32> {
self.to_i64().and_then(|x| x.to_i32())
}
/// Converts the value of `self` to an `i64`.
fn to_i64(&self) -> Option<i64>;
/// Converts the value of `self` to a `usize`.
#[inline]
fn to_usize(&self) -> Option<usize> {
self.to_u64().and_then(|x| x.to_usize())
}
/// Converts the value of `self` to an `u8`.
#[inline]
fn to_u8(&self) -> Option<u8> {
self.to_u64().and_then(|x| x.to_u8())
}
/// Converts the value of `self` to an `u16`.
#[inline]
fn to_u16(&self) -> Option<u16> {
self.to_u64().and_then(|x| x.to_u16())
}
/// Converts the value of `self` to an `u32`.
#[inline]
fn to_u32(&self) -> Option<u32> {
self.to_u64().and_then(|x| x.to_u32())
}
/// Converts the value of `self` to an `u64`.
#[inline]
fn to_u64(&self) -> Option<u64>;
/// Converts the value of `self` to an `f32`.
#[inline]
fn to_f32(&self) -> Option<f32> {
self.to_f64().and_then(|x| x.to_f32())
}
/// Converts the value of `self` to an `f64`.
#[inline]
fn to_f64(&self) -> Option<f64> {
self.to_i64().and_then(|x| x.to_f64())
}
}
macro_rules! impl_to_primitive_int_to_int {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let n = $slf as i64;
let min_value: $DstT = Bounded::min_value();
let max_value: $DstT = Bounded::max_value();
if min_value as i64 <= n && n <= max_value as i64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_int_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_int {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_int! { isize }
impl_to_primitive_int! { i8 }
impl_to_primitive_int! { i16 }
impl_to_primitive_int! { i32 }
impl_to_primitive_int! { i64 }
macro_rules! impl_to_primitive_uint_to_int {
($DstT:ty, $slf:expr) => (
{
let max_value: $DstT = Bounded::max_value();
if $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_uint_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_uint {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> {
impl_to_primitive_uint_to_uint!($T, usize, *self)
}
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_uint! { usize }
impl_to_primitive_uint! { u8 }
impl_to_primitive_uint! { u16 }
impl_to_primitive_uint! { u32 }
impl_to_primitive_uint! { u64 }
macro_rules! impl_to_primitive_float_to_float {
($SrcT:ident, $DstT:ident, $slf:expr) => (
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
macro_rules! int_to_int {
($dst:ident, $n:ident) => (
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
Some($n as $dst)
} else {
let n = $slf as f64;
let max_value: $SrcT = ::core::$SrcT::MAX;
if -max_value as f64 <= n && n <= max_value as f64 {
Some($slf as $DstT)
} else {
None
}
None
}
)
}
macro_rules! impl_to_primitive_float {
($T:ident) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { Some(*self as isize) }
#[inline]
fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
#[inline]
fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
#[inline]
fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
#[inline]
fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
#[inline]
fn to_usize(&self) -> Option<usize> { Some(*self as usize) }
#[inline]
fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
#[inline]
fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
#[inline]
fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
#[inline]
fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
#[inline]
fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
#[inline]
fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
macro_rules! int_to_uint {
($dst:ident, $n:ident) => (
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
)
}
impl_to_primitive_float! { f32 }
impl_to_primitive_float! { f64 }
macro_rules! uint_to {
($dst:ident, $n:ident) => (
if $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
)
}
pub trait FromPrimitive: Sized {
#[inline]
fn from_isize(n: isize) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i8(n: i8) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
fn from_isize(n: isize) -> Option<Self>;
fn from_i8(n: i8) -> Option<Self>;
fn from_i16(n: i16) -> Option<Self>;
fn from_i32(n: i32) -> Option<Self>;
fn from_i64(n: i64) -> Option<Self>;
#[inline]
fn from_usize(n: usize) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
fn from_usize(n: usize) -> Option<Self>;
fn from_u8(n: u8) -> Option<Self>;
fn from_u16(n: u16) -> Option<Self>;
fn from_u32(n: u32) -> Option<Self>;
fn from_u64(n: u64) -> Option<Self>;
#[inline]
fn from_f32(n: f32) -> Option<Self> {
FromPrimitive::from_f64(n as f64)
}
#[inline]
fn from_f64(n: f64) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
}
macro_rules! impl_from_primitive {
($T:ty, $to_ty:ident) => (
impl FromPrimitive for $T {
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
macro_rules! impl_from_primitive_for_int {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
}
)
}
impl_from_primitive! { isize, to_isize }
impl_from_primitive! { i8, to_i8 }
impl_from_primitive! { i16, to_i16 }
impl_from_primitive! { i32, to_i32 }
impl_from_primitive! { i64, to_i64 }
impl_from_primitive! { usize, to_usize }
impl_from_primitive! { u8, to_u8 }
impl_from_primitive! { u16, to_u16 }
impl_from_primitive! { u32, to_u32 }
impl_from_primitive! { u64, to_u64 }
impl_from_primitive! { f32, to_f32 }
impl_from_primitive! { f64, to_f64 }
macro_rules! impl_from_primitive_for_uint {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
}
)
}
macro_rules! impl_from_primitive_for_float {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
}
)
}
impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
+215
View File
@@ -0,0 +1,215 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// An efficient way of discarding data from a deserializer.
///
/// Think of this like `serde_json::Value` in that it can be deserialized from
/// any type, except that it does not store any information about the data that
/// gets deserialized.
///
/// ```rust
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, IgnoredAny};
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
/// ///
/// /// For example to deserialize only the element at index 3:
/// ///
/// /// ```rust
/// /// NthElement::new(3).deserialize(deserializer)
/// /// ```
/// pub struct NthElement<T> {
/// n: usize,
/// marker: PhantomData<T>,
/// }
///
/// impl<T> NthElement<T> {
/// pub fn new(n: usize) -> Self {
/// NthElement {
/// n: n,
/// marker: PhantomData,
/// }
/// }
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// {
/// type Value = T;
///
/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// write!(formatter, "a sequence in which we care about element {}", self.n)
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de>
/// {
/// // Skip over the first `n` elements.
/// for i in 0..self.n {
/// // It is an error if the sequence ends before we get to element `n`.
/// if seq.next_element::<IgnoredAny>()?.is_none() {
/// return Err(de::Error::invalid_length(i, &self));
/// }
/// }
///
/// // Deserialize the one we care about.
/// let nth = match seq.next_element()? {
/// Some(nth) => nth,
/// None => {
/// return Err(de::Error::invalid_length(self.n, &self));
/// }
/// };
///
/// // Skip over any remaining elements in the sequence after `n`.
/// while let Some(IgnoredAny) = seq.next_element()? {
/// // ignore
/// }
///
/// Ok(nth)
/// }
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// {
/// type Value = T;
///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de>
/// {
/// deserializer.deserialize_seq(self)
/// }
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de>
/// # {
/// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and
/// // after index 3 are allowed to be of any type.
/// let s: String = NthElement::new(3).deserialize(deserializer)?;
/// # Ok(())
/// # }
/// ```
#[derive(Copy, Clone, Debug, Default)]
pub struct IgnoredAny;
impl<'de> Visitor<'de> for IgnoredAny {
type Value = IgnoredAny;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("anything at all")
}
#[inline]
fn visit_bool<E>(self, x: bool) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_i64<E>(self, x: i64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
let _ = s;
Ok(IgnoredAny)
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
IgnoredAny::deserialize(deserializer)
}
#[inline]
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
IgnoredAny::deserialize(deserializer)
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
while let Some(IgnoredAny) = try!(seq.next_element()) {
// Gobble
}
Ok(IgnoredAny)
}
#[inline]
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
// Gobble
}
Ok(IgnoredAny)
}
#[inline]
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let _ = bytes;
Ok(IgnoredAny)
}
}
impl<'de> Deserialize<'de> for IgnoredAny {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_ignored_any(IgnoredAny)
}
}
+1421 -663
View File
File diff suppressed because it is too large Load Diff
+1091 -658
View File
File diff suppressed because it is too large Load Diff
-44
View File
@@ -1,44 +0,0 @@
use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
UntaggedUnitVisitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
where V: Deserialize,
E: Error
{
struct MissingFieldDeserializer<E>(&'static str, PhantomData<E>);
impl<E> Deserializer for MissingFieldDeserializer<E>
where E: Error
{
type Error = E;
fn deserialize<V>(self, _visitor: V) -> Result<V::Value, E>
where V: Visitor
{
Err(Error::missing_field(self.0))
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
where V: Visitor
{
visitor.visit_none()
}
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
let deserializer = MissingFieldDeserializer(field, PhantomData);
Deserialize::deserialize(deserializer)
}
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use 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: buf, pos: 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()
}
}
+731 -476
View File
File diff suppressed because it is too large Load Diff
-17
View File
@@ -1,17 +0,0 @@
//! A stand-in for `std::error`
use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
pub trait Error: Debug + Display {
/// A short description of the error.
///
/// The description should not contain newlines or sentence-ending
/// punctuation, to facilitate embedding in larger user-facing
/// strings.
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> {
None
}
}
+39 -32
View File
@@ -1,34 +1,41 @@
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::String;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::option::Option::{self, None, Some};
pub use core::result::Result::{self, Ok, Err};
#[cfg(any(feature = "collections", feature = "std"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
// Copyright 2017 Serde Developers
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "collections", feature = "std")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
use core::str;
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use lib::clone::Clone;
pub use lib::convert::{From, Into};
pub use lib::default::Default;
pub use lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some};
pub use lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy;
mod string {
use lib::*;
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "std", feature = "alloc")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
}
-73
View File
@@ -1,73 +0,0 @@
//! Module that contains helper iterators.
use std::io;
use std::iter::Peekable;
/// Iterator over a byte stream that tracks the current position's line and column.
pub struct LineColIterator<Iter: Iterator<Item = io::Result<u8>>> {
iter: Iter,
line: usize,
col: usize,
}
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Iter> {
/// Construct a new `LineColIterator<Iter>`.
pub fn new(iter: Iter) -> LineColIterator<Iter> {
LineColIterator {
iter: iter,
line: 1,
col: 0,
}
}
/// Report the current line inside the iterator.
pub fn line(&self) -> usize {
self.line
}
/// Report the current column inside the iterator.
pub fn col(&self) -> usize {
self.col
}
/// Gets a reference to the underlying iterator.
pub fn get_ref(&self) -> &Iter {
&self.iter
}
/// Gets a mutable reference to the underlying iterator.
pub fn get_mut(&mut self) -> &mut Iter {
&mut self.iter
}
/// Unwraps this `LineColIterator`, returning the underlying iterator.
pub fn into_inner(self) -> Iter {
self.iter
}
}
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Peekable<Iter>> {
/// peeks at the next value
pub fn peek(&mut self) -> Option<&io::Result<u8>> {
self.iter.peek()
}
}
impl<Iter: Iterator<Item = io::Result<u8>>> Iterator for LineColIterator<Iter> {
type Item = io::Result<u8>;
fn next(&mut self) -> Option<io::Result<u8>> {
match self.iter.next() {
None => None,
Some(Ok(b'\n')) => {
self.line += 1;
self.col = 0;
Some(Ok(b'\n'))
}
Some(Ok(c)) => {
self.col += 1;
Some(Ok(c))
}
Some(Err(e)) => Some(Err(e)),
}
}
}
+236 -60
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
@@ -9,99 +17,267 @@
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website https://serde.rs/ for additional documentation and
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! ### Design
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code
//! generation to automatically derive implementations at compile time). This
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform roughly the same speed as a handwritten serializer
//! for the specific selection of data structure and data format.
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ### Data formats
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object
//! Notation used by many HTTP APIs.
//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object
//! Representation designed for small message size without the need for
//! version negotiation.
//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly
//! configuration language that ain't markup language.
//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary
//! format that resembles a compact JSON.
//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration
//! format used by [Cargo](http://doc.crates.io/manifest.html).
//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in
//! the Python world.
//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed
//! to be readable and writable by humans.
//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network
//! transfer format used by MongoDB.
//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded
//! format.
//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C
//! standard. *(deserialization only)*
//! - [Envy](https://github.com/softprops/envy), a way to deserialize
//! environment variables into Rust structs. *(deserialization only)*
//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from
//! Redis when using [redis-rs](https://crates.io/crates/redis).
//! - [CBOR], a Concise Binary Object Representation designed for small message
//! size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//! language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//! *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//! *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//! *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis
#![doc(html_root_url="https://docs.serde.rs")]
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.29")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(inclusive_range, nonzero, specialization, zero_one))]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![deny(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy",
allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist,
needless_pass_by_value, redundant_field_names, type_complexity,
unreadable_literal, zero_prefixed_literal))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// simplifies some macros
invalid_upcast_comparisons,
// things are often more readable this way
decimal_literal_representation,
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
single_match_else,
stutter,
use_self,
// not practical
many_single_char_names,
missing_docs_in_private_items,
similar_names,
// alternative is not stable
empty_enum,
use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
#[cfg(feature = "collections")]
extern crate collections;
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "unstable")]
extern crate core as actual_core;
#[cfg(all(feature = "unstable", feature = "std"))]
extern crate core;
/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
mod core {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))]
pub use core::*;
}
pub use self::core::{cmp, iter, mem, ops, slice, str};
pub use self::core::{isize, i16, i32, i64, i8};
pub use self::core::{usize, u16, u32, u64, u8};
pub use self::core::{f32, f64};
pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone};
pub use self::core::convert::{self, From, Into};
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
#[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::borrow::{Cow, ToOwned};
#[cfg(feature = "std")]
pub use std::string::String;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::string::{String, ToString};
#[cfg(feature = "std")]
pub use std::vec::Vec;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::vec::Vec;
#[cfg(feature = "std")]
pub use std::boxed::Box;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::boxed::Box;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::Arc;
#[cfg(feature = "std")]
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::{error, net};
#[cfg(feature = "std")]
pub use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")]
pub use std::ffi::{CStr, CString, OsStr, OsString};
#[cfg(feature = "std")]
pub use std::hash::{BuildHasher, Hash};
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(feature = "std")]
pub use std::num::Wrapping;
#[cfg(feature = "std")]
pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")]
mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option};
#[cfg(feature = "unstable")]
pub use actual_core::nonzero;
pub use core::nonzero::{NonZero, Zeroable};
}
////////////////////////////////////////////////////////////////////////////////
#[macro_use]
mod macros;
pub mod ser;
pub mod de;
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[macro_use]
mod macros;
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod iter;
pub mod ser;
#[cfg_attr(feature = "std", doc(hidden))]
pub mod error;
mod utils;
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;
// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;
// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
// [features]
// serde-impls = ["serde", "serde_derive"]
//
// [dependencies]
// serde = { version = "1.0", optional = true }
// serde_derive = { version = "1.0", optional = true }
//
// # Used like this:
// # #[cfg(feature = "serde-impls")]
// # #[macro_use]
// # extern crate serde_derive;
// #
// # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
// [dependencies]
// serde = { version = "1.0", optional = true, features = ["derive"] }
//
// # Used like this:
// # #[cfg(feature = "serde")]
// # #[macro_use]
// # extern crate serde;
// #
// # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// 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;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
+198 -178
View File
@@ -1,122 +1,10 @@
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(u8) => {
forward_to_deserialize_method!{deserialize_u8()}
};
(u16) => {
forward_to_deserialize_method!{deserialize_u16()}
};
(u32) => {
forward_to_deserialize_method!{deserialize_u32()}
};
(u64) => {
forward_to_deserialize_method!{deserialize_u64()}
};
(i8) => {
forward_to_deserialize_method!{deserialize_i8()}
};
(i16) => {
forward_to_deserialize_method!{deserialize_i16()}
};
(i32) => {
forward_to_deserialize_method!{deserialize_i32()}
};
(i64) => {
forward_to_deserialize_method!{deserialize_i64()}
};
(f32) => {
forward_to_deserialize_method!{deserialize_f32()}
};
(f64) => {
forward_to_deserialize_method!{deserialize_f64()}
};
(char) => {
forward_to_deserialize_method!{deserialize_char()}
};
(str) => {
forward_to_deserialize_method!{deserialize_str()}
};
(string) => {
forward_to_deserialize_method!{deserialize_string()}
};
(unit) => {
forward_to_deserialize_method!{deserialize_unit()}
};
(option) => {
forward_to_deserialize_method!{deserialize_option()}
};
(seq) => {
forward_to_deserialize_method!{deserialize_seq()}
};
(seq_fixed_size) => {
forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)}
};
(bytes) => {
forward_to_deserialize_method!{deserialize_bytes()}
};
(byte_buf) => {
forward_to_deserialize_method!{deserialize_byte_buf()}
};
(map) => {
forward_to_deserialize_method!{deserialize_map()}
};
(unit_struct) => {
forward_to_deserialize_method!{deserialize_unit_struct(&'static str)}
};
(newtype_struct) => {
forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)}
};
(tuple_struct) => {
forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)}
};
(struct) => {
forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])}
};
(struct_field) => {
forward_to_deserialize_method!{deserialize_struct_field()}
};
(tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)}
};
(enum) => {
forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
}
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize
@@ -125,98 +13,230 @@ macro_rules! forward_to_deserialize_helper {
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
///
/// Some `Deserializer` implementations for self-describing formats do not care
/// what hint the `Visitor` gives them, they just want to blindly call the
/// `Visitor` method corresponding to the data they can tell is in the input.
/// This requires repetitive implementations of all the `Deserializer` trait
/// methods.
/// Some [`Deserializer`] implementations for self-describing formats do not
/// care what hint the [`Visitor`] gives them, they just want to blindly call
/// the [`Visitor`] method corresponding to the data they can tell is in the
/// input. This requires repetitive implementations of all the [`Deserializer`]
/// trait methods.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// # impl Deserializer for MyDeserializer {
/// #
/// # struct MyDeserializer;
/// #
/// # impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error;
/// # fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor
/// # { unimplemented!() }
/// #
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # {
/// # unimplemented!()
/// # }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// where V: Visitor<'de>
/// {
/// self.deserialize(visitor)
/// self.deserialize_any(visitor)
/// }
/// # forward_to_deserialize! {
/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// # tuple_struct struct struct_field tuple enum ignored_any
/// #
/// # forward_to_deserialize_any! {
/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// # byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any
/// # }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You
/// can choose which methods to forward.
/// The `forward_to_deserialize_any!` macro implements these simple forwarding
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
/// You can choose which methods to forward.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// impl Deserializer for MyDeserializer {
/// #
/// # struct MyDeserializer;
/// #
/// impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error;
/// fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// {
/// /* ... */
/// # let _ = visitor;
/// # unimplemented!()
/// }
///
/// forward_to_deserialize! {
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any
/// forward_to_deserialize_any! {
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct map struct enum identifier ignored_any
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// The macro assumes the convention that your `Deserializer` lifetime parameter
/// is called `'de` and that the `Visitor` type parameters on each method are
/// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use std::marker::PhantomData;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer<V>(PhantomData<V>);
/// #
/// # impl<'q, V> Deserializer<'q> for MyDeserializer<V> {
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q>
/// # {
/// # unimplemented!()
/// # }
/// #
/// forward_to_deserialize_any! {
/// <W: Visitor<'q>>
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
/// map struct enum identifier ignored_any
/// }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// [`Deserializer`]: trait.Deserializer.html
/// [`Visitor`]: de/trait.Visitor.html
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
#[macro_export]
macro_rules! forward_to_deserialize {
macro_rules! forward_to_deserialize_any {
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
$(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})*
};
// This case must be after the previous one.
($($func:ident)*) => {
$(forward_to_deserialize_helper!{$func})*
$(forward_to_deserialize_any_helper!{$func<'de, V>})*
};
}
/// Seralize the `$value` that implements Display as a string,
/// when that string is statically known to never have more than
/// a constant `$MAX_LEN` bytes.
///
/// Panics if the Display impl tries to write more than `$MAX_LEN` bytes.
#[cfg(feature = "std")]
// Not exported
macro_rules! serialize_display_bounded_length {
($value: expr, $MAX_LEN: expr, $serializer: expr) => {
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_any_method {
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
#[inline]
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error>
where
$v: $crate::de::Visitor<$l>,
{
use std::io::Write;
let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() };
let remaining_len;
{
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
remaining_len = remaining.len()
}
let written_len = buffer.len() - remaining_len;
let written = &buffer[..written_len];
// write! only provides std::fmt::Formatter to Display implementations,
// which has methods write_str and write_char but no method to write arbitrary bytes.
// Therefore, `written` is well-formed in UTF-8.
let written_str = unsafe {
::std::str::from_utf8_unchecked(written)
};
$serializer.serialize_str(written_str)
$(
let _ = $arg;
)*
self.deserialize_any(visitor)
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_any_helper {
(bool<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()}
};
(i8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i8<$l, $v>()}
};
(i16<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i16<$l, $v>()}
};
(i32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i32<$l, $v>()}
};
(i64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
};
(u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
};
(u16<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u16<$l, $v>()}
};
(u32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u32<$l, $v>()}
};
(u64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
};
(f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
};
(f64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()}
};
(char<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_char<$l, $v>()}
};
(str<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_str<$l, $v>()}
};
(string<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_string<$l, $v>()}
};
(bytes<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bytes<$l, $v>()}
};
(byte_buf<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_byte_buf<$l, $v>()}
};
(option<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_option<$l, $v>()}
};
(unit<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_unit<$l, $v>()}
};
(unit_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_unit_struct<$l, $v>(name: &'static str)}
};
(newtype_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)}
};
(seq<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_seq<$l, $v>()}
};
(tuple<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_tuple<$l, $v>(len: usize)}
};
(tuple_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)}
};
(map<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_map<$l, $v>()}
};
(struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
};
(enum<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])}
};
(identifier<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_identifier<$l, $v>()}
};
(ignored_any<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_ignored_any<$l, $v>()}
};
}
File diff suppressed because it is too large Load Diff
+148
View File
@@ -0,0 +1,148 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[doc(hidden)]
#[macro_export]
macro_rules! __private_serialize {
() => {
trait Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::Serializer;
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private_deserialize {
() => {
trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: $crate::Deserializer<'de>;
}
};
}
/// Used only by Serde doc tests. Not public API.
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented {
($($func:ident)*) => {
$(
__serialize_unimplemented_helper!($func);
)*
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented_method {
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::export::Result<Self::$ret, Self::Error> {
unimplemented!()
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented_helper {
(bool) => {
__serialize_unimplemented_method!(serialize_bool(bool) -> Ok);
};
(i8) => {
__serialize_unimplemented_method!(serialize_i8(i8) -> Ok);
};
(i16) => {
__serialize_unimplemented_method!(serialize_i16(i16) -> Ok);
};
(i32) => {
__serialize_unimplemented_method!(serialize_i32(i32) -> Ok);
};
(i64) => {
__serialize_unimplemented_method!(serialize_i64(i64) -> Ok);
};
(u8) => {
__serialize_unimplemented_method!(serialize_u8(u8) -> Ok);
};
(u16) => {
__serialize_unimplemented_method!(serialize_u16(u16) -> Ok);
};
(u32) => {
__serialize_unimplemented_method!(serialize_u32(u32) -> Ok);
};
(u64) => {
__serialize_unimplemented_method!(serialize_u64(u64) -> Ok);
};
(f32) => {
__serialize_unimplemented_method!(serialize_f32(f32) -> Ok);
};
(f64) => {
__serialize_unimplemented_method!(serialize_f64(f64) -> Ok);
};
(char) => {
__serialize_unimplemented_method!(serialize_char(char) -> Ok);
};
(str) => {
__serialize_unimplemented_method!(serialize_str(&str) -> Ok);
};
(bytes) => {
__serialize_unimplemented_method!(serialize_bytes(&[u8]) -> Ok);
};
(none) => {
__serialize_unimplemented_method!(serialize_none() -> Ok);
};
(some) => {
__serialize_unimplemented_method!(serialize_some<T>(&T) -> Ok);
};
(unit) => {
__serialize_unimplemented_method!(serialize_unit() -> Ok);
};
(unit_struct) => {
__serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok);
};
(unit_variant) => {
__serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok);
};
(newtype_struct) => {
__serialize_unimplemented_method!(serialize_newtype_struct<T>(&str, &T) -> Ok);
};
(newtype_variant) => {
__serialize_unimplemented_method!(serialize_newtype_variant<T>(&str, u32, &str, &T) -> Ok);
};
(seq) => {
type SerializeSeq = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_seq(Option<usize>) -> SerializeSeq);
};
(tuple) => {
type SerializeTuple = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple(usize) -> SerializeTuple);
};
(tuple_struct) => {
type SerializeTupleStruct = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_struct(&str, usize) -> SerializeTupleStruct);
};
(tuple_variant) => {
type SerializeTupleVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_variant(&str, u32, &str, usize) -> SerializeTupleVariant);
};
(map) => {
type SerializeMap = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_map(Option<usize>) -> SerializeMap);
};
(struct) => {
type SerializeStruct = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct(&str, usize) -> SerializeStruct);
};
(struct_variant) => {
type SerializeStructVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct_variant(&str, u32, &str, usize) -> SerializeStructVariant);
};
}
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod macros;
pub mod ser;
pub mod de;
File diff suppressed because it is too large Load Diff
-635
View File
@@ -1,635 +0,0 @@
use core::marker::PhantomData;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
use ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<Content>,
}
impl<M> SerializeTupleVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeTupleVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), M::Error>
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end()
}
}
pub struct SerializeStructVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<(&'static str, Content)>,
}
impl<M> SerializeStructVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeStructVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), M::Error>
{
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end()
}
}
#[derive(Debug)]
enum Content {
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
Char(char),
String(String),
Bytes(Vec<u8>),
None,
Some(Box<Content>),
Unit,
UnitStruct(&'static str),
UnitVariant(&'static str, usize, &'static str),
NewtypeStruct(&'static str, Box<Content>),
NewtypeVariant(&'static str, usize, &'static str, Box<Content>),
Seq(Vec<Content>),
SeqFixedSize(Vec<Content>),
Tuple(Vec<Content>),
TupleStruct(&'static str, Vec<Content>),
TupleVariant(&'static str, usize, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>),
}
impl Serialize for Content {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
match *self {
Content::Bool(b) => serializer.serialize_bool(b),
Content::U8(u) => serializer.serialize_u8(u),
Content::U16(u) => serializer.serialize_u16(u),
Content::U32(u) => serializer.serialize_u32(u),
Content::U64(u) => serializer.serialize_u64(u),
Content::I8(i) => serializer.serialize_i8(i),
Content::I16(i) => serializer.serialize_i16(i),
Content::I32(i) => serializer.serialize_i32(i),
Content::I64(i) => serializer.serialize_i64(i),
Content::F32(f) => serializer.serialize_f32(f),
Content::F64(f) => serializer.serialize_f64(f),
Content::Char(c) => serializer.serialize_char(c),
Content::String(ref s) => serializer.serialize_str(s),
Content::Bytes(ref b) => serializer.serialize_bytes(b),
Content::None => serializer.serialize_none(),
Content::Some(ref c) => serializer.serialize_some(&**c),
Content::Unit => serializer.serialize_unit(),
Content::UnitStruct(n) => serializer.serialize_unit_struct(n),
Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v),
Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c),
Content::NewtypeVariant(n, i, v, ref c) => serializer.serialize_newtype_variant(n, i, v, &**c),
Content::Seq(ref elements) => elements.serialize(serializer),
Content::SeqFixedSize(ref elements) => {
use ser::SerializeSeq;
let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len()));
for e in elements {
try!(seq.serialize_element(e));
}
seq.end()
}
Content::Tuple(ref elements) => {
use ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
for e in elements {
try!(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()));
for f in fields {
try!(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()));
for f in fields {
try!(tv.serialize_field(f));
}
tv.end()
}
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
for &(ref k, ref v) in entries {
try!(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()));
for &(k, ref v) in fields {
try!(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()));
for &(k, ref v) in fields {
try!(sv.serialize_field(k, v));
}
sv.end()
}
}
}
}
struct ContentSerializer<E> {
error: PhantomData<E>,
}
impl<E> ContentSerializer<E> {
fn new() -> Self {
ContentSerializer {
error: PhantomData,
}
}
}
impl<E> Serializer for ContentSerializer<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
type SerializeSeq = SerializeSeq<E>;
type SerializeTuple = SerializeTuple<E>;
type SerializeTupleStruct = SerializeTupleStruct<E>;
type SerializeTupleVariant = SerializeTupleVariant<E>;
type SerializeMap = SerializeMap<E>;
type SerializeStruct = SerializeStruct<E>;
type SerializeStructVariant = SerializeStructVariant<E>;
fn serialize_bool(self, v: bool) -> Result<Content, E> {
Ok(Content::Bool(v))
}
fn serialize_i8(self, v: i8) -> Result<Content, E> {
Ok(Content::I8(v))
}
fn serialize_i16(self, v: i16) -> Result<Content, E> {
Ok(Content::I16(v))
}
fn serialize_i32(self, v: i32) -> Result<Content, E> {
Ok(Content::I32(v))
}
fn serialize_i64(self, v: i64) -> Result<Content, E> {
Ok(Content::I64(v))
}
fn serialize_u8(self, v: u8) -> Result<Content, E> {
Ok(Content::U8(v))
}
fn serialize_u16(self, v: u16) -> Result<Content, E> {
Ok(Content::U16(v))
}
fn serialize_u32(self, v: u32) -> Result<Content, E> {
Ok(Content::U32(v))
}
fn serialize_u64(self, v: u64) -> Result<Content, E> {
Ok(Content::U64(v))
}
fn serialize_f32(self, v: f32) -> Result<Content, E> {
Ok(Content::F32(v))
}
fn serialize_f64(self, v: f64) -> Result<Content, E> {
Ok(Content::F64(v))
}
fn serialize_char(self, v: char) -> Result<Content, E> {
Ok(Content::Char(v))
}
fn serialize_str(self, value: &str) -> Result<Content, E> {
Ok(Content::String(value.to_owned()))
}
fn serialize_bytes(self, value: &[u8]) -> Result<Content, E> {
Ok(Content::Bytes(value.to_owned()))
}
fn serialize_none(self) -> Result<Content, E> {
Ok(Content::None)
}
fn serialize_some<T: ?Sized + Serialize>(self,
value: &T)
-> Result<Content, E> {
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
}
fn serialize_unit(self) -> Result<Content, E> {
Ok(Content::Unit)
}
fn serialize_unit_struct(self,
name: &'static str)
-> Result<Content, E> {
Ok(Content::UnitStruct(name))
}
fn serialize_unit_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str)
-> Result<Content, E> {
Ok(Content::UnitVariant(name, variant_index, variant))
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
name: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))))
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeVariant(name, variant_index, variant, Box::new(try!(value.serialize(self)))))
}
fn serialize_seq(self,
len: Option<usize>)
-> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: false,
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
}
fn serialize_seq_fixed_size(self,
size: usize)
-> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: true,
elements: Vec::with_capacity(size),
error: PhantomData,
})
}
fn serialize_tuple(self,
len: usize)
-> Result<Self::SerializeTuple, E> {
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeTupleStruct, E> {
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, E> {
Ok(SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_map(self,
len: Option<usize>)
-> Result<Self::SerializeMap, E> {
Ok(SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
}
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, E> {
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, E> {
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
struct SerializeSeq<E> {
fixed_size: bool,
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeSeq for SerializeSeq<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(if self.fixed_size {
Content::SeqFixedSize(self.elements)
} else {
Content::Seq(self.elements)
})
}
}
struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTuple for SerializeTuple<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Tuple(self.elements))
}
}
struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleStruct(self.name, self.fields))
}
}
struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeMap for SerializeMap<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self,
key: &T)
-> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self,
value: &T)
-> Result<(), E> {
let key = self.key.take().expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Map(self.entries))
}
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
key: &K,
value: &V)
-> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
}
struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStruct for SerializeStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Struct(self.name, self.fields))
}
}
struct SerializeStructVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
+470 -503
View File
File diff suppressed because it is too large Load Diff
+122 -51
View File
@@ -1,19 +1,35 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `Impossible` serializer and its implementations.
use core::marker::PhantomData;
use lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
///
/// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the `Serializer` compound types: `SerializeSeq`,
/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`,
/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`.
/// corresponding to the [`Serializer`] compound types: [`SerializeSeq`],
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
///
/// ```rust,ignore
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
/// #
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
@@ -27,130 +43,185 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
/// -> Result<Self::SerializeSeq, Error> {
/// // Given Impossible cannot be instantiated, the only
/// // thing we can do here is to return an error.
/// # stringify! {
/// Err(...)
/// # };
/// # unimplemented!()
/// }
///
/// /* other Serializer methods */
/// # __serialize_unimplemented! {
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant
/// # tuple tuple_struct tuple_variant map struct struct_variant
/// # }
/// }
/// #
/// # fn main() {}
/// ```
pub struct Impossible<Ok, E> {
///
/// [`Serializer`]: trait.Serializer.html
/// [`SerializeSeq`]: trait.SerializeSeq.html
/// [`SerializeTuple`]: trait.SerializeTuple.html
/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html
/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html
/// [`SerializeMap`]: trait.SerializeMap.html
/// [`SerializeStruct`]: trait.SerializeStruct.html
/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html
pub struct Impossible<Ok, Error> {
void: Void,
_marker: PhantomData<(Ok, E)>,
ok: PhantomData<Ok>,
error: PhantomData<Error>,
}
enum Void {}
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeSeq for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeTuple for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeTupleStruct for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeTupleVariant for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, E> SerializeMap for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeMap for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> {
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
match self.void {}
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeStruct for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where E: ser::Error
impl<Ok, Error> SerializeStructVariant for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = E;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, E> {
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
+1361 -327
View File
File diff suppressed because it is too large Load Diff
-313
View File
@@ -1,313 +0,0 @@
use core::fmt::{self, Display};
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
#[cfg(any(feature = "std", feature = "collections"))]
use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
/// Not public API.
pub fn serialize_tagged_newtype<S, T>(serializer: S,
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
value: &T)
-> Result<S::Ok, S::Error>
where S: Serializer,
T: Serialize
{
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
delegate: S,
}
enum Unsupported {
Boolean,
Integer,
Float,
Char,
String,
ByteArray,
Optional,
Unit,
UnitStruct,
Sequence,
Tuple,
TupleStruct,
#[cfg(not(any(feature = "std", feature = "collections")))]
Enum,
}
impl Display for Unsupported {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unsupported::Boolean => formatter.write_str("a boolean"),
Unsupported::Integer => formatter.write_str("an integer"),
Unsupported::Float => formatter.write_str("a float"),
Unsupported::Char => formatter.write_str("a char"),
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "collections")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
}
struct Error {
type_ident: &'static str,
variant_ident: &'static str,
ty: Unsupported,
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter,
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident, self.variant_ident, self.ty)
}
}
impl<S> TaggedSerializer<S>
where S: Serializer
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(Error {
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
}
}
impl<S> Serializer for TaggedSerializer<S>
where S: Serializer
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = Impossible<S::Ok, S::Error>;
type SerializeTuple = Impossible<S::Ok, S::Error>;
type SerializeTupleStruct = Impossible<S::Ok, S::Error>;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeStructVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(self,
_: &'static str,
_: usize,
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, &()));
map.end()
}
fn serialize_newtype_struct<T: ?Sized>(self,
_: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
inner_value: &T)
-> Result<Self::Ok, Self::Error>
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));
map.end()
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_seq_fixed_size(self, _: usize) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(self,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the tuple variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
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));
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len))
}
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));
Ok(map)
}
fn serialize_struct(self,
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));
Ok(state)
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the struct variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
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));
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len))
}
}
-74
View File
@@ -1,74 +0,0 @@
//! Private utility functions
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_utf8(c: char) -> EncodeUtf8 {
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
};
EncodeUtf8 {
buf: buf,
pos: pos,
}
}
pub struct EncodeUtf8 {
buf: [u8; 4],
pos: usize,
}
impl EncodeUtf8 {
// FIXME: use this from_utf8_unchecked, since we know it can never fail
pub fn as_str(&self) -> &str {
::core::str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
#[allow(non_upper_case_globals)]
const Pattern_White_Space_table: &'static [(char, char)] = &[('\u{9}', '\u{d}'),
('\u{20}', '\u{20}'),
('\u{85}', '\u{85}'),
('\u{200e}', '\u{200f}'),
('\u{2028}', '\u{2029}')];
fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
use core::cmp::Ordering::{Equal, Less, Greater};
r.binary_search_by(|&(lo, hi)| if c < lo {
Greater
} else if hi < c {
Less
} else {
Equal
})
.is_ok()
}
#[allow(non_snake_case)]
pub fn Pattern_White_Space(c: char) -> bool {
bsearch_range_table(c, Pattern_White_Space_table)
}
-18
View File
@@ -1,18 +0,0 @@
[package]
name = "serde_codegen_internals"
version = "0.14.1"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"]
readme = "../README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
syn = { version = "0.11", default-features = false, features = ["parsing"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
-122
View File
@@ -1,122 +0,0 @@
use syn;
use attr;
use Ctxt;
pub struct Item<'a> {
pub ident: syn::Ident,
pub attrs: attr::Item,
pub body: Body<'a>,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a syn::Ty,
}
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Item<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> {
let attrs = attr::Item::from_ast(cx, item);
let mut body = match item.body {
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data);
Body::Struct(style, fields)
}
};
match body {
Body::Enum(ref mut variants) => {
for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
}
}
Body::Struct(_, ref mut fields) => {
for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
}
}
}
Item {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: &item.generics,
}
}
}
impl<'a> Body<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Box::new(variants.iter()
.flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
}
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
variants.iter()
.map(|variant| {
let (style, fields) = struct_from_ast(cx, &variant.data);
Variant {
ident: variant.ident.clone(),
attrs: attr::Variant::from_ast(cx, variant),
style: style,
fields: fields,
}
})
.collect()
}
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields)),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields))
}
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields)),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
fields.iter()
.enumerate()
.map(|(i, field)| {
Field {
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field),
ty: &field.ty,
}
})
.collect()
}
-799
View File
@@ -1,799 +0,0 @@
use Ctxt;
use syn;
use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem};
use std::str::FromStr;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
// `attr::Field::from_ast`. Each returns an instance of the corresponding
// struct. Note that none of them return a Result. Unrecognized, malformed, or
// duplicated attributes result in a span_err but otherwise are ignored. The
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
pub use case::RenameRule;
struct Attr<'c, T> {
cx: &'c Ctxt,
name: &'static str,
value: Option<T>,
}
impl<'c, T> Attr<'c, T> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
Attr {
cx: cx,
name: name,
value: None,
}
}
fn set(&mut self, value: T) {
if self.value.is_some() {
self.cx.error(format!("duplicate serde attribute `{}`", self.name));
} else {
self.value = Some(value);
}
}
fn set_opt(&mut self, value: Option<T>) {
if let Some(value) = value {
self.set(value);
}
}
fn set_if_none(&mut self, value: T) {
if self.value.is_none() {
self.value = Some(value);
}
}
fn get(self) -> Option<T> {
self.value
}
}
struct BoolAttr<'c>(Attr<'c, ()>);
impl<'c> BoolAttr<'c> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
BoolAttr(Attr::none(cx, name))
}
fn set_true(&mut self) {
self.0.set(());
}
fn get(&self) -> bool {
self.0.value.is_some()
}
}
#[derive(Debug)]
pub struct Name {
serialize: String,
deserialize: String,
}
impl Name {
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String {
self.serialize.clone()
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
}
}
/// Represents container (e.g. struct) attribute information
#[derive(Debug)]
pub struct Item {
name: Name,
deny_unknown_fields: bool,
default: Default,
rename_all: RenameRule,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
tag: EnumTag,
}
/// Styles of representing an enum.
#[derive(Debug)]
pub enum EnumTag {
/// The default.
///
/// ```json
/// {"variant1": {"key1": "value1", "key2": "value2"}}
/// ```
External,
/// `#[serde(tag = "type")]`
///
/// ```json
/// {"type": "variant1", "key1": "value1", "key2": "value2"}
/// ```
Internal { tag: String },
/// `#[serde(tag = "t", content = "c")]`
///
/// ```json
/// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
/// ```
Adjacent { tag: String, content: String },
/// `#[serde(untagged)]`
///
/// ```json
/// {"key1": "value1", "key2": "value2"}
/// ```
None,
}
impl Item {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut default = Attr::none(cx, "default");
let mut rename_all = Attr::none(cx, "rename_all");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let mut untagged = BoolAttr::none(cx, "untagged");
let mut internal_tag = Attr::none(cx, "tag");
let mut content = Attr::none(cx, "content");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(rename_all="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
}
}
}
// Parse `#[serde(deny_unknown_fields)]`
MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Default);
}
_ => {
cx.error("#[serde(default)] can only be used on structs \
with named fields")
}
}
}
// Parse `#[serde(default="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Path(path));
}
_ => {
cx.error("#[serde(default = \"...\")] can only be used \
on structs with named fields")
}
}
}
}
// Parse `#[serde(bound="D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
// Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => {
match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
}
}
// Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
internal_tag.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(tag = \"...\")] can only be used on enums")
}
}
}
}
// Parse `#[serde(content = "c")]`
MetaItem(NameValue(ref name, ref lit)) if name == "content" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
content.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(content = \"...\")] can only be used on \
enums")
}
}
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error("unexpected literal in serde container attribute");
}
}
}
}
let tag = match (untagged.get(), internal_tag.get(), content.get()) {
(false, None, None) => EnumTag::External,
(true, None, None) => EnumTag::None,
(false, Some(tag), None) => {
// Check that there are no tuple variants.
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) |
syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error("#[serde(tag = \"...\")] cannot be used with tuple \
variants");
break;
}
}
}
}
}
EnumTag::Internal { tag: tag }
}
(true, Some(_), None) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
(false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External
}
(true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External
}
};
Item {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
},
deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None),
rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
tag: tag,
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
pub fn default(&self) -> &Default {
&self.default
}
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn tag(&self) -> &EnumTag {
&self.tag
}
}
/// Represents variant attribute information
#[derive(Debug)]
pub struct Variant {
name: Name,
ser_renamed: bool,
de_renamed: bool,
rename_all: RenameRule,
skip_deserializing: bool,
skip_serializing: bool,
}
impl Variant {
pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut rename_all = Attr::none(cx, "rename_all");
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(rename_all="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
}
}
}
// Parse `#[serde(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
}
Literal(_) => {
cx.error("unexpected literal in serde variant attribute");
}
}
}
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Variant {
name: Name {
serialize: ser_name.unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.unwrap_or_else(|| variant.ident.to_string()),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
rename_all: rename_all.get().unwrap_or(RenameRule::None),
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_variant(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_variant(&self.name.deserialize);
}
}
pub fn rename_all(&self) -> &RenameRule {
&self.rename_all
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
}
/// Represents field attribute information
#[derive(Debug)]
pub struct Field {
name: Name,
ser_renamed: bool,
de_renamed: bool,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<syn::Path>,
default: Default,
serialize_with: Option<syn::Path>,
deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
/// Represents the default to use for a field when deserializing.
#[derive(Debug, PartialEq)]
pub enum Default {
/// Field must always be specified because it does not have a default.
None,
/// The default is given by `std::default::Default::default()`.
Default,
/// The default is given by this function.
Path(syn::Path),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing_if = Attr::none(cx, "skip_serializing_if");
let mut default = Attr::none(cx, "default");
let mut serialize_with = Attr::none(cx, "serialize_with");
let mut deserialize_with = Attr::none(cx, "deserialize_with");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
let ident = match field.ident {
Some(ref ident) => ident.to_string(),
None => index.to_string(),
};
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename="foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
default.set(Default::Default);
}
// Parse `#[serde(default="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
default.set(Default::Path(path));
}
}
// Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing_if="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
skip_serializing_if.set(path);
}
}
// Parse `#[serde(serialize_with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
serialize_with.set(path);
}
}
// Parse `#[serde(deserialize_with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
deserialize_with.set(path);
}
}
// Parse `#[serde(with="...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
let mut ser_path = path.clone();
ser_path.segments.push("serialize".into());
serialize_with.set(ser_path);
let mut de_path = path;
de_path.segments.push("deserialize".into());
deserialize_with.set(de_path);
}
}
// Parse `#[serde(bound="D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`", meta_item.name()));
}
Literal(_) => {
cx.error("unexpected literal in serde field attribute");
}
}
}
}
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]`
if skip_deserializing.0.value.is_some() {
default.set_if_none(Default::Default);
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Field {
name: Name {
serialize: ser_name.unwrap_or_else(|| ident.clone()),
deserialize: de_name.unwrap_or(ident),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
default: default.get().unwrap_or(Default::None),
serialize_with: serialize_with.get(),
deserialize_with: deserialize_with.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_field(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_field(&self.name.deserialize);
}
}
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
}
pub fn skip_serializing_if(&self) -> Option<&syn::Path> {
self.skip_serializing_if.as_ref()
}
pub fn default(&self) -> &Default {
&self.default
}
pub fn serialize_with(&self) -> Option<&syn::Path> {
self.serialize_with.as_ref()
}
pub fn deserialize_with(&self) -> Option<&syn::Path> {
self.deserialize_with.as_ref()
}
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
type SerAndDe<T> = (Option<T>, Option<T>);
fn get_ser_and_de<T, F>(cx: &Ctxt,
attr_name: &'static str,
items: &[syn::NestedMetaItem],
f: F)
-> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>
{
let mut ser_item = Attr::none(cx, attr_name);
let mut de_item = Attr::none(cx, attr_name);
for item in items {
match *item {
MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
ser_item.set(v);
}
}
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
de_item.set(v);
}
}
_ => {
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., \
deserialize = ...)`",
attr_name));
return Err(());
}
}
}
Ok((ser_item.get(), de_item.get()))
}
fn get_renames(cx: &Ctxt, items: &[syn::NestedMetaItem]) -> Result<SerAndDe<String>, ()> {
get_ser_and_de(cx, "rename", items, get_string_from_lit)
}
fn get_where_predicates(cx: &Ctxt,
items: &[syn::NestedMetaItem])
-> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
match attr.value {
List(ref name, ref items) if name == "serde" => Some(items.iter().cloned().collect()),
_ => None,
}
}
fn get_string_from_lit(cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit)
-> Result<String, ()> {
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name,
meta_item_name));
Err(())
}
}
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_path(&string).map_err(|err| cx.error(err))
}
fn parse_lit_into_where(cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit)
-> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
if string.is_empty() {
return Ok(Vec::new());
}
let where_string = format!("where {}", string);
syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err))
}
-9
View File
@@ -1,9 +0,0 @@
extern crate syn;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
+14 -9
View File
@@ -1,27 +1,32 @@
[package]
name = "serde_derive"
version = "0.9.10"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
version = "1.0.29" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization", "no_std"]
readme = "../README.md"
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[features]
unstable = []
[badges]
travis-ci = { repository = "serde-rs/serde" }
[features]
default = []
deserialize_in_place = []
[lib]
name = "serde_derive"
proc-macro = true
[dependencies]
quote = "0.3.8"
serde_codegen_internals = { version = "=0.14.1", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.11", features = ["visit"] }
proc-macro2 = "0.2"
quote = "0.4"
serde_derive_internals = { version = "=0.20.0", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.12", features = ["visit"] }
[dev-dependencies]
serde = { version = "1.0", path = "../serde" }
+229 -135
View File
@@ -1,70 +1,88 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::HashSet;
use syn::{self, visit};
use syn::punctuated::Punctuated;
use internals::ast::Item;
use internals::ast::{Data, Container};
use internals::attr;
macro_rules! path {
($first:ident $(:: $rest:ident)*) => {
syn::Path {
global: false,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
(::$first:ident $(:: $rest:ident)*) => {
syn::Path {
global: true,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
}
use proc_macro2::{Span, Term};
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
ty_params: generics.ty_params
params: generics
.params
.iter()
.map(|ty_param| syn::TyParam { default: None, ..ty_param.clone() })
.map(|param| match *param {
syn::GenericParam::Type(ref param) => {
syn::GenericParam::Type(syn::TypeParam {
eq_token: None,
default: None,
..param.clone()
})
}
_ => param.clone(),
})
.collect(),
..generics.clone()
}
}
pub fn with_where_predicates(generics: &syn::Generics,
predicates: &[syn::WherePredicate])
-> syn::Generics {
pub fn with_where_predicates(
generics: &syn::Generics,
predicates: &[syn::WherePredicate],
) -> syn::Generics {
let mut generics = generics.clone();
generics.where_clause.predicates.extend_from_slice(predicates);
if generics.where_clause.is_none() {
generics.where_clause = Some(syn::WhereClause {
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates
.extend(predicates.into_iter().cloned());
generics
}
pub fn with_where_predicates_from_fields<F>(item: &Item,
generics: &syn::Generics,
from_field: F)
-> syn::Generics
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>
pub fn with_where_predicates_from_fields<F>(
cont: &Container,
generics: &syn::Generics,
from_field: F,
) -> syn::Generics
where
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
let predicates = item.body
let predicates = cont.data
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.where_clause.predicates.extend(predicates);
if generics.where_clause.is_none() {
generics.where_clause = Some(syn::WhereClause {
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates
.extend(predicates);
generics
}
@@ -79,12 +97,14 @@ pub fn with_where_predicates_from_fields<F>(item: &Item,
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(item: &Item,
generics: &syn::Generics,
filter: F,
bound: &syn::Path)
-> syn::Generics
where F: Fn(&attr::Field) -> bool
pub fn with_bound<F>(
cont: &Container,
generics: &syn::Generics,
filter: F,
bound: &syn::Path,
) -> syn::Generics
where
F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
@@ -95,134 +115,208 @@ pub fn with_bound<F>(item: &Item,
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
impl<'ast> visit::Visit<'ast> for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
if seg.into_value().ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if path.leading_colon.is_none() && path.segments.len() == 1 {
let id = path.segments[0].ident;
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
visit::visit_path(self, path);
}
// Type parameter should not be considered used by a macro path.
//
// struct TypeMacro<T> {
// mac: T!(),
// marker: PhantomData<T>,
// }
fn visit_macro(&mut self, _mac: &syn::Macro) {}
}
let all_ty_params: HashSet<_> = generics.ty_params
let all_ty_params: HashSet<_> = generics
.params
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter_map(|param| match *param {
syn::GenericParam::Type(ref param) => Some(param.ident),
_ => None,
})
.collect();
let relevant_tys = item.body
.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
match cont.data {
Data::Enum(ref variants) => for variant in variants.iter() {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
visit::visit_type(&mut visitor, field.ty);
}
},
Data::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visit::visit_type(&mut visitor, field.ty);
}
}
}
let new_predicates = generics.ty_params
let new_predicates = generics
.params
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter_map(|param| match *param {
syn::GenericParam::Type(ref param) => Some(param.ident),
_ => None,
})
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| {
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
bounded_ty: syn::Type::Path(syn::TypePath {
qself: None,
path: id.into(),
}),
colon_token: Default::default(),
// the bound e.g. Serialize
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None
)],
bounds: vec![
syn::TypeParamBound::Trait(syn::TraitBound {
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: bound.clone(),
}),
].into_iter().collect(),
})
});
let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
if generics.where_clause.is_none() {
generics.where_clause = Some(syn::WhereClause {
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates
.extend(new_predicates);
generics
}
pub fn with_self_bound(item: &Item,
generics: &syn::Generics,
bound: &syn::Path)
-> syn::Generics
{
pub fn with_self_bound(
cont: &Container,
generics: &syn::Generics,
bound: &syn::Path,
) -> syn::Generics {
let mut generics = generics.clone();
generics.where_clause.predicates.push(
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
if generics.where_clause.is_none() {
generics.where_clause = Some(syn::WhereClause {
where_token: Default::default(),
predicates: Punctuated::new(),
});
}
generics.where_clause
.as_mut()
.unwrap()
.predicates
.push(syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(item),
bounded_ty: type_of_item(cont),
colon_token: Default::default(),
// the bound e.g. Default
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None
)],
})
);
generics
}
pub fn with_lifetime_bound(generics: &syn::Generics,
lifetime: &str)
-> syn::Generics {
let mut generics = generics.clone();
for lifetime_def in &mut generics.lifetimes {
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
}
for ty_param in &mut generics.ty_params {
ty_param.bounds.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
}
generics.lifetimes.push(syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
});
generics
}
fn type_of_item(item: &Item) -> syn::Ty {
syn::Ty::Path(None, syn::Path {
global: false,
segments: vec![
syn::PathSegment {
ident: item.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
lifetimes: item.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
types: item.generics
.ty_params
.iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(),
bindings: Vec::new(),
bounds: vec![
syn::TypeParamBound::Trait(syn::TraitBound {
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: bound.clone(),
}),
}
]
].into_iter().collect(),
}));
generics
}
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let bound = syn::Lifetime::new(Term::intern(lifetime), Span::def_site());
let def = syn::LifetimeDef {
attrs: Vec::new(),
lifetime: bound,
colon_token: None,
bounds: Punctuated::new(),
};
let params = Some(syn::GenericParam::Lifetime(def))
.into_iter()
.chain(generics.params
.iter()
.cloned()
.map(|mut param| {
match param {
syn::GenericParam::Lifetime(ref mut param) => {
param.bounds.push(bound);
}
syn::GenericParam::Type(ref mut param) => {
param.bounds.push(syn::TypeParamBound::Lifetime(bound));
}
syn::GenericParam::Const(_) => {}
}
param
}))
.collect();
syn::Generics {
params: params,
..generics.clone()
}
}
fn type_of_item(cont: &Container) -> syn::Type {
syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: vec![
syn::PathSegment {
ident: cont.ident,
arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: Default::default(),
args: cont.generics
.params
.iter()
.map(|param| match *param {
syn::GenericParam::Type(ref param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None,
path: param.ident.into(),
}))
}
syn::GenericParam::Lifetime(ref param) => {
syn::GenericArgument::Lifetime(param.lifetime)
}
syn::GenericParam::Const(_) => {
panic!("Serde does not support const generics yet");
}
})
.collect(),
gt_token: Default::default(),
},
),
},
].into_iter().collect(),
},
})
}
+1785 -653
View File
File diff suppressed because it is too large Load Diff
+22 -8
View File
@@ -1,4 +1,13 @@
use quote::{Tokens, ToTokens};
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{ToTokens, Tokens};
use syn::token;
pub enum Fragment {
/// Tokens that can be used as an expression.
@@ -28,9 +37,7 @@ impl ToTokens for Expr {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
@@ -55,13 +62,20 @@ impl ToTokens for Match {
match self.0 {
Fragment::Expr(ref expr) => {
expr.to_tokens(out);
out.append(",");
<Token![,]>::default().to_tokens(out);
}
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
}
impl AsRef<Tokens> for Fragment {
fn as_ref(&self) -> &Tokens {
match *self {
Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block,
}
}
}
+37 -9
View File
@@ -1,17 +1,45 @@
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This crate provides Serde's two derive macros.
//!
//! ```rust
//! # #[macro_use]
//! # extern crate serde_derive;
//! #
//! #[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.29")]
#![cfg_attr(feature = "cargo-clippy", allow(enum_variant_names, redundant_field_names,
too_many_arguments, used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
#![recursion_limit = "256"]
extern crate syn;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate serde_codegen_internals as internals;
extern crate serde_derive_internals as internals;
extern crate proc_macro;
extern crate proc_macro2;
use proc_macro::TokenStream;
use syn::DeriveInput;
#[macro_use]
mod bound;
@@ -23,18 +51,18 @@ mod de;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
let input: DeriveInput = syn::parse(input).unwrap();
match ser::expand_derive_serialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Ok(expanded) => expanded.into(),
Err(msg) => panic!(msg),
}
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
let input: DeriveInput = syn::parse(input).unwrap();
match de::expand_derive_deserialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Ok(expanded) => expanded.into(),
Err(msg) => panic!(msg),
}
}
+642 -362
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
[package]
name = "serde_derive_internals"
version = "0.20.0" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
proc-macro2 = "0.2"
syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+164
View File
@@ -0,0 +1,164 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn;
use attr;
use check;
use Ctxt;
use syn::punctuated::Punctuated;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
pub data: Data<'a>,
pub generics: &'a syn::Generics,
}
pub enum Data<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a syn::Type,
pub original: &'a syn::Field,
}
#[derive(Copy, Clone)]
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
let attrs = attr::Container::from_ast(cx, item);
let mut data = match item.data {
syn::Data::Enum(ref data) => {
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
}
syn::Data::Struct(ref data) => {
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
Data::Struct(style, fields)
}
syn::Data::Union(_) => {
panic!("Serde does not support derive for unions");
}
};
match data {
Data::Enum(ref mut variants) => for variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
},
Data::Struct(_, ref mut fields) => for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
},
}
let item = Container {
ident: item.ident,
attrs: attrs,
data: data,
generics: &item.generics,
};
check::check(cx, &item);
item
}
}
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Data::Enum(ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Data::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
fn enum_from_ast<'a>(
cx: &Ctxt,
variants: &'a Punctuated<syn::Variant, Token![,]>,
container_default: &attr::Default,
) -> Vec<Variant<'a>> {
variants
.iter()
.map(|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) =
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant {
ident: variant.ident,
attrs: attrs,
style: style,
fields: fields,
}
})
.collect()
}
fn struct_from_ast<'a>(
cx: &Ctxt,
fields: &'a syn::Fields,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
match *fields {
syn::Fields::Named(ref fields) => (
Style::Struct,
fields_from_ast(cx, &fields.named, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) => (
Style::Tuple,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::Fields::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(
cx: &Ctxt,
fields: &'a Punctuated<syn::Field, Token![,]>,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(|(i, field)| Field {
ident: field.ident,
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty,
original: field,
})
.collect()
}
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,27 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
#[allow(unused_imports)]
use std::ascii::AsciiExt;
use std::str::FromStr;
use self::RenameRule::*;
#[derive(Debug, PartialEq)]
#[derive(PartialEq)]
pub enum RenameRule {
/// Don't apply a default rename rule.
None,
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "UPPERCASE" style.
UPPERCASE,
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
@@ -17,12 +32,16 @@ pub enum RenameRule {
ScreamingSnakeCase,
/// Rename direct children to "kebab-case" style.
KebabCase,
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
ScreamingKebabCase,
}
impl RenameRule {
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(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
@@ -36,12 +55,16 @@ impl RenameRule {
}
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase
.apply_to_variant(variant)
.replace('_', "-"),
}
}
pub fn apply_to_field(&self, field: &str) -> String {
match *self {
None | SnakeCase => field.to_owned(),
None | LowerCase | SnakeCase => field.to_owned(),
UPPERCASE => field.to_ascii_uppercase(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
@@ -63,6 +86,7 @@ impl RenameRule {
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
}
}
}
@@ -72,11 +96,14 @@ impl FromStr for RenameRule {
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str {
"lowercase" => Ok(LowerCase),
"UPPERCASE" => Ok(UPPERCASE),
"PascalCase" => Ok(PascalCase),
"camelCase" => Ok(CamelCase),
"snake_case" => Ok(SnakeCase),
"SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
"kebab-case" => Ok(KebabCase),
"SCREAMING-KEBAB-CASE" => Ok(ScreamingKebabCase),
_ => Err(()),
}
}
@@ -84,32 +111,76 @@ impl FromStr for RenameRule {
#[test]
fn rename_variants() {
for &(original, camel, snake, screaming, kebab) in
&[("Outcome", "outcome", "outcome", "OUTCOME", "outcome"),
("VeryTasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
("A", "a", "a", "A", "a"),
("Z42", "z42", "z42", "Z42", "z42")] {
for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
(
"Outcome",
"outcome",
"OUTCOME",
"outcome",
"outcome",
"OUTCOME",
"outcome",
"OUTCOME",
),
(
"VeryTasty",
"verytasty",
"VERYTASTY",
"veryTasty",
"very_tasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("A", "a", "A", "a", "a", "A", "a", "A"),
("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(UPPERCASE.apply_to_variant(original), upper);
assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab);
assert_eq!(
ScreamingKebabCase.apply_to_variant(original),
screaming_kebab
);
}
}
#[test]
fn rename_fields() {
for &(original, pascal, camel, screaming, kebab) in
&[("outcome", "Outcome", "outcome", "OUTCOME", "outcome"),
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty"),
("a", "A", "a", "A", "a"),
("z42", "Z42", "z42", "Z42", "z42")] {
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
(
"outcome",
"OUTCOME",
"Outcome",
"outcome",
"OUTCOME",
"outcome",
"OUTCOME",
),
(
"very_tasty",
"VERY_TASTY",
"VeryTasty",
"veryTasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("a", "A", "A", "a", "A", "a", "A"),
("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(UPPERCASE.apply_to_field(original), upper);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
assert_eq!(SnakeCase.apply_to_field(original), original);
assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
assert_eq!(KebabCase.apply_to_field(original), kebab);
assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab);
}
}
+237
View File
@@ -0,0 +1,237 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Data, Container, Style};
use attr::{Identifier, EnumTag};
use Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
check_getter(cx, cont);
check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont);
check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(_) => {
if cont.data.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Data::Struct(_, _) => {
if cont.data.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
);
}
}
}
}
/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (
variant.style,
cont.attrs.identifier(),
variant.attrs.other(),
) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true) => {
if i < variants.len() - 1 {
cx.error("#[serde(other)] must be the last variant");
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true) => {
cx.error("#[serde(other)] must be on a unit variant");
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false) => {
if i < variants.len() - 1 {
cx.error(format!("`{}` must be the last variant", variant.ident));
}
}
(_, Identifier::Field, false) => {
cx.error("field_identifier may only contain unit variants");
}
(_, Identifier::Variant, false) => {
cx.error("variant_identifier may only contain unit variants");
}
}
}
}
/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return;
}
};
for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
variant.ident
));
}
for (i, field) in variant.fields.iter().enumerate() {
let ident = field
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
if field.attrs.skip_serializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident
));
}
if field.attrs.skip_serializing_if().is_some() {
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident
));
}
}
}
if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() {
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
variant.ident
));
}
for (i, field) in variant.fields.iter().enumerate() {
if field.attrs.skip_deserializing() {
let ident = field
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident
));
}
}
}
}
}
/// The tag of an internally-tagged struct variant must not be
/// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(
cx: &Ctxt,
cont: &Container,
) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => return,
};
let tag = match *cont.attrs.tag() {
EnumTag::Internal { ref tag } => tag.as_str(),
EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
};
let diagnose_conflict = || {
let message = format!(
"variant field name `{}` conflicts with internal tag",
tag
);
cx.error(message);
};
for variant in variants {
match variant.style {
Style::Struct => {
for field in &variant.fields {
let check_ser = !field.attrs.skip_serializing();
let check_de = !field.attrs.skip_deserializing();
let name = field.attrs.name();
let ser_name = name.serialize_name();
let de_name = name.deserialize_name();
if check_ser && ser_name == tag || check_de && de_name == tag {
diagnose_conflict();
return;
}
}
},
Style::Unit | Style::Newtype | Style::Tuple => {},
}
}
}
/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
let (type_tag, content_tag) = match *cont.attrs.tag() {
EnumTag::Adjacent { ref tag, ref content } => (tag, content),
EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
};
if type_tag == content_tag {
let message = format!(
"enum tags `{}` for type and content conflict with each other",
type_tag
);
cx.error(message);
}
}
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Display;
use std::cell::RefCell;
@@ -8,11 +16,17 @@ pub struct Ctxt {
impl Ctxt {
pub fn new() -> Self {
Ctxt { errors: RefCell::new(Some(Vec::new())) }
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
}
pub fn error<T: Display>(&self, msg: T) {
self.errors.borrow_mut().as_mut().unwrap().push(msg.to_string());
self.errors
.borrow_mut()
.as_mut()
.unwrap()
.push(msg.to_string());
}
pub fn check(self) -> Result<(), String> {
+25
View File
@@ -0,0 +1,25 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.20.0")]
#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity, doc_markdown, match_same_arms,
redundant_field_names))]
#[macro_use]
extern crate syn;
extern crate proc_macro2;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
mod check;
+8 -4
View File
@@ -1,18 +1,22 @@
[package]
name = "serde_test"
version = "0.9.10"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
version = "1.0.29" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"]
readme = "../README.md"
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
serde = { version = "0.9", path = "../serde" }
serde = { version = "1.0.16", path = "../serde" }
[dev-dependencies]
serde = { version = "1.0.16", path = "../serde", features = ["rc"] }
serde_derive = { version = "1.0", path = "../serde_derive" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+232 -29
View File
@@ -1,54 +1,257 @@
use serde::{Serialize, Deserialize};
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{Deserialize, Serialize};
use de::Deserializer;
use error::Error;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Serialize + Deserialize + PartialEq + Debug
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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,
/// ]);
/// # }
/// ```
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`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_ser_tokens, Token};
/// #
/// # fn main() {
/// #[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,
/// ]);
/// # }
/// ```
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: Serialize
where
T: Serialize,
{
let mut ser = Serializer::new(tokens.iter());
assert_eq!(Serialize::serialize(value, &mut ser), Ok(()));
assert_eq!(ser.next_token(), None);
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());
}
}
/// Expect an error serializing `T`.
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde_test;
/// #
/// # fn main() {
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// use serde_test::{assert_ser_tokens_error, Token};
///
/// #[derive(Serialize)]
/// struct Example {
/// lock: Arc<Mutex<u32>>,
/// }
///
/// let example = Example { lock: Arc::new(Mutex::new(0)) };
/// let lock = example.lock.clone();
///
/// let _ = 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!()
/// }).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);
/// # }
/// ```
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: &str)
where
T: Serialize,
{
let mut ser = Serializer::new(tokens.iter());
let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
assert_eq!(v.as_ref(), Err(&error));
assert_eq!(ser.next_token(), None);
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());
}
}
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Deserialize + PartialEq + Debug
/// Asserts that the given `tokens` deserialize into `value`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_de_tokens, Token};
/// #
/// # fn main() {
/// #[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,
/// ]);
/// # }
/// ```
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
T: Deserialize<'de> + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.next_token(), None);
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());
}
}
/// Expect an error deserializing tokens into a `T`.
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error)
where T: Deserialize + PartialEq + Debug
/// Asserts that the given `tokens` yield `error` when deserializing.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_de_tokens_error, Token};
/// #
/// # fn main() {
/// #[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`",
/// );
/// # }
/// ```
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
where
T: Deserialize<'de>,
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v, Err(error));
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();
assert_eq!(de.next_token(), None);
de.next_token_opt();
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
}
+664
View File
@@ -0,0 +1,664 @@
use std::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
#[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.
///
/// ```
/// extern crate serde;
/// extern crate serde_test;
///
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{Configure, Token, assert_tokens};
///
/// #[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 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);
+434 -392
View File
File diff suppressed because it is too large Load Diff
+28 -25
View File
@@ -1,48 +1,51 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::error;
use std::fmt::{self, Display};
use serde::{ser, de};
use serde::{de, ser};
use token::Token;
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
Message(String),
InvalidName(&'static str),
UnexpectedToken(Token<'static>),
EndOfTokens,
#[derive(Clone, Debug)]
pub struct Error {
msg: String,
}
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Error {
Error::Message(msg.to_string())
fn custom<T: Display>(msg: T) -> Self {
Error {
msg: msg.to_string(),
}
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Error {
Error::Message(msg.to_string())
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 {
match *self {
Error::Message(ref msg) => formatter.write_str(msg),
Error::InvalidName(name) => write!(formatter, "invalid name `{}`", name),
Error::UnexpectedToken(_) => formatter.write_str("unexpected token"),
Error::EndOfTokens => formatter.write_str("end of tokens"),
}
formatter.write_str(&self.msg)
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Message(ref msg) => msg,
Error::InvalidName(_) => "invalid name",
Error::UnexpectedToken(_) => "unexpected token",
Error::EndOfTokens => "end of tokens",
}
&self.msg
}
}
impl PartialEq<str> for Error {
fn eq(&self, other: &str) -> bool {
self.msg == other
}
}
+180 -12
View File
@@ -1,18 +1,186 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This crate provides a convenient concise way to write unit tests for
//! implementations of [`Serialize`] and [`Deserialize`].
//!
//! [`Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html
//! [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
//!
//! 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`]: https://docs.serde.rs/serde/ser/trait.Serializer.html
//! [`Token`]: https://docs.serde.rs/serde_test/enum.Token.html
//! [`assert_ser_tokens`]: https://docs.serde.rs/serde_test/fn.assert_ser_tokens.html
//! [`assert_de_tokens`]: https://docs.serde.rs/serde_test/fn.assert_de_tokens.html
//! [`assert_tokens`]: https://docs.serde.rs/serde_test/fn.assert_tokens.html
//!
//! Here is an example from the [`linked-hash-map`] crate.
//!
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
//!
//! ```rust
//! # extern crate serde;
//! #
//! # macro_rules! ignore {
//! # ($($tt:tt)+) => {}
//! # }
//! #
//! # ignore! {
//! extern crate linked_hash_map;
//! use linked_hash_map::LinkedHashMap;
//! # }
//!
//! extern crate serde_test;
//! use serde_test::{Token, assert_tokens};
//!
//! # 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.29")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy",
allow(empty_line_after_outer_attr, missing_docs_in_private_items,
redundant_field_names, stutter, use_debug, use_self))]
#[macro_use]
extern crate serde;
mod assert;
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens,
assert_de_tokens_error};
mod ser;
pub use ser::Serializer;
mod de;
pub use de::Deserializer;
mod token;
pub use token::Token;
mod error;
pub use error::Error;
mod configure;
mod token;
mod assert;
pub use token::Token;
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
assert_ser_tokens_error, assert_tokens};
pub use configure::{Compact, Configure, Readable};
// Not public API.
#[doc(hidden)]
pub use de::Deserializer;
+249 -141
View File
@@ -1,363 +1,471 @@
use std::marker::PhantomData;
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{ser, Serialize};
use error::Error;
use token::Token;
pub struct Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
tokens: I,
phantom: PhantomData<&'a Token<'a>>,
/// 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, I> Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
phantom: PhantomData,
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 next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
pub fn remaining(&self) -> usize {
self.tokens.len()
}
}
impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
macro_rules! assert_next_token {
($ser:expr, $expected:ident) => {
assert_next_token!($ser, stringify!($expected), Token::$expected, true);
};
($ser:expr, $expected:ident($v:expr)) => {
assert_next_token!(
$ser,
format_args!("{}({:?})", stringify!($expected), $v),
Token::$expected(v),
v == $v
);
};
($ser:expr, $expected:ident { $($k:ident),* }) => {
let compare = ($($k,)*);
let field_format = || {
use std::fmt::Write;
let mut buffer = String::new();
$(
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
)*
buffer
};
assert_next_token!(
$ser,
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
Token::$expected { $($k),* },
($($k,)*) == compare
);
};
($ser:expr, $expected:expr, $pat:pat, $guard:expr) => {
match $ser.next_token() {
Some($pat) if $guard => {}
Some(other) => {
panic!("expected Token::{} but serialized as {}",
$expected, other);
}
None => {
panic!("expected Token::{} after end of serialized tokens",
$expected);
}
}
};
}
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 = Self;
type SerializeTupleVariant = Variant<'s, 'a>;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Self;
type SerializeStructVariant = Variant<'s, 'a>;
fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
assert_next_token!(self, Bool(v));
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
assert_next_token!(self, I8(v));
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
assert_next_token!(self, I16(v));
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
assert_next_token!(self, I32(v));
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
assert_next_token!(self, I64(v));
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
assert_next_token!(self, U8(v));
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
assert_next_token!(self, U16(v));
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
assert_next_token!(self, U32(v));
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
assert_next_token!(self, U64(v));
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
assert_next_token!(self, F32(v));
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
assert_next_token!(self, F64(v));
Ok(())
}
fn serialize_char(self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
assert_next_token!(self, Char(v));
Ok(())
}
fn serialize_str(self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
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, value: &[u8]) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bytes(value)));
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_eq!(self.tokens.next(), Some(&Token::Unit));
assert_next_token!(self, Unit);
Ok(())
}
fn serialize_unit_struct(self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
assert_next_token!(self, UnitStruct { name });
Ok(())
}
fn serialize_unit_variant(self,
name: &str,
_variant_index: usize,
variant: &str)
-> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
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
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
assert_next_token!(self, NewtypeStruct { name });
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
name: &str,
_variant_index: usize,
variant: &str,
value: &T)
-> Result<(), Error>
where T: Serialize
fn serialize_newtype_variant<T: ?Sized>(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<(), Error>
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
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_eq!(self.tokens.next(), Some(&Token::Option(false)));
assert_next_token!(self, None);
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where T: Serialize
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
assert_next_token!(self, Some);
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
Ok(self)
}
fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
assert_next_token!(self, Seq { len });
Ok(self)
}
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
assert_next_token!(self, Tuple { len });
Ok(self)
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::TupleStructStart(name, len)));
assert_next_token!(self, TupleStruct { name, len });
Ok(self)
}
fn serialize_tuple_variant(self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize)
-> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::EnumSeqStart(name, variant, 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_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
assert_next_token!(self, Map { len });
Ok(self)
}
fn serialize_struct(self, name: &str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
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: &str,
_variant_index: usize,
variant: &str,
len: usize)
-> Result<Self, Error> {
assert_eq!(self.tokens.next(),
Some(&Token::EnumMapStart(name, variant, 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`"
);
}
}
impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
assert_next_token!(self, SeqEnd);
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
assert_next_token!(self, TupleEnd);
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
assert_next_token!(self, TupleStructEnd);
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(&mut **self)
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
match self.end {
Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
_ => unreachable!(),
}
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(&mut **self)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where T: Serialize
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
assert_next_token!(self, MapEnd);
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
assert_next_token!(self, StructEnd);
Ok(())
}
}
impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I>
where I: Iterator<Item = &'a Token<'a>>
{
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
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
try!(key.serialize(&mut *self.ser));
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
match self.end {
Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
Token::MapEnd => assert_next_token!(self.ser, MapEnd),
_ => unreachable!(),
}
Ok(())
}
}
+542 -29
View File
@@ -1,59 +1,572 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::{self, Debug, Display};
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Token {
/// A serialized `bool`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&true, &[Token::Bool(true)]);
/// ```
Bool(bool),
/// A serialized `i8`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i8, &[Token::I8(0)]);
/// ```
I8(i8),
/// A serialized `i16`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i16, &[Token::I16(0)]);
/// ```
I16(i16),
/// A serialized `i32`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i32, &[Token::I32(0)]);
/// ```
I32(i32),
/// A serialized `i64`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i64, &[Token::I64(0)]);
/// ```
I64(i64),
/// A serialized `u8`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u8, &[Token::U8(0)]);
/// ```
U8(u8),
/// A serialized `u16`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u16, &[Token::U16(0)]);
/// ```
U16(u16),
/// A serialized `u32`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u32, &[Token::U32(0)]);
/// ```
U32(u32),
/// A serialized `u64`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u64, &[Token::U64(0)]);
/// ```
U64(u64),
/// A serialized `f32`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f32, &[Token::F32(0.0)]);
/// ```
F32(f32),
/// A serialized `f64`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f64, &[Token::F64(0.0)]);
/// ```
F64(f64),
/// A serialized `char`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&'\n', &[Token::Char('\n')]);
/// ```
Char(char),
Str(&'a str),
String(String),
Bytes(&'a [u8]),
ByteBuf(Vec<u8>),
Option(bool),
/// A serialized `str`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("transient");
/// assert_tokens(&s, &[Token::Str("transient")]);
/// ```
Str(&'static str),
/// A borrowed `str`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s: &str = "borrowed";
/// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]);
/// ```
BorrowedStr(&'static str),
/// A serialized `String`.
///
/// ```rust
/// # 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.
///
/// ```rust
/// # 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.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = Some('c');
/// assert_tokens(&opt, &[
/// Token::Some,
/// Token::Char('c'),
/// ]);
/// ```
Some,
/// A serialized `()`.
///
/// ```rust
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&(), &[Token::Unit]);
/// ```
Unit,
UnitStruct(&'a str),
StructNewType(&'a str),
/// A serialized unit struct of the given name.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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 },
EnumStart(&'a str),
EnumUnit(&'a str, &'a str),
EnumNewType(&'a str, &'a str),
/// A unit variant of an enum.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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,
},
SeqStart(Option<usize>),
SeqArrayStart(usize),
SeqSep,
/// The header to a serialized newtype struct of the given name.
///
/// After this header is the value contained in the newtype struct.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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`.
///
/// ```rust
/// # 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,
TupleStart(usize),
TupleSep,
/// The header to a tuple.
///
/// After this header are the elements of the tuple, followed by `TupleEnd`.
///
/// ```rust
/// # 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,
TupleStructStart(&'a str, usize),
TupleStructSep,
/// The header to a tuple struct.
///
/// After this header are the fields of the tuple struct, followed by
/// `TupleStructEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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,
MapStart(Option<usize>),
MapSep,
/// The header to a tuple variant of an enum.
///
/// After this header are the fields of the tuple variant, followed by
/// `TupleVariantEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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`.
///
/// ```rust
/// # 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,
StructStart(&'a str, usize),
StructSep,
/// The header of a struct.
///
/// After this header are the fields of the struct, followed by `StructEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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,
EnumSeqStart(&'a str, &'a str, usize),
EnumSeqSep,
EnumSeqEnd,
/// The header of a struct variant of an enum.
///
/// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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,
},
EnumMapStart(&'a str, &'a str, usize),
EnumMapSep,
EnumMapEnd,
/// An indicator of the end of a struct variant.
StructVariantEnd,
/// The header to an enum of the given name.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # 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)
}
}
+6 -5
View File
@@ -1,18 +1,19 @@
[package]
name = "serde_test_suite"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
publish = false
[features]
unstable-testing = ["compiletest_rs"]
unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies]
fnv = "1.0"
proc-macro2 = "0.2"
rustc-serialize = "0.3.16"
serde = { path = "../serde" }
serde_derive = { path = "../serde_derive" }
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.2", optional = true }
compiletest_rs = { version = "0.3", optional = true }
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(/*=============================================]
#![=== Serde test suite requires a nightly compiler. ===]
#![====================================================*/)]
+3
View File
@@ -4,5 +4,8 @@ version = "0.0.0"
publish = false
[dependencies]
libc = { version = "0.2", default-features = false }
serde = { path = "../../serde", default-features = false }
serde_derive = { path = "../../serde_derive" }
[workspace]
+10 -1
View File
@@ -1,7 +1,16 @@
#![feature(lang_items, start, libc)]
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(lang_items, start, compiler_builtins_lib)]
#![no_std]
extern crate libc;
extern crate compiler_builtins;
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "zzz")] //~^^ HELP: failed to parse borrowed lifetimes: "zzz"
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "'a + 'a")] //~^^ HELP: duplicate borrowed lifetime `'a`
s: &'a str,
}
fn main() {}
@@ -0,0 +1,21 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)]
struct Str<'a>(&'a str);
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
enum Test<'a> {
#[serde(borrow)] //~^^ HELP: duplicate serde attribute `borrow`
S(#[serde(borrow)] Str<'a>)
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "")] //~^^ HELP: at least one lifetime must be borrowed
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test {
#[serde(borrow)] //~^^ HELP: field `s` has no lifetimes to borrow
s: String,
}
fn main() {}
@@ -0,0 +1,21 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)]
struct Str<'a>(&'a str);
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
enum Test<'a> {
#[serde(borrow)] //~^^ HELP: #[serde(borrow)] may only be used on newtype variants
S { s: Str<'a> }
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "'b")] //~^^ HELP: field `s` does not have lifetime 'b
s: &'a str,
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "conflict", content = "conflict")]
//~^^ HELP: enum tags `conflict` for type and content conflict with each other
enum E {
A,
B,
}
fn main() {}
@@ -0,0 +1,22 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "conflict")]
//~^^ HELP: variant field name `conflict` conflicts with internal tag
enum E {
A {
#[serde(rename = "conflict")]
x: (),
},
}
fn main() {}
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier, variant_identifier)] //~^ HELP: `field_identifier` and `variant_identifier` cannot both be set
enum F {
A,
B,
}
fn main() {}
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
struct S; //~^^ HELP: `field_identifier` can only be used on an enum
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
B(u8, u8), //~^^^^ HELP: field_identifier may only contain unit variants
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
Other(String), //~^^^^ HELP: `Other` must be the last variant
B,
}
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
enum F {
A,
#[serde(other)] //~^^^ HELP: #[serde(other)] may only be used inside a field_identifier
B,
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be on a unit variant
Other(u8, u8),
}
fn main() {}
@@ -0,0 +1,21 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be the last variant
Other,
B,
}
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)] //~^ HELP: field identifiers cannot be serialized
enum F {
A,
B,
}
fn main() {}
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(variant_identifier)]
struct S; //~^^ HELP: `variant_identifier` can only be used on an enum
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(variant_identifier)]
enum F {
A,
B(u8, u8), //~^^^^ HELP: variant_identifier may only contain unit variants
}
fn main() {}
@@ -0,0 +1,25 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "remote::S")]
struct S {
#[serde(getter = "~~~")] //~^^^ HELP: failed to parse path: "~~~"
a: u8,
}
fn main() {}
@@ -0,0 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "~~~")] //~^ HELP: failed to parse path: "~~~"
struct S {
a: u8,
}
fn main() {}
@@ -0,0 +1,27 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub enum E {
A { a: u8 }
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "remote::E")]
pub enum E {
A {
#[serde(getter = "get_a")] //~^^^^ HELP: #[serde(getter = "...")] is not allowed in an enum
a: u8,
}
}
fn main() {}
@@ -0,0 +1,25 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u8,
pub b: u8,
}
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")]
struct S {
a: u8, //~^^^ ERROR: missing field `b` in initializer of `remote::S`
}
fn main() {}
@@ -0,0 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(getter = "S::get")] //~^^ HELP: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")]
a: u8,
}
impl S {
fn get(&self) -> u8 {
self.a
}
}
fn main() {}

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