Compare commits

...

725 Commits

Author SHA1 Message Date
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
David Tolnay 51ed9c2a40 Release 0.9.10 2017-02-28 12:45:39 -08: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
David Tolnay fe9ea3b4b4 Fix needless_pass_by_value lint 2017-02-27 19:43:42 -08:00
David Tolnay f944b453c4 Merge pull request #792 from elliottslaughter/fix_serialize_tuple_docs
Fix documentation of serialize_tuple and SerializeTuple
2017-02-27 14:05:15 -08:00
Elliott Slaughter a993630cf9 Fix documentation of serialize_tuple and SerializeTuple. 2017-02-27 14:00:21 -08:00
David Tolnay abc081ce9c Test rename_all attribute 2017-02-25 11:58:34 -08:00
David Tolnay 207940046b Merge pull request #788 from 46bit/issue-140
`rename_all` container attribute to have all children fit a naming convention
2017-02-25 11:38:33 -08:00
David Tolnay 47efbc6d75 Don't need to pass back the input here 2017-02-25 11:32:27 -08:00
David Tolnay 17279e8a4f Simplify case conversion implementation 2017-02-25 11:32:22 -08:00
David Tolnay 06c631db05 Bring in the tests 2017-02-25 11:02:51 -08:00
David Tolnay 7952bad41f Move case conversion to its own file 2017-02-25 11:02:25 -08:00
Michael Mokrysz 3308f81c3a Saving progress on naming convention conversion code to try new Inflector changes. #788 2017-02-25 13:24:49 +00:00
David Tolnay 75e6da02d3 Split up test suite so it compiles in parallel 2017-02-24 15:39:18 -08:00
David Tolnay 59ec931d8f Release 0.9.9 2017-02-24 13:57:52 -08:00
David Tolnay 4b3c5ea99e Fix clippy lint in content serializer 2017-02-24 13:56:44 -08:00
David Tolnay d4ea4a7eef Add test for enums containing enums
Fixes #775.
2017-02-24 13:50:47 -08:00
David Tolnay 5fbdadefb2 Deserializing enums in serde_test 2017-02-24 13:47:04 -08:00
David Tolnay 4da77e4200 Serialize to Content 2017-02-24 12:59:35 -08:00
David Tolnay d797504407 Deserialize enums from &Content 2017-02-24 09:32:14 -08:00
Michael Mokrysz 84915268ee Minor fixes for pull request. Cheers @dtolnay. 2017-02-24 01:55:31 +00:00
Michael Mokrysz 3b59d47e07 Heavily refactored rename_all and switched to SCREAMING_SNAKE_CASE. 2017-02-23 23:22:54 +00:00
Michael Mokrysz fc94c5399a Implementing rename_all container attribute using Inflector trait. #140 2017-02-23 18:58:41 +00:00
David Tolnay 8e5f472e27 Merge pull request #787 from 46bit/issue-775
Fix internally tagged enums by implementing ContentDeserializer::deserialize_enum
2017-02-22 18:23:18 -08:00
David Tolnay 5e7883945b Fix clippy lint in Content::unexpected 2017-02-22 18:16:51 -08:00
David Tolnay a4bd6b9a96 Fix content's SeqDeserializer on no_std 2017-02-22 18:14:56 -08:00
Michael Mokrysz 4c253748c2 Compiles and fixes internally tagged testcases. 2017-02-23 01:05:44 +00:00
Michael Mokrysz 8f6e1fb5b3 Resolved error typing. Needs to adapt to Content::Map with non-String keys.
`EnumDeserializer` is being adapted from:
  `serde_json::Value::Map<Vec<(String, Value)>>`
serde has a Map variant that allows non-String keys:
  `serde::de::Content::Map<Vec<(Content, Content)>>`

There's a lot of assumptions in `EnumDeserializer` about `String` keys and I'm not sure what the adaptation should be.
2017-02-22 23:59:47 +00:00
Michael Mokrysz 4e665a71bd Attempt to port serde_json::Value::deserialize_enum for ContentDeserializer is being derailed by what error types should be used. 2017-02-22 22:55:18 +00:00
David Tolnay 017e6d304f Release 0.9.8 2017-02-21 10:59:42 -08:00
David Tolnay 89cbb81673 Include readme and licenses in crates.io archive
Fixes #772.
2017-02-20 21:11:57 -08:00
David Tolnay c36743fa05 Merge pull request #782 from serde-rs/adjacent
Deserialization of Haskell style enums
2017-02-20 21:04:17 -08:00
David Tolnay 9a3c1243f4 Deserialization of Haskell style enums 2017-02-20 20:05:06 -08:00
David Tolnay 599a1b6607 Fragments that keep track of type of syntax
Fixes #777.
2017-02-20 17:12:35 -08:00
David Tolnay 3d6e086d3e Support custom paths in container attribute serde(default="...") 2017-02-20 17:06:00 -08:00
David Tolnay ad480d2b04 Merge pull request #780 from Thomasdezeeuw/default_container
Add support for `#[serde(default)]` on structs
2017-02-20 16:10:28 -08:00
Thomas de Zeeuw 7bee779514 Only allow #[serde(default)]` on structs 2017-02-21 00:15:00 +01:00
David Tolnay dff919a926 Rename __simple_value to __field0 to be consistent with tuples 2017-02-20 14:16:54 -08:00
David Tolnay bac593573c Drop aster dependency 2017-02-20 13:50:17 -08:00
Thomas de Zeeuw 9444db5f19 Add support for #[serde(default)] on structs
This allows structs to use the default value for each field defined in
the struct’s `std::default::Default` implementation, rather then the
default value for the field’s type.

```
struct StructDefault {
    a: i32,
    b: String,
}

impl Default for StructDefault {
    fn default() -> StructDefault {
        StructDefault{
            a: 100,
            b: "default".to_string(),
        }
    }
}
```

The code above will now return `100` for field `a` and `”default”` for
`b`, rather then `0` and `””` respectively.
2017-02-20 22:35:31 +01:00
David Tolnay 3bf8cda994 Update generics handling to use split_for_impl 2017-02-20 13:04:40 -08:00
David Tolnay f98e7f6ba0 Merge pull request #778 from SimonSapin/serialize_display_bounded_length
Avoid some string allocations.
2017-02-20 11:09:32 -08:00
Simon Sapin 772b22b427 Avoid some string allocations. 2017-02-20 18:36:38 +01:00
David Tolnay 535ab1e04b Merge pull request #771 from elliottslaughter:internally_content_tagged 2017-02-19 16:08:49 -08:00
David Tolnay a3fe03c323 Serialization of Haskell style enums 2017-02-19 16:04:39 -08:00
David Tolnay 7dad6426da Merge pull request #774 from nox/limit-hints
Clamp hints coming from untrusted input to 4096
2017-02-19 13:51:21 -08:00
David Tolnay 792a5f7502 Also clamp the collection impls 2017-02-19 13:47:05 -08:00
Anthony Ramine a4c738a9f3 Clamp hints coming from untrusted input to 4096 2017-02-19 14:29:41 +01:00
Elliott Slaughter 4538143d00 Initial work to support serialization of adjacently tagged enums. 2017-02-18 20:46:37 -08:00
David Tolnay 7f08894a32 Remove dependency on unneeded syn feature 2017-02-17 21:01:42 -08:00
David Tolnay adf7b086b5 Remove outdated comment 2017-02-17 20:38:50 -08:00
David Tolnay c590df13b9 Add compile-fail test for the with attribute 2017-02-16 18:43:04 -08:00
Oliver Schneider afa6dfbbe2 Merge pull request #765 from serde-rs/with
Pair serialize_with and deserialize_with into one attribute
2017-02-15 08:33:14 +01:00
David Tolnay f500db6e91 Pair serialize_with and deserialize_with into one attribute 2017-02-14 17:36:50 -08:00
David Tolnay 090c8a7049 Merge pull request #762 from serde-rs/rustfmt
Use rustfmt
2017-02-13 01:29:25 -08:00
David Tolnay e8651a52e7 Rustfmt 2017-02-12 22:15:59 -08:00
David Tolnay 964a2dd4d1 Release 0.9.7 2017-02-09 17:52:11 -08:00
David Tolnay 8a21bbc720 Merge pull request #755 from serde-rs/playground
Playground feature to get serde_derive picked up by integer32 playground
2017-02-09 17:50:39 -08:00
Oliver Schneider 4dba260ad7 Merge pull request #756 from shepmaster/patch-2
Add missing close backtick
2017-02-09 18:01:35 +01:00
Jake Goulding 1d3044fa28 Add missing close backtick 2017-02-09 11:53:12 -05:00
David Tolnay d1f0112bfb Playground feature to get serde_derive picked up by integer32 playground 2017-02-08 12:37:40 -08:00
David Tolnay 3f25cd9a7e No longer need ser::Error import 2017-02-08 08:17:43 -08:00
David Tolnay 45a36f1219 Fix proc macro panic message in tests 2017-02-08 08:12:32 -08:00
David Tolnay 529a1cfedb Keyword no_std for serde and serde_derive 2017-02-08 07:40:02 -08:00
David Tolnay 219abd2e00 The performance is identical 2017-02-04 19:04:29 -08:00
David Tolnay 4bd10528a0 Merge pull request #736 from nox/serialize-iter
Introduce collect_seq and collect_map
2017-02-04 11:18:36 -08:00
David Tolnay b82bba2d0a Merge pull request #747 from serde-rs/phantom_tags
Content clean-up
2017-02-04 08:53:04 -08:00
Anthony Ramine 17c175a1a6 Use specialisation to optimise collect_seq and collect_map 2017-02-04 12:22:58 +01:00
Anthony Ramine 763ab9c2a1 Use serialize_seq! to implement Serialize for [T] 2017-02-04 12:21:45 +01:00
Anthony Ramine 30b8036efa Remove ser::Iterator 2017-02-04 12:17:25 +01:00
Anthony Ramine 89bb16da6b Introduce Serializer::collect_map 2017-02-04 11:49:53 +01:00
Anthony Ramine d00a895902 Introduce Serializer::collect_seq
This function serializes the given iterator as a sequence. Its iter parameter
has type I: IntoIterator, <I as IntoIterator>::Item: Serialize, which means it
will work both for iterators passed by value, therefore consuming them, and as
the value for a #[serde(serialize_with)] attribute, where it will be called as
Serializer::collect_seq(&self.field, serializer), relying on the common practice
of implementing IntoIterator for &C where C is a data type representing some
kind of collection.
2017-02-04 11:49:34 +01:00
Oliver Schneider 393b19ee8a update codegen to the content changes 2017-02-04 10:37:50 +01:00
Oliver Schneider e68888d475 remove possible sublte ambiguity with .into_deserializer 2017-02-04 10:00:04 +01:00
David Tolnay d1306a78ec Release 0.9.6 2017-02-03 08:02:47 -08:00
David Tolnay ce230adf12 Merge pull request #739 from serde-rs/tag
Untagged and internally tagged enums
2017-02-03 07:50:26 -08:00
David Tolnay 066c9a15cf Explain status of content module 2017-02-03 07:43:04 -08:00
Oliver Schneider 6277079152 move the PhantomData usage to the Deserializer 2017-02-03 15:02:40 +01:00
Oliver Schneider d60fd84b7e Merge pull request #740 from serde-rs/enumset
Remove the EnumSet impls
2017-02-03 13:38:39 +01:00
David Tolnay 02e6c04e9f Check for sequence end 2017-02-02 22:13:32 -08:00
David Tolnay 9f04b9d6e7 Remove the EnumSet impls 2017-02-02 19:13:55 -08:00
David Tolnay d298da0b4f Require std for deserializing untagged enums 2017-02-02 19:09:38 -08:00
David Tolnay ff21d557c7 Untagged and internally tagged enums 2017-02-02 18:48:30 -08:00
Oliver Schneider faaa494579 Merge pull request #738 from serde-rs/absolute
Use absolute paths to Ok, Err, and other types and methods
2017-02-02 08:16:51 +01:00
David Tolnay 661cdf4e00 Inline the trait docs at the top level 2017-02-01 12:58:24 -08:00
David Tolnay a55d812441 Even more absolute paths 2017-02-01 12:12:39 -08:00
David Tolnay b7ca574bb3 Use absolute paths to Ok and Err 2017-02-01 09:42:12 -08:00
David Tolnay d960571439 Release 0.9.5 2017-02-01 01:01:06 -08:00
David Tolnay 1ccc58e2aa Merge pull request #735 from serde-rs/travis
Allow running travis build locally
2017-02-01 00:43:27 -08:00
David Tolnay 34b39083bc No error if clippy install fails 2017-02-01 00:38:02 -08:00
David Tolnay 48f4deac55 No more travis-cargo 2017-01-31 12:18:57 -08:00
David Tolnay 9a0f05d00d Speed up the travis clippy installation 2017-01-31 12:09:44 -08:00
David Tolnay b47e1a6dc3 Allow clippy failure in travis 2017-01-31 12:07:35 -08:00
David Tolnay 39c7797633 Allow running travis build locally 2017-01-31 12:07:31 -08:00
Oliver Schneider 368784949e move to cargo clippy instead of using the clippy plugin (#733)
* move to cargo clippy instead of using the clippy plugin

fixes #729

* non-exectable scripts must be run with `sh`

* don't build serde in the clippy travis job

* only run clippy tests if installing clippy succeeds

* why is travis so picky?

* no more serde_codegen

* serde_test_suite_deps has no features

* don't use empty loops, llvm optimizes them to undefined behaviour

* abort the clippy job when clippy lints are triggered

* use caches on travis to speed up builds

* why are we even using `travis-cargo`?

* need to reinstall clippy frequently due to nightly updates

* command line tools are hard
2017-01-31 09:09:37 -08:00
Oliver Schneider 74cf80989d Merge pull request #731 from serde-rs/pubtuple
No tuple structs with private fields in public API
2017-01-31 08:56:46 +01:00
David Tolnay f0b4735781 No tuple structs with private fields in public API 2017-01-30 18:10:50 -08:00
David Tolnay 297f373548 Release 0.9.4 2017-01-30 17:42:11 -08:00
David Tolnay 81f28da8e1 Clarify the role of Impossible serializer 2017-01-30 17:41:33 -08:00
David Tolnay d4bb687032 Merge pull request #728 from nox/impossibru
Introduce ser::Impossible (fixes #694)
2017-01-30 17:26:21 -08:00
Anthony Ramine f9bc5037f5 Introduce ser::Impossible (fixes #694) 2017-01-31 02:20:04 +01:00
David Tolnay 8624ca6f1d Release 0.9.3 2017-01-28 15:01:58 -08:00
David Tolnay a9b5cc4830 Fix invalid_length message for tuples and arrays 2017-01-28 15:00:54 -08:00
David Tolnay c31f76321c Release 0.9.2 2017-01-28 09:10:39 -08:00
David Tolnay f2402dcf52 Merge pull request #724 from serde-rs/entry
SerializeMap::serialize_entry
2017-01-28 09:08:51 -08:00
David Tolnay 361402ac4d SerializeMap::serialize_entry 2017-01-28 09:03:32 -08:00
David Tolnay c52e131a03 Replace deprecated MacroInput 2017-01-27 15:42:43 -08:00
David Tolnay c0a06bdc96 Update to syn 0.11 2017-01-27 15:25:42 -08:00
David Tolnay dd13fd3a34 Isolate the compiletest dependencies 2017-01-27 14:53:30 -08:00
David Tolnay 91f628727b Clean up the compile_tests script 2017-01-27 14:37:28 -08:00
David Tolnay 571a2e4e2d Indent the travis config to look like serde_json's 2017-01-27 14:17:07 -08:00
David Tolnay 7edcf6ec3b Simplify Error::custom example 2017-01-27 14:03:40 -08:00
David Tolnay e4f7d8513c Clean up clippy lints in codegen_internals 2017-01-25 21:22:15 -08:00
David Tolnay 09c69da909 Move test macro to where it is used 2017-01-25 20:55:55 -08:00
David Tolnay 7ee175f448 Remove duplicate btreemap macro 2017-01-25 20:54:31 -08:00
David Tolnay 70ab3cdd61 Docs are built in a different repo 2017-01-25 20:51:10 -08:00
David Tolnay 8fb554e593 Rename no_std tests to underscores 2017-01-25 20:50:23 -08:00
David Tolnay 7a2bfdc1dd Consistent underscores in root directory 2017-01-25 20:45:33 -08:00
David Tolnay 9046e9d7a1 Test suite requires beta for now 2017-01-25 20:45:08 -08:00
David Tolnay 87040b4bc4 Fix clippy lints in serde_test 2017-01-25 20:42:44 -08:00
David Tolnay 68aab2424f Rename test suite crate 2017-01-25 20:40:13 -08:00
David Tolnay 9b9b697eb1 Make compiletest an optional dependency of the test suite 2017-01-25 20:39:27 -08:00
David Tolnay db449c4bf2 Set up clippy for serde_test 2017-01-25 20:38:21 -08:00
David Tolnay 948aa47687 Clean up clippy lints 2017-01-25 20:34:01 -08:00
David Tolnay 3e1e42ef9b Combine the test suites 2017-01-25 20:29:09 -08:00
David Tolnay dbdfe4f306 Remove serde_codegen from the test suite 2017-01-25 20:19:16 -08:00
David Tolnay e0d6b9d010 Merge serde_codegen into serde_derive crate 2017-01-25 20:07:55 -08:00
David Tolnay a5b8e806f8 Remove with-syntex feature of serde_codegen 2017-01-25 20:02:24 -08:00
David Tolnay d7dadd83b6 Remove the syntex example 2017-01-25 19:54:24 -08:00
David Tolnay 7612fd8e82 Release 0.9.1 2017-01-25 14:58:22 -08:00
David Tolnay 4c77af53e5 Clean up dependency declarations 2017-01-25 14:54:32 -08:00
David Tolnay 5d9c1aeb06 Release 0.9.0 2017-01-25 12:57:45 -08:00
David Tolnay 59e48997dd Release 0.9.0-rc4 2017-01-25 10:14:43 -08:00
Oliver Schneider ffcd97834f Merge pull request #721 from serde-rs/size
Remove usize and isize from data model
2017-01-25 19:08:02 +01:00
David Tolnay e0c049dbf2 Remove usize and isize from data model 2017-01-25 09:08:06 -08:00
David Tolnay 8cb6607e82 Merge pull request #719 from serde-rs/rustdoc
Serde rustdoc
2017-01-24 20:59:26 -08:00
David Tolnay 1ffb0570b6 Do not require rustdoc tests to run on stable 2017-01-24 20:47:31 -08:00
David Tolnay 2c1dd60575 Serde rustdoc 2017-01-24 20:37:11 -08:00
David Tolnay 24f849da2d Remove unused #[macro_use]
I think this was for the quasi-quoting macros back in the day.
2017-01-24 09:28:00 -08:00
David Tolnay a5024a4238 Merge pull request #717 from serde-rs/badger
add travis badge to crates.io
2017-01-24 05:35:55 -08:00
Oliver Schneider b105423e5e add travis badge to crates.io 2017-01-24 10:30:10 +01:00
Oliver Schneider 42c1bc2907 Merge pull request #716 from serde-rs/ref
Serialize T by ref
2017-01-24 08:31:24 +01:00
David Tolnay c334c1c7b5 Release 0.9.0-rc3 2017-01-23 19:14:02 -08:00
David Tolnay 92668d7061 Serialize T by ref 2017-01-23 17:11:18 -08:00
David Tolnay b9d865d8e7 Merge pull request #715 from serde-rs/nostd
Support serde_derive on no_std
2017-01-23 16:13:25 -08:00
David Tolnay fc4e370ba9 Support serde_derive on no_std 2017-01-23 16:03:06 -08:00
Oliver Schneider a982d27536 Merge pull request #700 from serde-rs/usize
Restore visit_usize and visit_bytes for identifying variants
2017-01-23 11:27:06 +01:00
Oliver Schneider dc87826298 Merge pull request #699 from serde-rs/fields
Remove visit_usize from Duration impl
2017-01-23 11:26:18 +01:00
David Tolnay a09a8a039a All combinations of features compile without warnings 2017-01-23 01:45:54 -08:00
David Tolnay ea702755a2 Merge branch master into origin/usize
Conflicts:
    serde_codegen/src/de.rs
    testing/tests/test_de.rs
2017-01-23 01:36:49 -08:00
David Tolnay d161911c63 Merge branch master into origin/fields
Conflicts:
    serde/src/de/impls.rs
2017-01-23 01:28:01 -08:00
Oliver Schneider e27553d3df Merge pull request #710 from serde-rs/errors
Errors redesign
2017-01-23 10:25:48 +01:00
David Tolnay 48eaf988bc Add free-form option for Unexpected 2017-01-22 05:02:24 -08:00
David Tolnay 73a364d4fd Capture byte value for error message 2017-01-22 04:57:12 -08:00
David Tolnay 6dfdcb6ba1 Merge pull request #713 from serde-rs/zero
Suppress warning about using num::Zero
2017-01-21 19:20:57 -08:00
David Tolnay 089c7eb1d7 Suppress warning about using num::Zero 2017-01-21 19:14:56 -08:00
David Tolnay 1e05fc2145 Release 0.9.0-rc2 2017-01-21 16:30:13 -08:00
David Tolnay 977612d8dd Merge branch origin/missing into origin/errors 2017-01-21 16:28:24 -08:00
David Tolnay 5855078703 Fix backward invalid_length messages in value deserializer 2017-01-21 14:38:33 -08:00
David Tolnay 3c88a93fb2 Fix the filtered error messages 2017-01-21 12:34:04 -08:00
David Tolnay 530c29466e Merge pull request #711 from serde-rs/names
Filter the slice of expected field and variant names
2017-01-21 12:25:43 -08:00
David Tolnay ea99e8b686 Filter the slice of expected field and variant names 2017-01-21 12:18:55 -08:00
David Tolnay 2a148112d4 Fix Box<str> use on no_std 2017-01-21 10:17:48 -08:00
David Tolnay a4126e4c5a Errors 2017-01-21 09:13:01 -08:00
David Tolnay d1325862f7 Merge tag v0.8.23 into master
Conflicts:
    serde/Cargo.toml
    serde_codegen/Cargo.toml
    serde_derive/Cargo.toml
    serde_test/Cargo.toml
    testing/Cargo.toml
2017-01-20 15:29:32 -08:00
David Tolnay 1f65ce75ec Release 0.8.23 2017-01-20 15:25:57 -08:00
Jake Goulding 9536e52aa6 Add categories to Cargo.toml 2017-01-20 15:09:11 -08:00
Oliver Schneider be0c755731 Merge pull request #705 from serde-rs/inlineseed
Inline <PhantomData<T> as DeserializeSeed>::deserialize
2017-01-20 14:34:24 +01:00
David Tolnay 42bc63bed8 Standardize behavior of missing fields 2017-01-20 00:44:43 -08:00
David Tolnay e41b940a3d Inline <PhantomData<T> as DeserializeSeed>::deserialize 2017-01-19 16:17:27 -08:00
David Tolnay 88149fc0c3 Fix key and value seed variable names
Rename fail.
2017-01-19 13:44:18 -08:00
David Tolnay 5ecfb3b388 Update serde_test to use seeds 2017-01-19 01:24:33 -08:00
David Tolnay 13a9f929de Stateful deserialization 2017-01-19 01:17:59 -08:00
David Tolnay e40fbe0767 Restore visit_bytes for Duration impl 2017-01-18 21:13:51 -08:00
David Tolnay 0a10116bf5 Restore visit_bytes for identifying variants and fields 2017-01-18 21:11:51 -08:00
David Tolnay b1fbbfd3ce Restore visit_usize for identifying variants 2017-01-17 23:52:06 -08:00
David Tolnay 984ebcead0 Remove visit_usize and visit_bytes for Duration impl 2017-01-17 23:32:28 -08:00
David Tolnay aa88f01cdc Merge pull request #697 from serde-rs/vanity
cleanup some deprecation warnings
2017-01-17 09:26:44 -08:00
David Tolnay 13794c1b48 Stop testing on rust 1.12.0 2017-01-17 09:19:39 -08:00
Oliver Schneider b5e64abba1 cleanup some deprecation warnings 2017-01-17 14:29:33 +01:00
David Tolnay 503ce310f5 Merge pull request #692 from serde-rs/byte_buf
add missing `Vec<u8>` deserialization hint to `Deserializer`
2017-01-16 08:10:25 -08:00
Oliver Schneider b26f291d93 add missing Vec<u8> deserialization hint to Deserializer 2017-01-16 16:55:13 +01:00
David Tolnay bc6bc9e3f0 Remove LICENSE file in favor of LICENSE-MIT and LICENSE-APACHE
This repo no longer contains bench_log referenced in this file.
2017-01-15 10:16:57 -08:00
David Tolnay 3a52364f3e Release 0.9.0-rc1 2017-01-15 09:26:44 -08:00
David Tolnay 4d1627fc96 Merge pull request #687 from serde-rs/ser
Enforce correct use of Serialize trait
2017-01-15 09:22:30 -08:00
David Tolnay 7c04bf36d9 Merge pull request #686 from serde-rs/de
Enforce correct use of Deserialize trait
2017-01-15 07:30:14 -08:00
David Tolnay 4b06030666 Unabbreviated method naming 2017-01-14 21:39:37 -08:00
David Tolnay a5a04306f2 Update tests for Serializer changes 2017-01-14 16:07:43 -08:00
David Tolnay f9885c4826 Update serde_codegen for Serializer changes 2017-01-14 16:07:34 -08:00
David Tolnay 04f25eb122 Update serde_test for Serializer changes 2017-01-14 16:07:17 -08:00
David Tolnay 2fea5f3e1c Enforce correct use of Serialize trait 2017-01-14 15:21:31 -08:00
David Tolnay 905b2c3cf3 Expose VariantVisitor for the StrDeserializer 2017-01-14 14:17:46 -08:00
David Tolnay d5b428a087 Fix imports for stable compiler 2017-01-14 14:16:01 -08:00
David Tolnay b3b8056d93 Update tests for Deserializer changes 2017-01-14 13:42:49 -08:00
David Tolnay 137cf9bab8 Update serde_codegen for Deserializer changes 2017-01-14 13:42:48 -08:00
David Tolnay 7372f152bd Update serde_test for Deserializer changes 2017-01-14 13:42:45 -08:00
David Tolnay a43da15b74 Merge pull request #685 from mineo/patch-1
Typo: aggrergate -> aggregate
2017-01-14 13:36:49 -08:00
Wieland Hoffmann 212cbbd8bf Typo: aggrergate -> aggregate 2017-01-14 22:33:31 +01:00
David Tolnay 738aa31733 Enforce correct use of Deserialize trait 2017-01-14 12:16:08 -08:00
Oliver Schneider 787ecc6a82 Merge pull request #684 from serde-rs/end
Remove SeqVisitor::end() and MapVisitor::end()
2017-01-14 08:01:53 +01:00
David Tolnay 9fc8a86bcc Exclude serde-syntex-example until serde_json has been updated 2017-01-13 13:34:41 -08:00
David Tolnay 800442a75e Handle visitor that does not need to be mutable 2017-01-13 13:34:39 -08:00
David Tolnay 88debb3fb8 Remove SeqVisitor::end() and MapVisitor::end() 2017-01-13 13:34:38 -08:00
David Tolnay 88a4ed9cd7 Include missing_field in impl MapVisitor for &mut MapVisitor 2017-01-13 13:33:37 -08:00
David Tolnay bdba6fc5b0 Remove the proc_macro feature gate in serde-syntex-example 2017-01-13 10:27:51 -08:00
Oliver Schneider dec116311e Merge pull request #682 from serde-rs/unknown
Treat skipped fields as unknown
2017-01-13 10:46:18 +01:00
David Tolnay 8c49e6d6a5 Resolve conflict between rename changes and skip changes 2017-01-13 01:27:07 -08:00
David Tolnay 7cc24a43fb Merge branch master into unknown
Conflicts:
    serde_codegen/src/de.rs
2017-01-13 01:23:00 -08:00
David Tolnay c008c6d3a8 Merge pull request #681 from serde-rs/deserialize_struct_bug
fix various serde(rename) bugs
2017-01-13 01:21:46 -08:00
David Tolnay c9f5d08ed1 Add test for all variants skipped 2017-01-13 01:14:03 -08:00
David Tolnay fff6c9cb66 Add tests for all fields skipped 2017-01-13 01:12:31 -08:00
David Tolnay cb5e7c6264 Fix case of skipped variant followed by other variants 2017-01-12 23:35:39 -08:00
David Tolnay 4ef1128546 More explicit about argument to deserialize_field_visitor 2017-01-12 23:30:57 -08:00
David Tolnay 227bea1d0b Treat skipped fields as unknown 2017-01-12 23:17:45 -08:00
David Tolnay 766ede965e Eliminate collects in codegen for deserializing map 2017-01-12 21:52:56 -08:00
David Tolnay eb5a49e380 Use helper function to build __field{} 2017-01-12 21:49:20 -08:00
David Tolnay 2df529cac5 Simplify codegen logic in deserializing seq 2017-01-12 21:41:27 -08:00
David Tolnay 4b66463011 Eliminate collect in deserializing seq 2017-01-12 21:29:50 -08:00
David Tolnay b907cfef85 Eliminate collect in visitor generics 2017-01-12 21:28:09 -08:00
David Tolnay 506c8cc087 Simplify the trait paths used in bounds 2017-01-12 21:24:51 -08:00
David Tolnay 3951ef91c0 Don't need aster to construct syn::Ident 2017-01-12 21:15:13 -08:00
David Tolnay b0d20afdfb Merge pull request #680 from serde-rs/oli-obk-patch-1
make `ser::iterator` more general by taking `IntoIterator`
2017-01-12 16:45:39 -08:00
Oliver Schneider 5e6ee523d2 remove duplicate into_iter 2017-01-12 21:52:38 +01:00
Oliver Schneider a07b6bd9e7 also use the renamed variant names during deserialization 2017-01-12 20:21:59 +01:00
Oliver Schneider 8dd06eed2f type inference failure 2017-01-12 20:19:00 +01:00
Oliver Schneider 5b668ed87a attempt to test the field names, but deem it too complex and opt to at least improve the code 2017-01-12 20:17:55 +01:00
Oliver Schneider abe305dbfe fix deserialize_struct passing the original field names instead of the renamed ones 2017-01-12 20:17:02 +01:00
Oliver Schneider 2d1a60c056 Update the Serialize impl, too 2017-01-12 20:06:44 +01:00
Oliver Schneider 5edfdba940 use IntoIterator everywhere 2017-01-12 20:05:26 +01:00
Oliver Schneider 756bff534f make ser::iterator more general by taking IntoIterator 2017-01-12 19:24:35 +01:00
David Tolnay 110d36fa14 Merge pull request #679 from oli-obk/iterators
add wrapper to serde that allows serializing iterators as sequences
2017-01-12 10:19:09 -08:00
Oliver Schneider 8c576fe9fb rename IteratorSerializer to Iterator 2017-01-12 17:29:04 +01:00
Oliver Schneider b860d3cb1f fix tests on stable 2017-01-12 16:06:26 +01:00
Oliver Schneider dced4416a7 add wrapper to serde that allows serializing iterators as sequences 2017-01-12 15:31:40 +01:00
David Tolnay ca47eb929c Merge pull request #678 from serde-rs/empty
Handle various degenerate cases
2017-01-11 11:45:24 -08:00
David Tolnay b01c23b5ee Also provide a smarter alternative for the other impossible case 2017-01-11 11:34:47 -08:00
David Tolnay 3aaf29c846 Remove ref in top-level let pattern
Discouraged by Clippy.
2017-01-11 11:12:53 -08:00
David Tolnay d2eea87001 Handle various degenerate cases 2017-01-11 11:02:24 -08:00
David Tolnay 8242c64152 Merge branch v0.8 into master 2017-01-10 17:16:31 -08:00
Oliver Schneider 405b534254 Merge pull request #674 from serde-rs/nonascii
Add test for non ascii idents
2017-01-10 11:16:19 +01:00
David Tolnay d34be74dfd Add test for non ascii idents 2017-01-10 01:20:01 -08:00
David Tolnay c475df8320 Encourage GitHub issues 2017-01-09 14:44:36 -08:00
Oliver Schneider 2b8a620807 Merge pull request #671 from serde-rs/fields
Stop generating visit_usize and visit_bytes for FieldVisitor
2017-01-09 13:09:18 +01:00
David Tolnay 1cd6aee562 Merge pull request #670 from serde-rs/error
Stop exporting serde::de::Error as serde::Error
2017-01-09 00:45:04 -08:00
David Tolnay 90d4d7b37b Restore the old FieldVisitor tests as error tests 2017-01-09 00:43:13 -08:00
David Tolnay 1f8b803607 Repetition for field visitor arms 2017-01-09 00:37:37 -08:00
David Tolnay 516cc8b04e Stop generating visit_usize and visit_bytes for FieldVisitor 2017-01-08 01:01:56 -08:00
David Tolnay 0676477cd7 Stop exporting serde::de::Error as serde::Error 2017-01-08 00:50:07 -08:00
David Tolnay 4193122472 Use the more concise paths in generated code 2017-01-08 00:47:44 -08:00
David Tolnay eb6fb1d40e Merge pull request #523 from serde-rs/enum
Enum deserialization API
2017-01-08 00:45:50 -08:00
David Tolnay bf873a7b3f Merge branch origin/master into origin/enum
Conflicts:
    serde/src/de/mod.rs
    serde_codegen/src/de.rs
    testing/tests/test_bytes.rs
2017-01-08 00:31:07 -08:00
David Tolnay fbd4a17467 Merge pull request #664 from serde-rs/visitor-value
Remove the Deserialize trait bound on Visitor::Value
2017-01-08 00:24:53 -08:00
David Tolnay ad34c14c8c Prepare for 0.9 breaking changes 2017-01-08 00:18:53 -08:00
David Tolnay 7a0e8f73b4 Remove the Deserialize trait bound on Visitor::Value 2017-01-03 01:50:10 -08:00
David Tolnay 85f1bf0259 Enum deserialization API 2016-08-23 22:17:28 -04:00
174 changed files with 25334 additions and 11784 deletions
+3 -2
View File
@@ -1,3 +1,4 @@
Cargo.lock
target
target/
**/*.rs.bk
*.sw[po]
Cargo.lock
+14 -24
View File
@@ -1,27 +1,17 @@
sudo: false
language: rust
cache: cargo
# run builds for all the trains (and more)
rust:
- 1.12.0
- 1.13.0
- stable
- beta
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH
script:
- (cd serde && travis-cargo build)
- (cd serde && travis-cargo --skip nightly test)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde && travis-cargo build -- --no-default-features)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_derive && travis-cargo --only nightly test)
- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
- (cd serde && travis-cargo --only stable doc)
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
- 1.13.0
- stable
- beta
- nightly
matrix:
include:
- rust: nightly
env: CLIPPY=true
script: ./travis.sh
+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
+8
View File
@@ -0,0 +1,8 @@
[workspace]
members = [
"serde",
"serde_derive",
"serde_derive_internals",
"serde_test",
"test_suite",
]
-33
View File
@@ -1,33 +0,0 @@
See LICENSE-APACHE and LICENSE-MIT.
----
bench_log is derived from https://github.com/cloudflare/goser, which has the
following license:
Copyright (c) 2013, CloudFlare, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+35 -3
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)]
@@ -49,8 +80,9 @@ fn main() {
Serde developers live in the #serde channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
good resource with generally faster response time but less specific knowledge
about Serde. If IRC is not your thing, we are happy to respond to [GitHub
issues](https://github.com/serde-rs/serde/issues/new) as well.
about Serde. If IRC is not your thing or you don't get a good response, we are
happy to respond to [GitHub issues](https://github.com/serde-rs/serde/issues/new)
as well.
## License
+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
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- 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
@@ -1,2 +0,0 @@
target
Cargo.lock
-18
View File
@@ -1,18 +0,0 @@
[package]
name = "serde-syntex-example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
publish = false
[features]
default = ["serde_codegen"]
unstable = ["serde_derive"]
[build-dependencies]
serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" }
[dependencies]
serde = "^0.8"
serde_derive = { version = "^0.8", optional = true, path = "../../serde_derive" }
serde_json = "^0.8"
-20
View File
@@ -1,20 +0,0 @@
This example demonstrates how to use Serde with Syntex. On stable or nightly
with Syntex, it can be built with:
```
% rustup run stable cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
% rustup run nightly cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
On nightly, it can use a plugin with:
```
% rustup run nightly cargo run --features unstable --no-default-features
```
-25
View File
@@ -1,25 +0,0 @@
#[cfg(not(feature = "serde_derive"))]
mod inner {
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
}
#[cfg(feature = "serde_derive")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
-14
View File
@@ -1,14 +0,0 @@
#![cfg_attr(feature = "serde_derive", feature(proc_macro))]
#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_derive")]
include!("main.rs.in");
#[cfg(not(feature = "serde_derive"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
@@ -1,16 +0,0 @@
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
+5
View File
@@ -0,0 +1,5 @@
fn_args_layout = "Block"
array_layout = "Block"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
+56 -12
View File
@@ -1,24 +1,68 @@
[package]
name = "serde"
version = "0.8.22"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
version = "1.0.22" # 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"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
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"]
std = []
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
unstable-testing = ["clippy", "unstable", "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"]
[dependencies]
clippy = { version = "^0.*", optional = true }
# 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"]
# 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"]
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
-252
View File
@@ -1,252 +0,0 @@
//! Helper module to enable serializing bytes more efficiently
use core::{ops, fmt, char, iter, slice};
use core::fmt::Write;
use ser;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::{ByteBuf, ByteBufVisitor};
#[cfg(feature = "collections")]
use collections::Vec;
///////////////////////////////////////////////////////////////////////////////
/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array.
#[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: &mut S) -> Result<(), S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
mod bytebuf {
use core::ops;
use core::fmt;
use core::fmt::Write;
use ser;
use de;
#[cfg(feature = "collections")]
use collections::{String, Vec};
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
#[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: &mut S) -> Result<(), 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;
#[inline]
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
try!(visitor.end());
Ok(ByteBuf::from(values))
}
#[inline]
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::from(v))
}
#[inline]
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::from(v))
}
fn visit_str<E>(&mut self, v: &str) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::from(v))
}
fn visit_string<E>(&mut self, v: String) -> Result<ByteBuf, E>
where E: de::Error,
{
Ok(ByteBuf::from(v))
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.deserialize_bytes(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)
}
+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 as i64 <= $n as i64 && $n as i64 <= $dst::MAX 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 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 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, Visitor, SeqAccess, MapAccess, Error};
/// 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)
}
}
+1316 -780
View File
File diff suppressed because it is too large Load Diff
+1799 -616
View File
File diff suppressed because it is too large Load Diff
+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()
}
}
+960 -744
View File
File diff suppressed because it is too large Load Diff
-44
View File
@@ -1,44 +0,0 @@
//! A stand-in for `std::error`
use core::any::TypeId;
use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(feature = "unstable")]
pub trait Error: Debug + Display + ::core::marker::Reflect {
/// 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 }
/// Get the `TypeId` of `self`
#[doc(hidden)]
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<Self>()
}
}
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(not(feature = "unstable"))]
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 }
/// Stubbed! Returns type_id of `()`
#[doc(hidden)]
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<()>()
}
}
+41
View File
@@ -0,0 +1,41 @@
// 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.
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, Ok, Err};
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}")
}
}
-61
View File
@@ -1,61 +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)),
}
}
}
+273 -41
View File
@@ -1,58 +1,290 @@
//! Serde Serialization Framework
//!
//! Serde is a powerful framework that enables serialization libraries to generically serialize
//! Rust data structures without the overhead of runtime type information. In many situations, the
//! handshake protocol between serializers and serializees can be completely optimized away,
//! leaving serde to perform roughly the same speed as a hand written serializer for a specific
//! type.
//!
//! For a detailed tutorial on the different ways to use serde please check out the
//! [github repository](https://github.com/serde-rs/serde)
// 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.serde.rs")]
//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! 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
//! usage examples.
//!
//! [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 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 the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [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
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.22")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(reflect_marker, unicode, nonzero, plugin, step_trait, 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, enumset))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist))]
#![cfg_attr(any(not(feature = "std"), feature = "unstable"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(
cast_lossless,
const_static_lifetime,
doc_markdown,
linkedlist,
needless_pass_by_value,
type_complexity,
unreadable_literal,
zero_prefixed_literal,
))]
// 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
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
single_match_else,
stutter,
use_self,
// not practical
missing_docs_in_private_items,
// alternative is not stable
empty_enum,
use_debug,
))]
#![deny(missing_docs)]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
#[cfg(all(feature = "unstable", feature = "collections"))]
extern crate collections;
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "unstable", feature = "alloc"))]
#[cfg(feature = "alloc")]
extern crate alloc;
#[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};
#[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::{i8, i16, i32, i64, isize};
pub use self::core::{u8, u16, u32, u64, usize};
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::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, 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::{CString, CStr, OsString, OsStr};
#[cfg(feature = "std")]
pub use std::hash::{Hash, BuildHasher};
#[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 = "unstable")]
extern crate core;
#[cfg(feature = "unstable")]
pub use self::core::nonzero;
pub use core::nonzero::{NonZero, Zeroable};
}
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
#[cfg(not(feature = "std"))]
macro_rules! format {
($s:expr, $($rest:tt)*) => ($s)
}
////////////////////////////////////////////////////////////////////////////////
#[macro_use]
mod macros;
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
pub mod iter;
pub mod ser;
#[cfg(not(feature = "std"))]
pub mod error;
mod utils;
pub mod de;
#[doc(inline)]
pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer};
// 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::*;
+232 -169
View File
@@ -1,179 +1,242 @@
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
// 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.
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(usize) => {
forward_to_deserialize_method!{deserialize_usize()}
};
(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()}
};
(isize) => {
forward_to_deserialize_method!{deserialize_isize()}
};
(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()}
};
(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)}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
(enum) => {
forward_to_deserialize_enum!();
};
}
/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`.
/// Every given method ignores all arguments and forwards to `deserialize`.
/// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a
/// better approach is tracked in [serde-rs/serde#521][1].
// Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize
// documentation.
//
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
///
/// ```rust,ignore
/// impl Deserializer for MyDeserializer {
/// fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// /* ... */
/// }
/// 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.
///
/// forward_to_deserialize! {
/// bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
/// unit option seq seq_fixed_size bytes map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any
/// }
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// # impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error;
/// #
/// # 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<'de>
/// {
/// self.deserialize_any(visitor)
/// }
/// #
/// # forward_to_deserialize_any! {
/// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// # byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any
/// # }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// [1]: https://github.com/serde-rs/serde/issues/521
/// 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;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer;
/// #
/// impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error;
/// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// {
/// /* ... */
/// # let _ = visitor;
/// # unimplemented!()
/// }
///
/// 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>})*
};
}
#[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>,
{
$(
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
+513 -556
View File
File diff suppressed because it is too large Load Diff
+227
View File
@@ -0,0 +1,227 @@
// 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 lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
/// 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`].
///
/// ```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;
///
/// type SerializeSeq = Impossible<(), Error>;
/// /* other associated types */
///
/// /// This data format does not support serializing sequences.
/// fn serialize_seq(self,
/// len: Option<usize>)
/// -> 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() {}
/// ```
///
/// [`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,
ok: PhantomData<Ok>,
error: PhantomData<Error>,
}
enum Void {}
impl<Ok, Error> SerializeSeq for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeTuple for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeTupleStruct for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeTupleVariant for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeMap for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
match self.void {}
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {}
}
fn end(self) -> Result<Ok, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeStruct for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
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, Error> {
match self.void {}
}
}
impl<Ok, Error> SerializeStructVariant for Impossible<Ok, Error>
where
Error: ser::Error,
{
type Ok = Ok;
type Error = Error;
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, Error> {
match self.void {}
}
}
+1805 -337
View File
File diff suppressed because it is too large Load Diff
-72
View File
@@ -1,72 +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)
}
-29
View File
@@ -1,29 +0,0 @@
[package]
name = "serde_codegen"
version = "0.8.22"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
unstable = []
unstable-testing = ["clippy"]
with-syntex = [
"syntex",
"syntex_syntax",
]
with-syn = []
[dependencies]
clippy = { version = "^0.*", optional = true }
quote = "0.3.8"
serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.10", features = ["aster", "visit"] }
syntex = { version = "^0.54.0", optional = true }
syntex_syntax = { version = "^0.54.0", optional = true }
-121
View File
@@ -1,121 +0,0 @@
use std::collections::HashSet;
use syn::{self, aster, visit};
use internals::ast::Item;
use internals::attr;
// 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.iter().map(|ty_param| {
syn::TyParam {
default: None,
.. ty_param.clone()
}}).collect(),
.. generics.clone()
}
}
pub fn with_where_predicates(
generics: &syn::Generics,
predicates: &[syn::WherePredicate],
) -> syn::Generics {
aster::from_generics(generics.clone())
.with_predicates(predicates.to_vec())
.build()
}
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]>,
{
aster::from_generics(generics.clone())
.with_predicates(
item.body.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec()))
.build()
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[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,
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
}
let all_ty_params: HashSet<_> = generics.ty_params.iter()
.map(|ty_param| ty_param.ident.clone())
.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);
}
aster::from_generics(generics.clone())
.with_predicates(
generics.ty_params.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| aster::where_predicate()
// the type parameter that is being bounded e.g. T
.bound().build(aster::ty().id(id))
// the bound e.g. Serialize
.bound().trait_(bound.clone()).build()
.build()))
.build()
}
File diff suppressed because it is too large Load Diff
-172
View File
@@ -1,172 +0,0 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
extern crate syn;
#[macro_use]
extern crate quote;
#[cfg(feature = "with-syntex")]
use std::path::Path;
mod bound;
mod de;
mod ser;
#[cfg(feature = "with-syntex")]
fn syntex_registry() -> syntex::Registry {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
return None;
}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
let mut reg = syntex::Registry::new();
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", shim::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg
}
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)
}
macro_rules! shim {
($name:ident $pkg:ident :: $func:ident) => {
pub fn $func(
cx: &mut ::syntax::ext::base::ExtCtxt,
span: ::syntax::codemap::Span,
meta_item: &::syntax::ast::MetaItem,
annotatable: &::syntax::ext::base::Annotatable,
push: &mut FnMut(::syntax::ext::base::Annotatable)
) {
let item = match *annotatable {
::syntax::ext::base::Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
concat!("`#[derive(",
stringify!($name),
")]` may only be applied to structs and enums"));
return;
}
};
use syntax::{attr, ast, visit};
struct MarkSerdeAttributesUsed;
impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
attr::mark_used(attr);
}
}
}
}
visit::walk_item(&mut MarkSerdeAttributesUsed, item);
use syntax::print::pprust;
let s = pprust::item_to_string(item);
use {syn, $pkg};
let syn_item = syn::parse_macro_input(&s).unwrap();
let expanded = match $pkg::$func(&syn_item) {
Ok(expanded) => expanded.to_string(),
Err(msg) => {
cx.span_err(span, &msg);
return;
}
};
use syntax::parse;
let name = stringify!($name).to_string();
let sess = cx.parse_sess;
let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
}
};
}
#[cfg(feature = "with-syntex")]
mod shim {
shim!(Serialize ser::expand_derive_serialize);
shim!(Deserialize de::expand_derive_deserialize);
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
ser::expand_derive_serialize(&syn_item)
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
de::expand_derive_deserialize(&syn_item)
}
-570
View File
@@ -1,570 +0,0 @@
use syn::{self, aster};
use quote::Tokens;
use bound;
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{self, attr};
pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item);
try!(ctxt.check());
let impl_generics = build_impl_generics(&item);
let ty = aster::ty().path()
.segment(item.ident.clone()).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(&item,
&impl_generics,
ty.clone());
let where_clause = &impl_generics.where_clause;
let dummy_const = aster::id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident));
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#[automatically_derived]
impl #impl_generics _serde::ser::Serialize for #ty #where_clause {
fn serialize<__S>(&self, _serializer: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: _serde::ser::Serializer
{
#body
}
}
};
})
}
// All the generics in the input, plus a bound `T: Serialize` for each generic
// field type that will be serialized by us.
fn build_impl_generics(item: &Item) -> syn::Generics {
let generics = bound::without_defaults(item.generics);
let generics = bound::with_where_predicates_from_fields(
item, &generics,
|attrs| attrs.ser_bound());
match item.attrs.ser_bound() {
Some(predicates) => {
bound::with_where_predicates(&generics, predicates)
}
None => {
bound::with_bound(item, &generics,
needs_serialize_bound,
&aster::path().ids(&["_serde", "ser", "Serialize"]).build())
}
}
}
// Fields with a `skip_serializing` or `serialize_with` attribute are not
// serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(attrs: &attr::Field) -> bool {
!attrs.skip_serializing()
&& attrs.serialize_with().is_none()
&& attrs.ser_bound().is_none()
}
fn serialize_body(
item: &Item,
impl_generics: &syn::Generics,
ty: syn::Ty,
) -> Tokens {
match item.body {
Body::Enum(ref variants) => {
serialize_item_enum(
&item.ident,
impl_generics,
ty,
variants,
&item.attrs)
}
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(
impl_generics,
ty,
fields,
&item.attrs)
}
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
serialize_tuple_struct(
impl_generics,
ty,
fields,
&item.attrs)
}
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(
impl_generics,
ty,
&fields[0],
&item.attrs)
}
Body::Struct(Style::Unit, _) => {
serialize_unit_struct(
&item.attrs)
}
}
}
fn serialize_unit_struct(item_attrs: &attr::Item) -> Tokens {
let type_name = item_attrs.name().serialize_name();
quote! {
_serializer.serialize_unit_struct(#type_name)
}
}
fn serialize_newtype_struct(
impl_generics: &syn::Generics,
item_ty: syn::Ty,
field: &Field,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let mut field_expr = quote!(&self.0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&item_ty, impl_generics, field.ty, path, field_expr);
}
quote! {
_serializer.serialize_newtype_struct(#type_name, #field_expr)
}
}
fn serialize_tuple_struct(
impl_generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let serialize_stmts = serialize_tuple_struct_visitor(
ty.clone(),
fields,
impl_generics,
false,
aster::id("serialize_tuple_struct_elt"),
);
let type_name = item_attrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len));
#(#serialize_stmts)*
_serializer.serialize_tuple_struct_end(__serde_state)
}
}
fn serialize_struct(
impl_generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let serialize_fields = serialize_struct_visitor(
ty.clone(),
fields,
impl_generics,
false,
aster::id("serialize_struct_elt"),
);
let type_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = quote!(&self.#ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len));
#(#serialize_fields)*
_serializer.serialize_struct_end(__serde_state)
}
}
fn serialize_item_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> Tokens {
let arms: Vec<_> =
variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
item_attrs,
)
})
.collect();
quote! {
match *self {
#(#arms)*
}
}
}
fn serialize_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_ident = variant.ident.clone();
let variant_name = variant.attrs.name().serialize_name();
if variant.attrs.skip_serializing() {
let skipped_msg = format!("The enum variant {}::{} cannot be serialized",
type_ident, variant_ident);
let skipped_err = quote! {
Err(_serde::ser::Error::invalid_value(#skipped_msg))
};
let fields_pat = match variant.style {
Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!( (..) ),
Style::Struct => quote!( {..} ),
};
quote! {
#type_ident::#variant_ident #fields_pat => #skipped_err,
}
} else { // variant wasn't skipped
match variant.style {
Style::Unit => {
quote! {
#type_ident::#variant_ident =>
_serde::ser::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
}
},
Style::Newtype => {
let block = serialize_newtype_variant(
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote! {
#type_ident::#variant_ident(ref __simple_value) => #block,
}
},
Style::Tuple => {
let field_names = (0 .. variant.fields.len())
.map(|i| aster::id(format!("__field{}", i)));
let block = serialize_tuple_variant(
type_name,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
);
quote! {
#type_ident::#variant_ident(#(ref #field_names),*) => { #block }
}
}
Style::Struct => {
let fields = variant.fields.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
let block = serialize_struct_variant(
variant_index,
variant_name,
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
#type_ident::#variant_ident { #(ref #fields),* } => { #block }
}
}
}
}
}
fn serialize_newtype_variant(
type_name: String,
variant_index: usize,
variant_name: String,
item_ty: syn::Ty,
generics: &syn::Generics,
field: &Field,
) -> Tokens {
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&item_ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::ser::Serializer::serialize_newtype_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
)
}
}
fn serialize_tuple_variant(
type_name: String,
variant_index: usize,
variant_name: String,
generics: &syn::Generics,
structure_ty: syn::Ty,
fields: &[Field],
) -> Tokens {
let serialize_stmts = serialize_tuple_struct_visitor(
structure_ty,
fields,
generics,
true,
aster::id("serialize_tuple_variant_elt"),
);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_variant(
#type_name,
#variant_index,
#variant_name,
#len));
#(#serialize_stmts)*
_serializer.serialize_tuple_variant_end(__serde_state)
}
}
fn serialize_struct_variant(
variant_index: usize,
variant_name: String,
generics: &syn::Generics,
ty: syn::Ty,
fields: &[Field],
item_attrs: &attr::Item,
) -> Tokens {
let serialize_fields = serialize_struct_visitor(
ty.clone(),
fields,
generics,
true,
aster::id("serialize_struct_variant_elt"),
);
let item_name = item_attrs.name().serialize_name();
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct_variant(
#item_name,
#variant_index,
#variant_name,
#len,
));
#(#serialize_fields)*
_serializer.serialize_struct_variant_end(__serde_state)
}
}
fn serialize_tuple_struct_visitor(
structure_ty: syn::Ty,
fields: &[Field],
generics: &syn::Generics,
is_enum: bool,
func: syn::Ident,
) -> Vec<Tokens> {
fields.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = aster::id(format!("__field{}", i));
quote!(#id)
} else {
let i = aster::id(i);
quote!(&self.#i)
};
let skip = field.attrs.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&structure_ty, generics, field.ty, path, field_expr);
}
let ser = quote! {
try!(_serializer.#func(&mut __serde_state, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn serialize_struct_visitor(
structure_ty: syn::Ty,
fields: &[Field],
generics: &syn::Generics,
is_enum: bool,
func: syn::Ident,
) -> Vec<Tokens> {
fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote!(#ident)
} else {
quote!(&self.#ident)
};
let key_expr = field.attrs.name().serialize_name();
let skip = field.attrs.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&structure_ty, generics, field.ty, path, field_expr)
}
let ser = quote! {
try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
fn wrap_serialize_with(
item_ty: &syn::Ty,
generics: &syn::Generics,
field_ty: &syn::Ty,
path: &syn::Path,
value: Tokens,
) -> Tokens {
let where_clause = &generics.where_clause;
let wrapper_generics = aster::from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let wrapper_ty = aster::path()
.segment("__SerializeWith")
.with_generics(wrapper_generics.clone())
.build()
.build();
quote!({
struct __SerializeWith #wrapper_generics #where_clause {
value: &'__a #field_ty,
phantom: ::std::marker::PhantomData<#item_ty>,
}
impl #wrapper_generics _serde::ser::Serialize for #wrapper_ty #where_clause {
fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: _serde::ser::Serializer
{
#path(self.value, __s)
}
}
__SerializeWith {
value: #value,
phantom: ::std::marker::PhantomData::<#item_ty>,
}
})
}
// Serialization of an empty struct results in code like:
//
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
// serializer.serialize_struct_end(__serde_state)
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut {
Some(quote!(mut))
} else {
None
}
}
-18
View File
@@ -1,18 +0,0 @@
[package]
name = "serde_codegen_internals"
version = "0.11.3"
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"]
include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable-testing = ["clippy"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syn = "0.10"
-116
View File
@@ -1,116 +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 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)
}
};
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()
}
-543
View File
@@ -1,543 +0,0 @@
use Ctxt;
use syn;
use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem};
// 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.
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,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
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 ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
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(deny_unknown_fields)]`
MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// 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 container attribute `{}`",
meta_item.name()));
}
Literal(_) => {
cx.error(format!("unexpected literal in serde container attribute"));
}
}
}
}
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(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
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[..])
}
}
/// Represents variant attribute information
#[derive(Debug)]
pub struct Variant {
name: Name,
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");
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(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(format!("unexpected literal in serde variant attribute"));
}
}
}
}
Variant {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()),
},
skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
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,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<syn::Path>,
default: FieldDefault,
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 FieldDefault {
/// 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(FieldDefault::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(FieldDefault::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(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(format!("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(FieldDefault::Default);
}
Field {
name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
},
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
default: default.get().unwrap_or(FieldDefault::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 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) -> &FieldDefault {
&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))
}
-10
View File
@@ -1,10 +0,0 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
extern crate syn;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
+13 -13
View File
@@ -1,27 +1,27 @@
[package]
name = "serde_derive"
version = "0.8.22"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
version = "1.0.22" # 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"]
include = ["Cargo.toml", "src/**/*.rs"]
keywords = ["serde", "serialization", "no_std"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
[lib]
name = "serde_derive"
proc-macro = true
[dependencies.serde_codegen]
version = "=0.8.22"
path = "../serde_codegen"
default-features = false
features = ["with-syn"]
[dependencies]
quote = "0.3.8"
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] }
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
serde = { version = "0.8.22", path = "../serde" }
serde_test = { version = "0.8.22", path = "../serde_test" }
serde = { version = "1.0", path = "../serde" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+274
View File
@@ -0,0 +1,274 @@
// 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 internals::ast::{Body, Container};
use internals::attr;
macro_rules! path {
($($path:tt)+) => {
syn::parse_path(quote!($($path)+).as_str()).unwrap()
};
}
// 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
.iter()
.map(
|ty_param| {
syn::TyParam {
default: None,
..ty_param.clone()
}
},
)
.collect(),
..generics.clone()
}
}
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);
generics
}
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 = cont.body
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
generics.where_clause.predicates.extend(predicates);
generics
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
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
// the example). Initialized up front.
all_ty_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<syn::Ident>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].ident.clone();
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
// Type parameter should not be considered used by a macro path.
//
// struct TypeMacro<T> {
// mac: T!(),
// marker: PhantomData<T>,
// }
fn visit_mac(&mut self, _mac: &syn::Mac) {}
}
let all_ty_params: HashSet<_> = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.collect();
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
match cont.body {
Body::Enum(ref variants) => {
for variant in variants.iter() {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
visit::walk_ty(&mut visitor, field.ty);
}
}
}
Body::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visit::walk_ty(&mut visitor, field.ty);
}
}
}
let new_predicates = generics
.ty_params
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(
|id| {
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
)
},
);
let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
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(),
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
),
);
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(cont: &Container) -> syn::Ty {
syn::Ty::Path(
None,
syn::Path {
global: false,
segments: vec![
syn::PathSegment {
ident: cont.ident.clone(),
parameters: syn::PathParameters::AngleBracketed(
syn::AngleBracketedParameterData {
lifetimes: cont.generics
.lifetimes
.iter()
.map(|def| def.lifetime.clone())
.collect(),
types: cont.generics
.ty_params
.iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(),
bindings: Vec::new(),
},
),
},
],
},
)
}
File diff suppressed because it is too large Load Diff
+75
View File
@@ -0,0 +1,75 @@
// 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::{Tokens, ToTokens};
pub enum Fragment {
/// Tokens that can be used as an expression.
Expr(Tokens),
/// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens.
Block(Tokens),
}
macro_rules! quote_expr {
($($tt:tt)*) => {
$crate::fragment::Fragment::Expr(quote!($($tt)*))
}
}
macro_rules! quote_block {
($($tt:tt)*) => {
$crate::fragment::Fragment::Block(quote!($($tt)*))
}
}
/// Interpolate a fragment in place of an expression. This involves surrounding
/// Block fragments in curly braces.
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
}
}
}
}
/// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out),
}
}
}
/// Interpolate a fragment as the value part of a `match` expression. This
/// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut Tokens) {
match self.0 {
Fragment::Expr(ref expr) => {
expr.to_tokens(out);
out.append(",");
}
Fragment::Block(ref block) => {
out.append("{");
block.to_tokens(out);
out.append("}");
}
}
}
}
+50 -4
View File
@@ -1,11 +1,56 @@
extern crate proc_macro;
extern crate serde_codegen;
// 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.22")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate serde_derive_internals as internals;
extern crate proc_macro;
use proc_macro::TokenStream;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod ser;
mod de;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_serialize(&input.to_string()) {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match ser::expand_derive_serialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
@@ -13,7 +58,8 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_deserialize(&input.to_string()) {
let input = syn::parse_derive_input(&input.to_string()).unwrap();
match de::expand_derive_deserialize(&input) {
Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg),
}
File diff suppressed because it is too large Load Diff
@@ -1,10 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize`
x: (),
}
fn main() {}
@@ -1,11 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -1,10 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -1,11 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -1,10 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -1,11 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct S {
#[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
x: (),
}
fn main() {}
@@ -1,9 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)] //~ ERROR: custom derive attribute panicked
struct Test<'a> {
s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str
}
fn main() {}
@@ -1,10 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc`
struct A {
x: u32,
}
fn main() { }
@@ -1,10 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
struct C {
#[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc`
x: u32,
}
fn main() { }
@@ -1,10 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked
enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc`
V,
}
fn main() { }
-30
View File
@@ -1,30 +0,0 @@
extern crate compiletest_rs as compiletest;
use std::path::PathBuf;
use std::env::var;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
let cfg_mode = mode.parse().ok().expect("Invalid mode");
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
if let Ok(name) = var::<&str>("TESTNAME") {
let s : String = name.to_owned();
config.filter = Some(s)
}
config.mode = cfg_mode;
config.src_base = PathBuf::from(format!("tests/{}", mode));
compiletest::run_tests(&config);
}
#[test]
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
@@ -1,12 +0,0 @@
#![deny(identity_op)]
#[macro_use]
extern crate serde_derive;
// The derived implementation uses 0+1 to add up the number of fields
// serialized, which Clippy warns about. If the expansion info is registered
// correctly, the Clippy lint is not triggered.
#[derive(Serialize)]
struct A { b: u8 }
fn main() {}
-10
View File
@@ -1,10 +0,0 @@
#![feature(test)]
#[macro_use]
extern crate serde_derive;
extern crate test;
include!("../../testing/tests/test.rs.in");
mod compile_tests;
+19
View File
@@ -0,0 +1,19 @@
[package]
name = "serde_derive_internals"
version = "0.17.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]
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
synom = "0.11"
[badges]
travis-ci = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+144
View File
@@ -0,0 +1,144 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn;
use attr;
use check;
use Ctxt;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
pub body: Body<'a>,
pub generics: &'a syn::Generics,
}
pub enum Body<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
pub ty: &'a syn::Ty,
}
#[derive(Copy, Clone)]
pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
let attrs = attr::Container::from_ast(cx, item);
let mut body = match item.body {
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data, None);
Body::Struct(style, fields)
}
};
match body {
Body::Enum(ref mut variants) => {
for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
}
}
Body::Struct(_, ref mut fields) => {
for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
}
}
}
let item = Container {
ident: item.ident.clone(),
attrs: attrs,
body: body,
generics: &item.generics,
};
check::check(cx, &item);
item
}
}
impl<'a> Body<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Body::Enum(ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Body::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
variants
.iter()
.map(
|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
}
},
)
.collect()
}
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields, attrs))
}
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(
|(i, field)| {
Field {
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field, attrs),
ty: &field.ty,
}
},
)
.collect()
}
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
// 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)]
pub enum RenameRule {
/// Don't apply a default rename rule.
None,
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
CamelCase,
/// Rename direct children to "snake_case" style, as commonly used for fields.
SnakeCase,
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
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(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
for (i, ch) in variant.char_indices() {
if i > 0 && ch.is_uppercase() {
snake.push('_');
}
snake.push(ch.to_ascii_lowercase());
}
snake
}
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 | LowerCase | SnakeCase => field.to_owned(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
for ch in field.chars() {
if ch == '_' {
capitalize = true;
} else if capitalize {
pascal.push(ch.to_ascii_uppercase());
capitalize = false;
} else {
pascal.push(ch);
}
}
pascal
}
CamelCase => {
let pascal = PascalCase.apply_to_field(field);
pascal[..1].to_ascii_lowercase() + &pascal[1..]
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-")
}
}
}
impl FromStr for RenameRule {
type Err = ();
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str {
"lowercase" => Ok(LowerCase),
"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(()),
}
}
}
#[test]
fn rename_variants() {
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in
&[
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
("A", "a", "a", "a", "A", "a", "A"),
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
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, screaming_kebab) in
&[
("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
("a", "A", "a", "A", "a", "A"),
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_field(original), original);
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);
}
}
+152
View File
@@ -0,0 +1,152 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Body, Container, Style};
use attr::Identifier;
use Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
check_getter(cx, cont);
check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.body {
Body::Enum(_) => {
if cont.body.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Body::Struct(_, _) => {
if cont.body.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
);
}
}
}
}
/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.body {
Body::Enum(ref variants) => variants,
Body::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (variant.style, cont.attrs.identifier(), variant.attrs.other()) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) |
(_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true) => {
if i < variants.len() - 1 {
cx.error("#[serde(other)] must be the last variant");
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true) => {
cx.error("#[serde(other)] must be on a unit variant");
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false) => {
if i < variants.len() - 1 {
cx.error(format!("`{}` must be the last variant", variant.ident));
}
}
(_, Identifier::Field, false) => {
cx.error("field_identifier may only contain unit variants");
}
(_, Identifier::Variant, false) => {
cx.error("variant_identifier may only contain unit variants");
}
}
}
}
/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match cont.body {
Body::Enum(ref variants) => variants,
Body::Struct(_, _) => {
return;
}
};
for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]", variant.ident));
}
for (i, field) in variant.fields.iter().enumerate() {
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|ident| format!("`{}`", ident));
if field.attrs.skip_serializing() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident));
}
if field.attrs.skip_serializing_if().is_some() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident));
}
}
}
if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() {
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]", variant.ident));
}
for (i, field) in variant.fields.iter().enumerate() {
if field.attrs.skip_deserializing() {
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|ident| format!("`{}`", ident));
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident));
}
}
}
}
}
@@ -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,13 +16,15 @@ 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> {
+22
View File
@@ -0,0 +1,22 @@
// 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.17.0")]
extern crate syn;
#[macro_use]
extern crate synom;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
mod check;
+12 -5
View File
@@ -1,15 +1,22 @@
[package]
name = "serde_test"
version = "0.8.22"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
version = "1.0.22" # 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/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
serde = { version = "0.8.22", 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" }
+1
View File
@@ -0,0 +1 @@
../LICENSE-APACHE
+1
View File
@@ -0,0 +1 @@
../LICENSE-MIT
+1
View File
@@ -0,0 +1 @@
../README.md
+216 -29
View File
@@ -1,54 +1,241 @@
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);
match T::deserialize(&mut de) {
Ok(v) => assert_eq!(v, *value),
Err(e) => panic!("tokens failed to deserialize: {}", 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());
}
}
+661
View File
@@ -0,0 +1,661 @@
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::{Visitor, EnumAccess, VariantAccess, MapAccess, DeserializeSeed, SeqAccess, Error};
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);
+478 -777
View File
File diff suppressed because it is too large Load Diff
+26 -66
View File
@@ -1,87 +1,47 @@
use std::{error, fmt};
// 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 token::Token;
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
// Shared
Custom(String),
InvalidValue(String),
// De
EndOfStream,
InvalidType(de::Type),
InvalidLength(usize),
UnknownVariant(String),
UnknownField(String),
MissingField(&'static str),
DuplicateField(&'static str),
InvalidName(&'static str),
UnexpectedToken(Token<'static>),
#[derive(Clone, Debug)]
pub struct Error {
msg: String,
}
impl ser::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() }
}
}
impl de::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn end_of_stream() -> Error {
Error::EndOfStream
}
fn invalid_type(ty: de::Type) -> Error {
Error::InvalidType(ty)
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
fn invalid_length(len: usize) -> Error {
Error::InvalidLength(len)
}
fn unknown_variant(variant: &str) -> Error {
Error::UnknownVariant(variant.to_owned())
}
fn unknown_field(field: &str) -> Error {
Error::UnknownField(field.to_owned())
}
fn missing_field(field: &'static str) -> Error {
Error::MissingField(field)
}
fn duplicate_field(field: &'static str) -> Error {
Error::DuplicateField(field)
fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() }
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(&self.msg)
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Error"
}
fn cause(&self) -> Option<&error::Error> {
None
&self.msg
}
}
impl PartialEq<str> for Error {
fn eq(&self, other: &str) -> bool {
self.msg == other
}
}
+185 -17
View File
@@ -1,22 +1,190 @@
// 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 immitation 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.22")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
missing_docs_in_private_items,
stutter,
use_debug,
use_self,
))]
#[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;
+417 -269
View File
@@ -1,323 +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::{
self,
Serialize,
};
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<'a, I> ser::Serializer for 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 MapState = ();
type SeqState = ();
type TupleState = ();
type TupleStructState = ();
type TupleVariantState = ();
type StructState = ();
type StructVariantState = ();
fn serialize_unit(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Variant<'s, 'a>;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Variant<'s, 'a>;
fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_next_token!(self, Bool(v));
Ok(())
}
fn serialize_newtype_variant<T>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_unit_struct(&mut self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_next_token!(self, I8(v));
Ok(())
}
fn serialize_unit_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_next_token!(self, I16(v));
Ok(())
}
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_next_token!(self, I32(v));
Ok(())
}
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_next_token!(self, I64(v));
Ok(())
}
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_next_token!(self, U8(v));
Ok(())
}
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_next_token!(self, U16(v));
Ok(())
}
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_next_token!(self, U32(v));
Ok(())
}
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_next_token!(self, U64(v));
Ok(())
}
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_next_token!(self, F32(v));
Ok(())
}
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_next_token!(self, F64(v));
Ok(())
}
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
fn serialize_char(self, v: char) -> Result<(), Error> {
assert_next_token!(self, Char(v));
Ok(())
}
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn serialize_char(&mut self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn serialize_str(&mut self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn serialize_none(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
where V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq<'b>(&'b mut self, len: Option<usize>) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
Ok(())
}
fn serialize_seq_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn serialize_seq_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn serialize_seq_fixed_size(&mut self, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
Ok(())
}
fn serialize_tuple(&mut self, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
}
fn serialize_tuple_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
}
fn serialize_tuple_struct(&mut self, name: &'static str, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
Ok(())
}
fn serialize_tuple_struct_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self)
}
fn serialize_tuple_struct_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
fn serialize_tuple_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
Ok(())
}
fn serialize_tuple_variant_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(self)
}
fn serialize_tuple_variant_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
fn serialize_map(&mut self, len: Option<usize>) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
Ok(())
}
fn serialize_map_key<T>(&mut self, _: &mut (), key: T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(self)
}
fn serialize_map_value<T>(&mut self, _: &mut (), value: T) -> Result<(), Self::Error> where T: Serialize {
value.serialize(self)
}
fn serialize_map_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
fn serialize_struct(&mut self, name: &str, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
Ok(())
}
fn serialize_struct_elt<V>(&mut self, _: &mut (), key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
fn serialize_struct_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
Ok(())
}
fn serialize_struct_variant_elt<V>(&mut self, _: &mut (), key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
let mut state = try!(self.serialize_seq(Some(value.len())));
for c in value {
try!(self.serialize_seq_elt(&mut state, c));
fn serialize_str(self, v: &str) -> Result<(), Error> {
match self.tokens.first() {
Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
Some(&Token::String(_)) => assert_next_token!(self, String(v)),
_ => assert_next_token!(self, Str(v)),
}
self.serialize_seq_end(state)
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
match self.tokens.first() {
Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
_ => assert_next_token!(self, Bytes(v)),
}
Ok(())
}
fn serialize_unit(self) -> Result<(), Error> {
assert_next_token!(self, Unit);
Ok(())
}
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
assert_next_token!(self, UnitStruct { name });
Ok(())
}
fn serialize_unit_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<(), Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
assert_next_token!(self, Unit);
} else {
assert_next_token!(self, UnitVariant { name, variant });
}
Ok(())
}
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
assert_next_token!(self, NewtypeStruct { name });
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<(), Error>
where
T: Serialize,
{
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
} else {
assert_next_token!(self, NewtypeVariant { name, variant });
}
value.serialize(self)
}
fn serialize_none(self) -> Result<(), Error> {
assert_next_token!(self, None);
Ok(())
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
assert_next_token!(self, Some);
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_next_token!(self, Seq { len });
Ok(self)
}
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_next_token!(self, Tuple { len });
Ok(self)
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_next_token!(self, TupleStruct { name, len });
Ok(self)
}
fn serialize_tuple_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Seq { len });
Ok(Variant {
ser: self,
end: Token::SeqEnd,
})
} else {
assert_next_token!(self, TupleVariant { name, variant, len });
Ok(Variant {
ser: self,
end: Token::TupleVariantEnd,
})
}
}
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
assert_next_token!(self, Map { len });
Ok(self)
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_next_token!(self, Struct { name, len });
Ok(self)
}
fn serialize_struct_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Error> {
if self.tokens.first() == Some(&Token::Enum { name: name }) {
self.next_token();
assert_next_token!(self, Str(variant));
let len = Some(len);
assert_next_token!(self, Map { len });
Ok(Variant {
ser: self,
end: Token::MapEnd,
})
} else {
assert_next_token!(self, StructVariant { name, variant, len });
Ok(Variant {
ser: self,
end: Token::StructVariantEnd,
})
}
}
fn is_human_readable(&self) -> bool {
panic!(
"Types which have different human-readable and compact representations \
must explicitly mark their test cases with `serde_test::Configure`"
);
}
}
pub struct Variant<'s, 'a: 's> {
ser: &'s mut Serializer<'a>,
end: Token,
}
impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, SeqEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, TupleEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Error> {
assert_next_token!(self, TupleStructEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Error> {
match self.end {
Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
_ => unreachable!(),
}
Ok(())
}
}
impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
key.serialize(&mut **self)
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_next_token!(self, MapEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
try!(key.serialize(&mut **self));
value.serialize(&mut **self)
}
fn end(self) -> Result<(), Self::Error> {
assert_next_token!(self, StructEnd);
Ok(())
}
}
impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error>
where
T: Serialize,
{
try!(key.serialize(&mut *self.ser));
value.serialize(&mut *self.ser)
}
fn end(self) -> Result<(), Self::Error> {
match self.end {
Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
Token::MapEnd => assert_next_token!(self.ser, MapEnd),
_ => unreachable!(),
}
Ok(())
}
}
+536 -30
View File
@@ -1,60 +1,566 @@
#[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),
Isize(isize),
/// 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),
Usize(usize),
/// 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]),
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.
///
/// When testing deserialization, the `len` field must match the number of
/// fields that the struct expects to deserialize. This may be different
/// from the number of fields contained in the input tokens.
///
/// After this header are the fields of the struct, followed by `StructEnd`.
///
/// ```rust
/// # #[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.
///
/// When testing deserialization, the `len` field must match the number of
/// fields that the struct variant expects to deserialize. This may be
/// different from the number of fields contained in the input tokens.
///
/// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`.
///
/// ```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)
}
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "serde_test_suite"
version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
publish = false
[features]
unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive" }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.3", optional = true }
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
+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. ===]
#![====================================================*/)]
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "serde_derive_tests_no_std"
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]
+61
View File
@@ -0,0 +1,61 @@
// 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
}
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {}
#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32) -> ! {
unsafe {
libc::abort()
}
}
//////////////////////////////////////////////////////////////////////////////
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)]
struct Unit;
#[derive(Serialize, Deserialize)]
struct Newtype(u8);
#[derive(Serialize, Deserialize)]
struct Tuple(u8, u8);
#[derive(Serialize, Deserialize)]
struct Struct { f: u8 }
#[derive(Serialize, Deserialize)]
enum Enum {
Unit,
Newtype(u8),
Tuple(u8, u8),
Struct { f: u8 },
}
@@ -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() {}

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